zoukankan      html  css  js  c++  java
  • 顺序容器2(用法)

    顺序容器类型:

    vector    可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢

    deque    双端队列。支持快速随机访问。在头尾位置插入/删除速度很快

    list       双向列表。只支持双向顺序访问。在 list 中任何位置进行插入/删除操作速度都很快

    forward_list   单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作都很快

    array      固定大小数组。支持快速随机访问。不能添加或删除元素

    string     与 vector 相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度很快

    容器操作(后面再提具体每个容器操作对元素的其他限制):

    类型别名

    iterator      此容器的迭代器类型

    const_iterator      可以读取元素,但不能修改元素的迭代器类型

    size_type       无符号整数类型,足够保存此种容器类型最大可能容器大小

    difference_type   带符号整数类型,足够保存两个迭代器之间的距离

    value_type     元素类型

    reference       元素的左值类型,与 value_type& 含义相同

    const_reference  元素的 const 左值类型,即 const value_type&

    构造函数

    C c;        默认构造函数,构造空容器

    C c1(c2);     构造 c2 的拷贝 c1

    C c(b, e);     构造 c,将迭代器 b 到 e 指定的范围内的元素拷贝到 c(array 不支持)

    C c{a, b, c, d...}   列表初始化 c

    赋值与 swap

    c1 = c2;       将 c1 中的元素替换为 c2 中的元素

    c1 = {a, b, c, d...}   将 c1 中的元素替换为列表中元素(不适用于 array)

    a.swap(b);      交换 a 和 b 的元素

    swap(a, b);     等价于 a.swap(b)

    大小

    c.size();       c 中元素的数目(不支持 forward_list)

    c.max_size();   c 中可保存的最大数目的元素数目

    c.empty();      若 c 中存储了元素,返回 false,否则返回 true

    添加/删除元素(不适用于 array)

    注:在不同容器中,这些操作的接口都不同

    c.insert(args);   将 args 中的元素拷贝进 c

    c.emplace(inits); 使用 inits 构造 c 中的一个元素

    c.erase(args);   删除 args 指定的元素

    c.clear();      删除 c 中所有元素,返回 void

    关系运算符

    ==,!=      所有容器都支持

    <,<=,>,>=    关系运算(无序关联容器不支持)

    获取迭代器

    c.begin(),c.end()  返回 c 的首元素和尾元素之后位置的迭代器

    c.cbegin(),c.cend() 返回 const_iterator

    反向容器的额外成员(不支持 forward_list)

    reverse_iterator       按逆序寻址元素的迭代器

    const_reverse_iterator 不能修改元素的逆序迭代器

    c.rbegin(),c.rend()      返回指向 c 尾元素和首元素之前位置的迭代器

    c.crbegin(),c.crend()   返回 const_reverse_iterator

    虽然我们可以在容器中保存几乎任何类型,但某些容器操作对元素类型有自己的特殊要求。我们可以为不支持特定操作需求的类型定义容器,但这种情况下就只能使用那些没有特殊要求的容器操作了:

     1 #include <iostream>
     2 #include <vector>
     3 using namespace std;
     4 
     5 class no_default{//no_default 是一个没有默认构造函数的类型
     6     int x;
     7 public:
     8     no_default(int a) : x(a){}
     9     ~no_default(){}
    10 };
    11 
    12 int main(void){
    13     int init = 1;
    14     std::vector<no_default> v1(10, init);//正确,提供了元素初始化器(执行结果是v1中有10个1)
    15     // std::vector<no_default> v2(10);//错误,必须提供一个元素初始化器
    16     return 0;
    17 }
    View Code

    begin 和 end 成员:

     1 #include <iostream>
     2 #include <list>
     3 using namespace std;
     4 
     5 int main(void){
     6     list<string> a = {"Milton", "Shakespeare", "Austen"};
     7     auto it1 = a.begin(); //list<string>::iterator
     8     auto it2 = a.rbegin();//list<string>::reverse_iterator
     9     auto it3 = a.cbegin();//list<string>::const_iterator
    10     auto it4 = a.crbegin();//list<string>::const_reverse_iterator
    11 
    12     cout << *it1 << endl;//Milton
    13     it1++;
    14     cout << *it1 << endl;//Shakespeare
    15     *it1 = "jflsfk";
    16     cout << *it1 << endl;//jflsfk
    17     cout << endl;
    18 
    19     cout << *it2 << endl;//Austen
    20     it2++;
    21     cout << *it2 << endl;//jflsfk
    22     *it2 = "Shakespeare";
    23     cout << *it2 << endl;//Shakespeare
    24     cout << endl;
    25 
    26     cout << *it3 << endl;//Milton
    27     it3++;
    28     cout << *it3 << endl;//Shakespeare
    29     // *it3 = "hello";//错误,常量迭代器类似于具有底层const的指针
    30     cout << endl;
    31 
    32     cout << *it4 << endl;//Austen
    33     it4++;
    34     cout << *it4 << endl;//Shakespeare
    35     // *it4 = "hello";//错误,常量迭代器类似于具有底层const的指针
    36     cout << endl;
    37 
    38     const list<string> b = {"hello", "gg", "yy"};
    39     auto it5 = b.begin();
    40     auto it6 = b.rbegin();
    41     auto it7 = b.cbegin();
    42     auto it8 = b.crbegin();
    43 
    44     cout << *it5 << endl;//hello
    45     it5++;
    46     cout << *it5 << endl;//gg
    47     // *it5 = "aa";//错误,const对象的begin()返回的是一个const_iterator
    48 
    49     // b = a;//错误
    50 
    51     list<string> const c = {"hello", "gg", "yy"};//可以将list<string>看作int,那么b和c分别相当于const int 和 int const,是等价的,都是顶层const
    52 
    53     // c = a;//错误
    54 
    55     return 0;
    56 }
    View Code

    通过上面的列子还可以发现不以 c 开头的函数都是被重载过的。也就是说,实际上有两个名为 begin 的成员。一个是 const 成员,返回容器的 const_iterator 类型。另一个是非常量成员,返回容器的 iterator 类型。rbegin,end,rend 的情况类型。当我们对一个非常量成员调用这些成员时,返回的是 const 版本。只有在对一个 const 对象调用这些函数时,才会得到一个 const 版本。与 const 指针和引用类似,可以将一个普通的 iterator 转换成对应的 const_iterator,反之则不行。

    而以 c 开头版本是 c++11 标准引入的,用以支持 auto 与 begin 和 end 函数结合使用。无论对常量容器还是非常量容器,其返回的都是 const_iterator。

    即 auto 与 begin 或 end 结合时,获得的迭代器类型依赖于容器类型,而以 c 开头的版本是可以获得 const_iterator 的,无论容器的类型是否为 const。

    将一个容器初始化为另一个容器的拷贝:

     1 #include <iostream>
     2 #include <list>
     3 #include <vector>
     4 #include <deque>
     5 #include <forward_list>
     6 using namespace std;
     7 
     8 int main(void){
     9     list<string> authors = {"Milton", "Shakespeare", "Austen"};//列表初始化
    10     vector<const char*> gel = {"a", "an", "the"};//列表初始化
    11 
    12     list<string> list1(authors);//正确,类型都匹配
    13     // deque<string> a(authors);//错误,容器类型不匹配
    14     // vector<string> v(gel);//错误,元素类型不匹配
    15 
    16     forward_list<string> f(gel.begin(), gel.end());//正确,只元素能相互转化即可
    17 
    18     return 0;
    19 }
    View Code

    为了创建一个容器为另一个容器的拷贝,两个容器的类型及其元素类型必须匹配。不过,当传递迭代器参数来拷贝一个范围时,就不要求容器类型是相同的了。而且,新容器和原容器中的元素也可以不同,只要能将拷贝的元素转换为要初始化的容器元素类型即可。

    标准库 array:

     1 #include <iostream>
     2 #include <array>
     3 using namespace std;
     4 
     5 int main(void){
     6     array<int, 10> a;//类型为保存10个int的数组
     7     array<string, 10> b;//类型为保存10个string的数组
     8 
     9     array<int, 10>::size_type i;//数组类型包括元素类型和大小
    10     // array<int>::size_type j;//错误,array<int>不是一个类型
    11 
    12     array<int, 3> c = {1, 2, 3};//列表初始化
    13     array<int, 5> d = {1};//d[0]为1,剩余元素都为0
    14     //这两点和内置数组是一样的
    15 
    16     int e[5] = {1, 2, 3, 4, 5};
    17     // int cpy[5] = e;//错误,内置数组不支持拷贝或赋值
    18     array<int, 5> f = {1, 2, 3, 4, 5};
    19     array<int, 5> copy = f;//正确,只要数组类型匹配即合法
    20     // copy = e;//错误,内置数组不能被赋值给array
    21     // array<int, 4> g = f;//错误,数组大小不一致
    22 
    23     return 0;
    24 }
    View Code

    定义以及使用 array 类型时必须指定容器的元素类型和大小

    数组类型包含元素的类型和大小,因此拷贝初始化时不仅要求初始值的类型必须与要创建的容器相同,大小也要相同

    array 的列表初始化规则和内置数组一致

    assign:

     1 #include <iostream>
     2 #include <list>
     3 #include <vector>
     4 using namespace std;
     5 
     6 int main(void){
     7     list<string> names;
     8     vector<const char*> old_style;
     9     // names = old_style;//错误,容器类型不匹配不能赋值
    10     names.assign(old_style.cbegin(), old_style.cend());//正确,可以将const char*转化成string
    11 
    12     list<string> a(1);//一个元素,为空string
    13     a.assign(10, "hello");//10个元素,每个都是hello
    14     for(const auto indx : a){
    15         cout << indx << " ";
    16     }
    17     cout << endl;
    18 
    19     a.clear();
    20     a.insert(a.begin(), 10, "hello");//通过输出可以发现这两条语句与前面的两条语句等效
    21     for(const auto indx : a){
    22         cout << indx << " ";
    23     }
    24     cout << endl;
    25     return 0;
    26 }
    View Code

    赋值运算符要求左边和右边的运算对象具有相同的类型。此外顺序容器(array除外)还定义了一个名为 assign 的成员,允许我们从一个不同但相容的类型赋值,或从容器的一个子序列赋值。

    需要注意的是:赋值相关运算会导致指向左边容器内部的迭代器、引用和指针失效。

    swap:

     1 #include <iostream>
     2 #include <vector>
     3 using namespace std;
     4 
     5 int main(void){
     6     std::vector<string> v1(10, "f");
     7     std::vector<string> v2(24, "a");
     8     auto it = v1.begin();//此时it指向v1的第一个元素,是f
     9     cout << &it << endl;//0x6afeb8
    10 
    11     swap(v1, v2);
    12 
    13     cout << *it << endl;//f
    14     cout << &it << endl;//0x6afeb8
    15     
    16     for(const auto indx : v1){//输出24个a
    17         cout << indx << endl;
    18     }
    19     cout << endl;
    20     for(const auto indx : v2){//输出10个f
    21         cout << indx << endl;
    22     }
    23     return 0;
    24 }
    View Code

    除 array 外,swap 不会对任何元素进行拷贝、删除或插入操作,因此可以保证在常数时间内完成。元素不会被移动也意味着,除 string 外,指向容器的迭代器、引用和指针在 swap 操作之后都不会失效。它们任指向 swap 操作之前所指向的那些元素,但是这些元素已经不属于原来的容器了。

    insert:

    注意:只有 vector、deque、list、string 支持 insert 成员

     1 #include <iostream>
     2 #include <list>
     3 #include <vector>
     4 using namespace std;
     5 
     6 int main(void){
     7     vector<string> a;
     8     list<string> b;
     9 
    10     //在指定位置之前插入某个元素
    11     b.insert(b.begin(), "hello");//等价于b.push_front("hello");
    12     a.insert(a.begin(), "hello");//vector不支持push_front,但我们通过insert达到了同样的效果
    13 
    14     //在指定位置之前插入范围内元素
    15     vector<string> v = {"kjf", "fksl", "fjsl", "fls"};
    16     b.insert(b.begin(), v.end() - 2, v.end());//将v中最后两个元素插入到b的开始位置
    17     b.insert(b.end(), {"fjksl", "fskl", "fsl"});//在b的末尾插入一个列表
    18 
    19     list<string> c;
    20     auto it = c.begin();
    21     string s;
    22     while(cin >> s){
    23         it = c.insert(it, s);//返回插入元素的迭代器
    24     }
    25     return 0;
    26 }
    View Code

    需要注意的是:向一个 vector、string 或 deque 插入元素会使原来的迭代器、引用和指针失效。

    emplace:

     1 #include <iostream>
     2 #include <vector>
     3 using namespace std;
     4 
     5 class gel{
     6 friend ostream& operator<<(ostream&, const gel&);
     7 
     8 private:
     9     int x, y, z;
    10 
    11 public:
    12     gel(int a, int b, int c) : x(a), y(b), z(c){}
    13     ~gel(){}
    14 };
    15 
    16 ostream& operator<<(ostream &os, const gel &it){
    17     os << it.x << " " << it.y << " " << it.z;
    18     return os;
    19 }
    20 
    21 int main(void){
    22     vector<gel> a;
    23     a.emplace_back(1, 2, 3);//隐式使用了构造函数
    24     // a.push_back(1, 2, 3);//错误,没有接受3个参数的push_back版本
    25     a.push_back(gel(2, 3, 4));//创建一个临时的gel对象传递给push_back
    26 
    27     // a.emplace_back();//错误,gel类没有默认构造函数
    28     a.emplace(a.begin(), 1, 2, 3);//将gel(1, 2, 3)插入到a的首元素前
    29 
    30     for(const auto indx : a){
    31         cout << indx << endl;
    32     }
    33     return 0;
    34 }
    View Code

    c++11标准引入了三个新成员——emplace_front、emplace 和 emplace_back,这些操作构造而不是拷贝元素。这些操作分别对应 push_back、insert 和 push_back。

    注意:emplace 函数在容器中直接构造元素。传递给 emplace 函数的参数必须与元素类型的构造函数匹配。

    访问元素:

    c.back()    返回 c 中尾元素的引用(左值)。若 c 为空,函数行为未定义

    c.front()    返回 c 中首元素的引用(左值)。若 c 为空,函数行为未定义

    c[n]      返回 c 中下标为 n 的元素引用,n 是一个无符号整数

    c.at(n)       返回下标为 n 的元素引用。如果下标越界,则抛出 out_of_range 异常

    注意:at 和下标访问只适用于 string、vector、deque 和 array。back 不适用于 forward_list。

    删除元素:

    c.pop_back()      删除 c 中尾元素。若 c 为空,则函数的行为未定义。返回 void

    c.pop_front()      删除 c 中首元素。若 c 为空,则函数的行为未定义。返回 void

    c.erase(p)        删除迭代器 p 所指定的元素,返回一个指向被删元素之后元素的迭代器。若 p 是尾后迭代器,则行为未定义。

    c.erase(b, e)         删除迭代器 b 和 e 之间所指定范围(左闭右开)内的元素。返回一个指向最后一个被删除元素之后元素的迭代器,若 e 本身就是尾后迭代器,则函数也返回尾后迭代器。

    c.clear()        删除 c 中的所有元素。返回 void

    注意:这些操作会改变容器的大小,所以不适用于 array。forward_list 有特殊版本的 erase。forward_list 不支持 pop_back。vector 和 string 不支持 pop_front。

    删除 deque 中除首尾位置之外的任何元素都会使所有迭代器、引用和指针失效。指向 vector 或 string 中删除点之后位置的迭代器、引用和指针都会失效。

    特殊的 forward_list 操作:

    lst.before_begin()    返回指向链表首元素之前不存在的元素的迭代器。此迭代器不能解引用

    lst.cbefore_begin()     cbefore_begin() 返回一个 const_iterator,同样不能解引用

    lst.insert_after(p, t)     在迭代器 p 之后的位置插入元素 t

    lst.insert_after(p, n, t)    在迭代器 p 之后的位置插入 n 个元素 t

    lst.insert_after(p, b, e)   b 和  e 是一对范围迭代器(不能指向 lst 内),在迭代器 p 后插入迭代器 [b, e) 之间的元素

    lst.insert_after(p, il)     il 是一个花括号列表。返回一个指向最后一个插入元素的迭代器。如果范围为空,则返回 p。若 p 为尾后迭代器,则行为为定义

    emplace_after(a, args)  使用 args 在 p 指定的位置之后创建一个元素。返回一个指向这个新元素的迭代器。若 p 为尾后迭代器,则行为未定义

    lst.erase_after(p)      删除 p 指向的位置之后的元素,若 p 指向尾元素或者为尾后迭代器,则函数行为未定义。返回尾后迭代器

    lst.erase_after(b, e)    b, e 为一对范围迭代器,删除 [b, e) 之间的元素。返回一个指向被删元素之后的迭代器。若不存在这样的元素,则返回尾后迭代器

     1 #include <iostream>
     2 #include <forward_list>
     3 using namespace std;
     4 
     5 int main(void){
     6     forward_list<int> f = {1, 2, 3, 4, 4, 5, 6, 6, 7};
     7     auto a = f.before_begin();
     8     auto b = f.begin();
     9     f.insert_after(a, 100);
    10     cout << *b << endl;//输出1,向链表中插入元素,原来的指针不会失效
    11     
    12     auto c = f.begin();
    13     cout << *c << endl;//100
    14     auto d = f.erase_after(c);//删除c之后的元素并返回删除元素之后的迭代器
    15     cout << *d << endl;//2
    16 
    17     for(const auto indx : f){
    18         cout << indx << " ";
    19     }
    20     cout << endl;
    21 
    22     auto e = f.erase_after(f.begin(), ++(++f.begin()));
    23     while(e != f.end()){
    24         cout << *e << " ";
    25         e++;
    26     }
    27     cout << endl;
    28     return 0;
    29 }
    View Code

    改变容器大小(resize):

     1 #include <iostream>
     2 #include <list>
     3 using namespace std;
     4 
     5 class gel{
     6 private:
     7     int x, y, z;
     8 
     9 public:
    10     gel(int a, int b, int c) : x(a), y(b), z(c){}
    11     ~gel(){}
    12     
    13 };
    14 
    15 int main(void){
    16     list<int> l(10, 1024);
    17     l.resize(15);//将5个值为0的元素添加到l的末尾,此时l的大小为15
    18     l.resize(25, -1);//将10个值为-1的元素添加到l的末尾,此时l的大小为25
    19     l.resize(5);//从l的末尾删除20个元素,此时指向末尾20个元素的迭代器,指针和引用全部失效
    20 
    21     list<gel> l2(10, gel(1, 2, 3));
    22     l2.resize(15, gel(1, 2, 3));
    23     // l2.resize(5);//错误,gel没有默认构造函数
    24     return 0;
    25 }
    View Code

    注意:array 不支持 resize

    对于没有默认构造函数的数据类型不能使用一个参数版本的 resize

    如果 resize 缩小容器,则指向被删除元素的迭代器、引用和指针都会失效

    管理容量的成员函数:

    c.shrink_to_fit()    将 capacity() 减少为与 size() 大小相同,即将多余的内存释放回系统

    c.capacity()        返回 c 当前的容量大小

    c.reserve(n)       分配至少能容纳 n 个元素的内存空间

    其中:shrink_to_fit 只适用于 vector、string 和 deque

    capacity 和 reserve 只适用于 vector 和 string

     1 #include <iostream>
     2 #include <list>
     3 #include <vector>
     4 using namespace std;
     5 
     6 int main(void){
     7     vector<int> a(10, 2);
     8     cout << a.size() << endl;//10
     9     cout << a.capacity() << endl;//10
    10 
    11     a.push_back(1);
    12     cout << a.size() << endl;//11
    13     cout << a.capacity() << endl;//20
    14     cout << endl;
    15 
    16     a.push_back(1);
    17     cout << a.size() << endl;//12
    18     cout << a.capacity() << endl;//20 size没有超过capacity时系统不会重新分配内存
    19 
    20     for(int i = 1; i < 10; i++){
    21         a.push_back(i);
    22     }
    23     cout << a.size() << endl;//21
    24     cout << a.capacity() << endl;//40
    25     cout << endl;
    26 
    27     for(int i = 0; i < 20; i++){
    28         a.push_back(i);
    29     }
    30     cout << a.size() << endl;//41
    31     cout << a.capacity() << endl;//80    
    32     cout << endl;
    33 
    34     //只有当前空间小于用reserve分配的空间大小时才会按照我们指定的大小重新分配内存空间
    35     a.reserve(10);
    36     cout << a.capacity() << endl;//80
    37     a.reserve(100);
    38     cout << a.capacity() << endl;//100
    39     cout << endl;
    40 
    41     //使用shrink_to_fit函数将多余的空间退回给系统
    42     a.shrink_to_fit();
    43     cout << a.size() << endl;//41
    44     cout << a.capacity() << endl;//41
    45     return 0;
    46 }
    View Code

    注意:重新分配内存时会引起迭代器、指针和引用失效

    只有当需求的内存空间大于当前容量时,reserve 才会改变 vector 的容量大小

    reserve 和 resize 的区别是 reserve 不改变容器中元素的数量,仅影响预先分配多大的内存空间,而 resize 恰好相反

    构造 string 的方法:

    string s(cp)     其中 cp 是一个 char* 字符,且其必须以空字符结尾

    string s(cp, n)      此时 cp 不必以空字符结尾,但是 n 必须不大于 cp 的长度,否则该行为是未定义的

    string s(cp + a, b)   从 cp[a] 开始拷贝 b 个字符构造 s,注意不能越界

    string s(s2, pos)     从 s2[pos] 开发拷贝到 s2 结束,若 pos 大于 s2 的大小,则抛出一个 out_of_range 异常

    string s(s2, pos, len) 从 s2[pos] 开始拷贝 len 个字符构造 s

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(void){
     5      const char *cp = "hello world!";//以空字符结束的数组
     6      char a[] = {'H', 'i'};//不是以空字符结束
     7      
     8      string s1(cp);//拷贝cp中的字符直到遇到空字符
     9      cout << s1 << endl;//hello woeld!
    10      cout << endl;
    11      
    12      string s2(a);//未定义,a不是以空字符结尾
    13      cout << s2 << endl;//乱码
    14      cout.clear(ios::goodbit);
    15      
    16      cout << endl;
    17      string s3(a, 2);//从a[0]开始拷贝2个字符
    18      cout << s3 << endl;//Hi
    19      cout << endl;
    20 
    21      string s4(cp + 6, 5);//从cp[6]开始拷贝5个字符
    22      cout << s4 << endl;//world
    23      cout << endl;
    24 
    25      string s5(s1, 6, 5);//从s1[6]开始拷贝5个字符到s5中
    26      cout << s5 << endl;//world
    27      cout << endl;
    28 
    29      string s6(s1, 0);//从s1[0]开始拷贝,直至s1末尾
    30      cout << s6 << endl;//hello world!
    31      cout << endl;
    32 
    33      string s7(s1);//从s1[0]开始拷贝到s1末尾
    34      cout << s7 << endl;//hello world!
    35      cout << endl;
    36 
    37      string s8(s1, 0, 100);
    38      cout << s8 << endl;//hello world!
    39 
    40      // string s9(s1, 100, 1);//抛出一个out_of_range异常
    41 
    42      return 0;
    43 }
    View Code

    substr 操作:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(void){
     5     string s("hello world");
     6     string s1 = s.substr(0, 5);//从s[0]开始拷贝5个字符赋值给s1
     7     cout << s1 << endl;//hello
     8     cout << endl;
     9 
    10     string s2 = s.substr(6);//从s[6]开始到s结束拷贝到s2
    11     cout << s2 << endl;//world
    12     cout << endl;
    13 
    14     string s3 = s.substr(6, 11);
    15     cout << s3 << endl;//world
    16 
    17     // string s5 = s.substr(12);//抛出一个out_of_range异常
    18 
    19     return 0;
    20 }
    View Code

    改变 string 的其它方法:

    s.insert(a, len, ch)    在 s[a] 之前插入 len 个 ch 字符

    s.insert(a, s1)        在 s[a] 之前插入字符串 s1,s1 是一个 string 字符串

    s.insert(a, s1, pos, len)    在 s[a] 之前插入字符串 s1 中从 s[pos] 开始的 len 个字符

    s.erase(a, len)       删除从 s[a] 开始的 len 个字符

    s.append(ch)      在 s 末尾追加一个字符 ch

    s.replace(a, len, str)   删除从 s[a] 开始的 len 个字符然后再在此处插入字符串 str

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(void){
     5     string s;
     6     s.insert(s.size(), 10, '!');//在s末尾插入10个感叹号
     7     s.erase(s.size() - 5, 5);//从s删除最后5个字符
     8     cout << s << endl;//!!!!!
     9     cout << endl;
    10 
    11     const char *cp = "abcdefg jfsljf fjs";
    12     s.assign(cp + 1, 8);//从cp[1]开始拷贝8个字符赋值给s
    13     cout << s << endl;//bcdefg j
    14     cout << endl;
    15 
    16     string s1;
    17     s1.insert(0, s);//在s1[0]之前插入s的拷贝
    18     cout << s1 << endl;//bcdefg j
    19     cout << endl;
    20 
    21     s1.insert(0, s, 0, s.size());//在s1[0]之前插入s中s[0]开始的s0.size()个字符
    22     cout << s1 << endl;//bcdefg jbcdefg j
    23     cout << endl;
    24 
    25     s.append("hello");//等价于 s.erase(s.size() - 5, 5)
    26     cout << s << endl;//bcdefg jhello
    27 
    28     s.replace(s.size() - 5, 5, "hello world!");//从s[s.size()-5]开始删除5个字符,然后再插入"hello world!"
    29     cout << s << endl;//bcdefg jhello world!
    30 
    31     return 0;
    32 }
    View Code

    注意:字符数组越界问题

    string 搜索操作:

    搜索操作返回指定字符出现的下标,如果未找到则返回 npos(通常其值为-1,但是 npos 为 const string::size_type 类型(是 unsigned 的))

    s.find(args)      查找 s 中 args 第一次出现的位置

    s.rfind(args)       查找 s 中 args 最后一次出现的位置

    s.find_first_of(args)    在 s 中查找 args 中任何一个字符第一次出现的位置

    s.find_last_of(args)    在 s 中查找 args 中任何一个字符最后一次出现的位置

    s.find_first_not_of(args)  在 s 中查找第一个不在 args 中的字符

    s.find_last_not_of(args)  在 s 中查找最后一个不在 args 中的字符

    其中 args 必须是以下形式之一:

    c,pos    从 s 中位置 pos 开始查找字符 c。pos 默认为 0

    s1, pos    从 s 中位置 pos 开始查找字符串 s1。pos 默认为 0

    cp,pos     从 s 中位置 pos 开始查找指针 cp 指向的以空字符结尾的 c 风格字符串

    cp,pos,n  从 s 中位置 pos 开始查找指针 cp 指向的数组的前 n 个字符。pos 和 n 无默认值

    即共有 6 个不同的搜索函数,每个搜索函数又有 4 个重载版本

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(void){
     5     string name("AnnaBelle");
     6     auto pos1 = name.find("Anna");
     7     int pos4 = name.find("Anna", 1);//从name[1]开始查找Anna
     8     cout << pos1 << endl;//0
     9     cout << pos4 << endl;//-1
    10 
    11     int pos2 = name.find("Cc");
    12     auto pos3 = name.find("Cc");
    13     cout << pos2 << endl;//-1
    14     cout << pos3 << endl;//4294967295,find返回的是一个unsigned类型
    15 
    16     string numbers("0123456789");
    17     string gel("jfs90fd00jf");    
    18     cout << gel.find_first_of(numbers) << endl;//3
    19     cout << gel.find_first_of(numbers, 4) << endl;//4
    20     cout << gel.find_first_not_of(numbers, 4) << endl;//5
    21 
    22     const char* ch = "cchhh";
    23     string cc("ch12");
    24     cout << cc.find(ch, 0) << endl;//4294967295
    25     cout << cc.find(ch + 1, 0, 2) << endl;//0 从cc中0开始查找指针ch指向数组的前2个字符,即在cc中查找字符串"ch"
    26     cout << cc.find_first_of(ch, 1, 3) << endl;//1 从cc中1开始查找指针ch指向数组的前3个字符中的字符第一次出现的位置
    27 
    28     return 0;
    29 }
    View Code

    compare 函数:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 int main(void){
     5     string s1("abc");
     6     string s2("abcd");
     7     int a = s1.compare(s2);//比较s1和s2
     8     cout << a << endl;//-1
     9 
    10     a = s1.compare(1, 2, s2);//将s1从s1[1]开始的两个字符和s2比较
    11     cout << a << endl;//1
    12 
    13     a = s1.compare(1, 2, s2, 1, 3);//将s1中从s1[1]开始的两个字符与s2中s2[1]开始的3个字符进行比较
    14     cout << a << endl;//-1
    15 
    16     const char *str = "abcd";
    17     a = s2.compare(str);//比较s1与空字符结尾的字符串数组的大小
    18     cout << a << endl;//0
    19 
    20     a = s2.compare(1, 3, str);//将s2中从s2[1]开始的3个字符与字符数组str比较
    21     cout << a << endl;//1
    22 
    23     a = s2.compare(1, 3, str + 1, 3);//将s2中从s2[1]开始的3个字符与指针str+1开始的3个字符开始比较
    24     cout << a << endl;//0
    25 
    26     return 0;
    27 }
    View Code

    容器适配器:http://blog.csdn.net/selfi_xiaowen/article/details/49700539

  • 相关阅读:
    MySql查看时间
    我的名人名言
    记录:今天架构让隔壁项目组使用MapDB,就好奇的百度了一下
    Hbase安装
    Hbase安装的坑: org.apache.hadoop.hbase.PleaseHoldException: Master is initializing(2)
    Hbase安装的坑:java.lang.ClassNotFoundException: org.apache.htrace.SamplerBuilder(1)
    Kafka安装
    linux下zookeeper安装
    启动kafka生产者报错: WARN [Producer clientId=console-producer] Connection to node -1 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
    org.postgresql.util.PSQLException: ������������: ��������� "runoobdba" ���������
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/8284527.html
Copyright © 2011-2022 走看看