CPP 16. String类和标准模板库 2020-12-03 浏览量 746 暂无评论 # 第16章 String类和标准模板库 - 标准C++ string类 - 模板auto_prt, unique_ptr, shared_ptr--智能指针 - 标准模板库(STL)--泛型编程 - 容器类 - 迭代器 - 函数对象(functor) - STL算法 - 模板initializer_list ## 16.1 string类 ### 16.1.1 构造字符串 ### 16.1.2 string类输入 C-风格字符串 ```cpp char info[100]; cin >> info; cin.getline(info, 100); // discard \n cin.get(info, 100); // leave \n in queue ``` string对象 ```cpp string stuff; cin >> stuff; - 不断读取,直到遇到使isspace()为true的空白字符并将其留在输入队列中 getline(cin, stuff); ``` 两个版本的getline()都有一个可选参数,用于指定使用哪个字符来确定输入的边界; ```cpp cin.getline(info, 100, ':'); getline(info, ':'); // 自动调整目标string对象的大小 - 到达文件尾,设置输入流的eofbit,fail()和eof()都将返回true - 遇到分解字符(默认为\n) - 读取的字符数达到最大允许值,设置输入流的failbit,fail()返回true ``` ### 16.1.3 使用字符串 1. 6个关系运算符 2. 长度,size(), length() 3. 搜索,find(), rfind(), find_first_of(), find_last_of(), find_first_not_of(), find_last_not_of() ```cpp size_type find(const string & str, size_type pos = 0) const size_type find(const char * s, size_type pos = 0) const size_type find(const char * s, size_type pos = 0, size_type n) size_type find(char ch, size_type pos = 0) const ``` 4. 删除 5. 替换 6. 插入 7. 当前分配给字符串的内存块的大小,capacity() 8. 请求内存块的最小长度,reserve() 9. 指向C-风格字符串的指针,c_str() ## 16.2 智能指针模板类 思想:定义类似指针的对象,当智能指针过期时,其析构函数将使用delete来释放内存。 有:auto_ptr, unique_ptr, shared_ptr,后两个是C++11的,摒弃了第一个,因为auto_ptr可能会出现所有权丢失的问题:当使用auto_ptr指向已有auto_ptr时,原来的所有权就会丢失。 ```cpp #include void remodel(std::string & str) { std::auto_prt ps (new std::string(str)) if (weird_thing()) throw exception(); str = *ps; return; } // 所有权丢失,好处:防止删除一个对象两次,坏处:无法再使用p1 auto_ptr p1 (new string("auto")); auto_ptr p2; p2 = p1; // 当把auto_ptr换成shared_ptr时,不会丢失所有权,而是将引用次数加1 // 当把auto_ptr换成unique_ptr时,p2 = p1将非法 ``` ## 16.3 标准模板库 ### 16.3.1 模板类vector 容器、迭代器 ```cpp vector scores; vector::iterator pd; // auto pd = scores.begin(); 更简洁 pd = scores.begin(); *pd = 22.3; ++pd; for (pd = scores.begin(); pd != scores.end(); pd++) cout << *pd << endl; // 一些方法 push_back(): 将元素添加到元素末尾 erase(): 删除矢量中给定区间的元素,左闭右开 insert(): 向一个容器的某个位置插入另一个容易对象的某个区间元素 vector old_v; vector new_v; old_v.insert(old_v.begin(), new_v.begin() + 1, new_v.end()); ``` STL函数 ```cpp for_each(): 将被指向的函数应用于容器区间中的各个元素,很像python的map呀 random_shuffle(): 随机排列容器区间中的元素 sort(): 两个版本 一个默认使用为存储在容器中的类型元素定义的<运算符,升序 如果容器是用户定义的,则需要提供成员或非成员函数operator<() 另一个版本接受三个参数,前两个同上,为区间,第三个为自定义的排序规则函数名称,返回值为bool ``` ### 16.3.2 基于范围的for循环(C++11) ```cpp double prices[3] = {4.55, 234.3, 23.3}; for (double x : prices) // 括号内的代码声明一个类型与容器存储的内容相同的变量 cout << x << std::endl; for_each(books.begin(), bookd.end(), ShowReview); 类似于 for (auto x : books) ShowReview(x); 但是基于范围的for循环可以修改容器的内容,只要指定一个引用参数 void InflateReview(Review &r){r.rating++;} for (auto x : books) InflateReview(x); ``` ## 16.4 泛型编程 面向对象编程关注编程的数据方面,而泛型编程关注的是算法,都是抽象和创建可重用代码。 模板使得算法独立于存储的数据类型,迭代器使算法独立于使用的容器类型。 ### 16.4.1 迭代器的基本特征 1. 可对迭代器执行解除引用操作,即定义*p; 2. 可将一个迭代器赋给另一个,即定义p=q; 3. 可比较迭代器,即定义p==q,p!=q; 4. 可通过迭代器遍历容器中的所有元素,即定义++p和p++。 **5种迭代器:** 输入迭代器:读取,单向,可以递增,但不能倒退,每次迭代的顺序不一定相同 输出迭代器:只写,单向 正向迭代器:读写,总是按相同的顺序遍历一系列值,使用++运算符 双向迭代器:具有正向迭代器的所有特性,还可-- 随机访问迭代器:具有双向迭代器的所有特性,还可使用a[10] ```cpp typedef double * iterator; iterator find_ar(iterator begin, iterator end, const double & val) { iterator ar; for (ar = begin; ar != end; ar++) if (*ar == val) return ar; return end; } ``` 容器有一些基本的特征和要求。 下面就是一些容器类型和用法。 1. vector,强调快速访问 2. deque,双端队列 3. list,强调快速插入和删除,它表示双向链表 4. list工具箱 5. forward_list 6. queue,适配器类 7. priority_queue,适配器类,与queue的区别在于,它将最大的元素移到队首 8. stack,适配器类 9. array,不是STL容器,因为它的长度是固定的 **关联容器:基于树结构** 1. set,可翻转,经过排序 2. multiset, 3. map, 4. multimap,与set类似,但键和值的类型不同,且同一个键可能与多个值相关联 ```cpp #include #include typedef int KeyType; typedef std::pair Pair; typedef std::multimap MapCode; int main() { using namespace std; MapCode codes; codes.insert(Pair(415, "Beijing")); codes.insert(Pair(110, "Nanjing")); // Number of cities with area code 415 codes.count(415) MapCode::iterator it; for (it = codes.begin(); it != codes.end(); ++it) cout << " " << (*it).first << " " << (*it).second << endl; pair range = codes.equal_range(110); for (it = range.first; it != range.second; ++it) cout << (*it).second << endl; return 0; } ``` 无序关联容器:基于哈希表 ## 16.5 函数对象 函数对象,也叫函数符(functor),包括**函数名、指向函数的指针和重载了()运算符的类对象**,它们都可以以函数方式与()结合使用。 STL通过模板解决for_each处理容器中不同类型数据的问题。 ```cpp template // 这就是为什么for_each无法修改 Function for_each(InputIterator first, InputIterator last, Function f); ``` 头文件functional定义了多个模板类函数对象 ![](http://lcipm.com/Jineng/picture-bed/uploads/5b0696531040b6fc657bbffe1a54f9c9/20201201223350.png) **自适应函数符和函数适配器** 自适应生成器、自适应一元函数、自适应二元函数、自适应谓词、自适应二元谓词 假设有一个自适应二元函数对象f2(),则可以创建一个binder1st对象,使之与第一个参数相关联 ```cpp binder1st(f2, val) f1; 这样,使用f1(x)时等价于f2(val, x) 简化版:不需要f2为自适应函数 bind1st(multiplies(), 2.5) ``` ## 16.6 算法 ### 16.6.1 算法组 STL将算法库分成4组: 头文件algorithm - 非修改式序列操作; - 修改式序列操作; - 排序和相关操作; 头文件numeric - 通用数字运算。 就地算法(in-place algorithm):sort() 复制算法(copying algorithm):copy() transform()可以以这两种方式完成工作。 ## 16.7 其他库 vector, valarray, array initializer_list vector是一个容器类和算法系统的一部分,valarray更适合于数组计算,array为替代内置数组而设计,提供更好、更安全的接口,让数组更紧凑、效率更高。 赞赏 微信支付 支付宝支付