【C++】STL容器--string的使用
目录
前言
书接上文【C++】模板初阶详情请点击
本文接着由小编为大家介绍【C++】STL容器string的使用
一、string的介绍
string的文档介绍,点击跳转
在使用string类时,必须包含 C++常规的头文件#include< iostream >和命名空间的展开using namespace std;
1、auto关键字
在这里补充2个C++11的小语法,方便我们后面的学习:
- 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期 推导而得。
- 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
- 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
- auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
- auto不能直接用来声明数组(
auto array[] = { 4, 5, 6 })
int func()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = func();
cout << a << " " << b << " " << c << " " << d << endl;
return 0;
}

但是如果直接
auto e;会报错(类型包含“auto”的符号必须具有初始值设定项)

2、范围for
对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。
- 范围for可以作用到数组和容器对象上进行遍历
- 范围for的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到
根据C语言习惯,我们遍历数组是用for或者while循环
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
{
cout << arr[i] << endl;
}
return 0;
}
现在C++中有了范围for和auto关键字之后,我们可以使用范围for遍历修改数组,结果与C语言完全一致
二、string的使用
1、默认成员函数
①构造函数和拷贝构造

这里第三条中的npos是一个静态成员函数,npos是无符号整型,所以npos = -1代表这一个很大的值,在这里作为缺省值,这代表如果不传参默认str从pos位置开始一直到结尾的字符全部拷贝。
int main()
{
string s1;//构造空的string类对象,即空字符串
string s2("hello world");//用C-string来构造string类对象
string s3(s2); //拷贝构造
string s4(s2, 0, 5);//s4 = s2字符串下标为0的位置开始到第5个字符结束“hello”
string s5(s2, 0); //size_t len = npos这个值使用缺省值,所以默认从下标为0的位置->s2结束
string s6("hello world", 2); //用C-string("hello world")的前2个字符组成的字符串构成s6
string s7(20, 'k');//用20个字符‘k’构成字符串s7
string s8(s2.begin(), s2.end());//使用迭代器
return 0;
}

②析构函数
析构函数在类对象生命周期结束时会自动调用对对象资源进行清理,不需要我们显示调用。
③赋值运算符重载

注意:赋值运算符重载的对象一定是已经存在的类(对象)
int main()
{
string s1("hello");
string s2;
s2 = s1; //赋值运算
s2 = "world";
s2 = 'h';
return 0;
}

2、迭代器
①begin/end
string的迭代器类似指针,但其本质不一定是指针,迭代器的使用:使用::声明类域。s1.begin()获取的是s1的第一个字符,s1.end()指向的是s1最后一个元素的下一个位置(左闭右开)
int main()
{
string s1("hello world");
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it;
++it;
}
cout << endl;
return 0;
}
返回为iterator的迭代器可以访问对象,也可以对对象进行修改

返回为const_iterator的迭代器只能访问对象元素,无法修改

②rbegin/rend
begin/end是正向迭代器,而rbegin/rend是与begin/end相反的反向迭代器,即反向遍历对象元素;同理const_reverse_iterator无法修改对象元素。
int main()
{
string s1("hello world");
string::reverse_iterator it = s1.rbegin();
while (it != s1.rend())
{
(*it)++;
cout << *it;
++it;
}
cout << endl << endl;
return 0;
}
3、Capacity(容量相关函数)

1.size和length:返回字符串的有效元素个数(一般使用size)
2.max_size:返回字符数组能存储字符的大小,不同编译器返回的值不同,几乎不使用
3.capacity:返回字符数组的空间大小,实际空间要比编译器显示的大1,因为编译器在字符串末尾放了一个“\0”
4.clear:清空字符数组中的有效字符,并改变底层字符数组空间大小
5.empty:判断字符串是否为空串
6.shrink_to_fit:缩小容量至有效个数大小,但是考虑各种原因缩的大小不确定,几乎不使用
int main()
{
string s1("hello world");
cout << s1.size() << endl;
cout << s1.length() << endl;
cout << s1.capacity() << endl;
cout << s1.max_size() << endl;
cout << s1.empty() << endl;
s1.clear();
cout << s1.size() << endl;
cout << s1.capacity() << endl;
cout << s1.empty() << endl;
return 0;
}
观察终端,我们发现s1空间大小是16,但是在串窗口打印为15,这是因为s1后面还有”\0“
①resize

