前言

书接上文【C++】模板初阶详情请点击
本文接着由小编为大家介绍【C++】STL容器string的使用

一、string的介绍

在这里插入图片描述string的文档介绍,点击跳转
在使用string类时,必须包含 C++常规的头文件#include< iostream >和命名空间的展开using namespace std;

1、auto关键字

在这里补充2个C++11的小语法,方便我们后面的学习:

  1. 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期 推导而得。
  2. 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
    在这里插入图片描述
  3. 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
    在这里插入图片描述
  4. auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
  5. 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循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。

  1. 范围for可以作用到数组和容器对象上进行遍历
  2. 范围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读取数据读取到空格或者换行的时候,读取都会结束,这会导致下面这个情况)
在这里插入图片描述

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