目录
介绍:
string类的常见接口说明
1. string类的常见构造
1.1 string(const string& str,size_t pos,size_t len = npos);
1.2 string(const char* s)
1.3 string (const char * s , size_t n);
1.4 string(size_t n,char c);
2.string类对象的容量操作
2.1 size 与 length
2.2 capacity
2.2.1 capacity的扩容机制
2.3 clear
2.4 reserve
2.5 resize
(1)字符串变短
(2)字符串变长
(3)修改长度比capacity大
3. string类对象的访问及遍历操作
3.1 operator[] 与 at
3.2遍历操作
1.使用size
2.使用operator[]
3.begin + end 的 迭代器 遍历操作
3.1 反向迭代器
4.string类对象的修改操作
4.1push_back
4.2 append
4.3 operator += (最为常用)
4.4 assign
4.5 insert
4.6 erase
4.7 replace
4.7.1 find与replace
小总结:
介绍:
相关内容详细介绍:cplusplus.com/reference/string/string/?kw=string
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,typedef basic_string string,所以string 在底层的本质上也是一个模板
- 不能操作多字节或者变长字符的序列。
- 在使用string类时,必须包含#include头文件以及using namespace std;
string类的常见接口说明
1. string类的常见构造
1.1 string(const string& str,size_t pos,size_t len = npos);
void test_string()
{string s1;string s2(s1 , 5 ,10);
}提取字符串中的某个区间段的字符,作为一个新的字符串
或者可以说是从一个字符串中提取子字符串
- str:要从中提取子字符串的源字符串。
- pos:指定要开始提取子字符串的位置。
- len:可选参数,指定要提取的子字符串的长度。默认值为 npos,表示提取从 pos 开始到源字符串的末尾的所有字符。
1.2 string(const char* s)
const char* cstr = "Hello, C++";
string str(cstr); // 使用构造函数将字符串赋值给string的对象strcout << str << endl; // 输出:Hello, C++接收一个char类型的字符串作为参数,也就是说将一个字符串赋予给string的对象
1.3 string (const char * s , size_t n);
const char* cstr = "Hello, World!";
size_t n = 5;
std::string str(cstr, n); // 使用C风格字符串的前n个字符初始化std::string对象
- 在这个例子中,cstr 指向字符串 "Hello, World!"。
- 由于 n 被设置为5,std::string str(cstr, n); 会创建一个 std::string 对象 str并只包含 "Hello" 这5个字符,不包含后面的逗号和空格以及终止空字符。
1.4 string(size_t n,char c);
string s6(10,'#');
cout << s6 << ednl;//输出结果 : ##########本质上是一种初始化
2.string类对象的容量操作
2.1 size 与 length
void test_string()
{string s1("hello world");cout << s1.size() << endl; //输出结果: 11cout << s1.length() << endl; //输出结果: 11}size 与 length 的功能都是返回字符串的实际长度,二者并没有任何的区别
2.2 capacity
void test_string()
{string s1("hello world");cout << s1.capacity() << endl; //输出结果: 15}返回字符串所处在的空间大小,在一般情况下capacity的返回值并不会包含\0所占用的空间
同时,我们需要直到的是capacity的返回值是比size和lenghth的返回值大的,理由如下:
在C++中,std::string是一个动态数组,它可以根据需要自动调整大小,当你创建一个字符串对象时,它会分配一定的内存空间来存储字符串的字符。
这个内存空间的大小由capacity决定,在例子中,字符串"s"的内容是"hello world",它包含11个字符,然而,为了提高性能,std::string通常会分配比实际字符串长度更大的内存空间。
这个额外的空间被称为capacity,它用于存储未来可能添加到字符串中的字符,以避免频繁的内存重新分配操作。所以,s.size()返回的是字符串实际包含的字符数,即11。而s.capacity()返回的是字符串当前分配的内存空间大小,即15。
2.2.1 capacity的扩容机制
如上代码想要表达的意思如下:
- 使用变量 sz 获取当前 字符串中的 空间大小,随后进入for循环中使用了 同为 string 的一种接口,push_back 对字符串内部的内容进行添加,随后,判断当前 sz 与 当前的capacity 大小相比较。
- 由于,在字符串中添加了内容,以及在字符串内部添加了内容,导致了capacity 会因为字符串内容的添加进行空间的对策扩充。
- 而这个扩充的机制便是,第一次扩充到原来空间的两倍左右,而之后则扩充到当前空间的1.5倍
2.3 clear
void test_string()
{string s1("hello world");cout << s1 << endl; //输出结果: hello worlds1.clear();cout << s1 << endl; //输出结果:一行空格}清除数据,但仅仅只是数据的清除,空间并不一定清理掉
也就空间不会被释放或者空间不会被销毁!只是清除了空间内部的数据void test_string()
{string s1("hello world");cout << s1 << endl; //输出结果: hello worldcout << s1.capacity() << endl ; // 输出结果:15s1.clear();cout << s1 << endl; //输出结果:一行空格cout << s1.capacity() << endl;//输出结果:15
}如果想要释放空间或者在情况数据后释放空间,可以使用shrink_to_fit
但是这个只是缩小空间大小,但还是会保留一定量的空间,总之不会变成0
2.4 reserve
string s;//创建一个string 的变量s
s1.reserve(100);//提前为 s 进行空间的开辟
cout << s1.capacity() <<endl;//输出结果是 111reserve的功能是开辟空间,或者说是预留空间
当我们知道所需要的空间大小时,可以使用reserve进行空间的开辟
使得在内存空间中提前为我们需要的数据开辟空间当然,使用了reserve后,因为编译器的问题,有些编译器为了灵活分配内存空间问题
会对reserve开辟的空间进行二次的开辟,也就说进行空间的二次预留这样就导致开辟出来的空间可能比我们需要的空间还要多
同时,如果使用了reserve 进行空间的扩容,是完全可以的,但是要注意,reserve进行扩容的大小必须要比当前空间的大小还要大,不然reserve是无效扩容
void test1()
{string s1("hello world xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")cout << s1.capacity() << endl;s1.reserve(10);cout << s1.capacity() << endl;//因为reserve扩容的大小比capacity小,所以扩容无效}void test2()
{string s1("hello world xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")cout << s1.capacity() << endl;s1.reserve(200);cout << s1.capacity() << endl;//因为reserve扩容的大小比capacity大,所以扩容成功//输出的结果,应该是两百左右的大小}
2.5 resize
resize的主要作用是改变一个字符串的实际长度,但是resize改变长度的情况分为三种:
(1)字符串变短
string s("hello world");
cout << s.size() << endl; // 长度是 11
sout << s.capacity() << endl; // 空间大小是 15s.resize(5);
cout << s.size() << endl; //长度是5
sout << s.capacity() << endl;//空间大小是15
当resize修改的长度比原本的长度还要小时,那么resize会保留前面的长度,删除后面的数据内容,以此达到相对因的长度,不包含\0
(2)字符串变长
string s("hello world");
cout << s.size() << endl; // 长度是 11
sout << s.capacity() << endl; // 空间大小是 15s.resize(13);
cout << s.size() << endl; //长度是13
sout << s.capacity() << endl;//空间大小是15
当resize修改的长度比原本的长度还长,且resize修改的长度比capacity的空间大小要小时,字符串的长度会被添加至resize修改的长度,而多出来的部分则是用\0进行填充,或者被指定字符填充,以上的代码是默认情况,使用了\0填充
(3)修改长度比capacity大
string s("hello world");
cout << s.size() << endl; // 长度是 11
sout << s.capacity() << endl; // 空间大小是 15s.resize(20);//修改的长度比空间大小还大
cout << s.size() << endl; //长度是20
sout << s.capacity() << endl;
//空间大小是31,因为修改长度超过了原来的空间大小,所以进行了扩容
当resize修改的长度大小比capacity还要大时,capacity会进行扩容处理
3. string类对象的访问及遍历操作
3.1 operator[] 与 at
void test()
{string s1("hello world");cout << s[2] <<endl; //结果是 ecout << s.at(2) << endl; //结果是 e}
at和[]的功能是类似的,二者虽然访问的功能是一样的,但是二者的检查越界的方式是不一样的。
如以上两张图,图1是[]的越界访问,是一个断言警告,图二是at的越界访问,是一个异常处理
3.2遍历操作
1.使用size
2.使用operator[]
而由于operator []的本质是返回当前位置的字符,所以可以利用它的特性对字符串中的字符进行++或者--等相关的加减操作
3.begin + end 的 迭代器 遍历操作
迭代器的行为像指针一样的类型对象,begin是返回第一个有效位置的迭代器,end是返回最后一个有效数据的下一个位置,这里的最后一个有效数据的下一个字符是\0,相当于指针的移动,从当前位置移动到\0位置结束
时使用迭代器也可以进行字符串中的字符修改操作
3.1 反向迭代器
反向迭代器使用的是 rbegin 和 rend 进行字符串的反向输出操作
4.string类对象的修改操作
4.1push_back
主要功能是在字符串的尾部插入字符,且只能插入一个字符
void test()
{string s("hello world");s.push_back("!");cout << s << endl; //输出结果:hello world!}
4.2 append
append(const & char*s)这个功能和push_back的功能类似,但是比push_back更强,因为它可以添加字符串
void test()
{string s("hello world");s.append(" hello bit");cout << s << endl; //输出结果:hello world hello bit}
4.3 operator += (最为常用)
void test()
{string s("hello world");s += " " ;s += "apple" ;cout << s << endl; //输出结果:hello world apple}
4.4 assign
最常见的功能是字符的覆盖,将空间内部内容进行删除,然后在添加所需要的内容
void test()
{string s("hello world");s.assign("xxx");cout << s << endl; //输出结果:xxx}
4.5 insert
主要功能在当前位置之前插入字符串
void test()
{string s("hello world");s.insert(0,"xxx");cout << s << endl; //输出结果:xxxhello world}
4.6 erase
从某个位置开始删除几个字符,如果字符不够删,则有多少删多少
void test()
{string s("xxxhello world");s.erase(0,3);//前面的 0 是位置,后面的3是需要删除的字符个数cout << s << endl; //输出结果:hello worlds.erase();cout << s << endl;//erase的默认是全部删除,只留下一行空格当作还要空间存在没有释放}
4.7 replace
主要功能是字符的替换,某个区间位置的字符进行替换
void test()
{string s("hello world");s.replace(5,1,"%")//5是位置,1是替换的字符个数,%是替换的内容cout << s << endl; //输出结果:hello%world}
4.7.1 find与replace
find的功能是寻找字符串内部需要查询的字符,找到后返回字符所处在的位置下标,找不到则返回-1
如图配合了replace使用,就可以查询字符串中的空格符号,并且将空格符号进行替换,直到字符串内的所有空格符号都替换完成,其中的npos其实表示的是find找不到字符后的返回值。也就是-
小总结:
insert replace erase 这几个能少用就少用,因为基本都需要挪动数据,它们的底层代码就是挪动数据,所以效率不是很高,建议多使用operator +=