1.resize指定字符个数,如果大于当前字符数组的有效数据个数,如果没有指定字符串,会将’\0’作为效字符追加在原字符串后面,让该字符串有效字符个数变为指定的字符个数,如果空间不够会扩容。如果指定了字符,那么用这个字符追加在原字符串后面。
2.如果resize指定字符个数,如果小于当前字符数组的有效数据个数,那么该字符数组的有效数据个数会变为指定的个数,但是底层空间不会因为有效字符个数的减少而去缩容。
②reserve

reserve会一次性扩容开空间,改变底层空间capacity大小,reserve一般用于你提前知道要开多大的空间的情况,这样可以一次性开好避免扩容
4、元素访问
①operator[]

string重载了operator[],由于string类存储的字符串其实是一个字符数组,重载[]可以支持类对象想数组下标一样访问元素,传回来的元素的引用可以访问和修改,如果是const类型对象,不能被修改。
②at

at和重载[]一样可以访问下标位置,但是不同的是at如果下标位置不对或者超出字符数组下标范围会抛异常,抛异常之后可以捕获异常
超出字符数组范围,抛异常
5、修改相关的成员函数
①operator+=

重载的+=操作符,用于追加字符串、单个字符或者string对象的字符串
②append

append作为成员函数,它也可以进行各种追加
③push_back/pop_back
用于插入/删除单个字符
注意:在string尾部追加字符时,s.push_back(c)/ s.append(1, c) / s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
④assign

assign:为字符串分配一个新值,替换原字符串内容
⑤insert

insert:在指定位置插入,但是在头位置插入时,需要把后面的字符都往后挪动一位再头插,效率低。下面展示部分接口
⑤erase

erase:删除某个位置的值,由于有缺省值的存在,可以不用传参,不传参默认是清空字符串。也可以传入迭代器,传入单个迭代器,表示删除指定位置的单个字符,传入的是两个迭代器,表示删除的左闭右开的区间内的字符。
⑥swap

swap:交换两个string类型字符串
6、String operations(字符串操作相关)
①c_str

c_str将string类对象字符串转化为C语言格式的字符串
②find/rfind


find:查找string字符串中是否有string类字符串或者C字符串或者字符,从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置(不是下标),找不到时返回string::npos。refind:查找方式和find类似。
③substr

substr:生成的string类对象的字符串的字串,在str中从pos位置开始,截取n个字符,然后将其返回,不传参,默认返回相同内容的对象。
④find类


find_first_of:查找pos位置的字符是否是给定string字符串、C字符串或者单个字符的字串,如果是返回对应位置的下标,没有找到,返回npos。(find_last_of反向查找)
find_first_not_of:也和find_first_of类似,但是查找的是和我们给的字符串或字符不一样的字符,并返回字符位置。(find_last_not_of反向查找)
int main()
{
string s1("hello world");
size_t pos = s1.find_first_of('h', 0);
while (pos != string::npos)
{
s1[pos] = '#';
pos = s1.find_first_of('0', pos + 1);
}
cout << s1 << endl;
return 0;
}

7、非成员函数的重载
①operator+

operator+:是将string类对象和字符串或者字符或者string类字符串相加,不改变原来的字符串,相加后的字符串放到string类中。
②relational operators

③operator>>/operator<<


operator>>:提取运算符重载,输入字符或者字符串
operator<<:插入运算符重载,进行输出string类对象
④getline

getline:获取一行数据,当遇到"\n"的时候结束数据读取,使用时需要包含头文件#include < string >(getline和cin的区别:当cin读取数据读取到空格或者换行的时候,读取都会结束,这会导致下面这个情况)
更多推荐





























所有评论(0)