文章目录
🚀1. string类对象的容量操作
⚡️1.1 size
size返回string类对象的_size属性,也就是string的长度。注意:size不包含\0
int main()
{
string s1("Hello world");
cout << s1.size() << endl;
}
也可以用length,与size功能一样:
我们更常用size,length是历史遗留的函数,为了与后面的容器统一所以用size
⚡️1.2 capacity
capacity返回string类对象的_capacity属性,也就是对象的现有容量。这个属性与size不同,size是现有成员的个数,capacity是现有容量大小,当size = capacity时,对象会扩容。这是为了避免每次添加字符时都要重新分配内存,提高性能。
int main()
{
string s1("Hello world");
cout << s1.capacity() << endl;
}
capacity会比实际的空间要小一个字节,有多一个预留给\0的,这里现有容量实际上是16字节,
题外话
:在vs2022有点需要注意,对于长度不大的string类对象,其字符串是建在栈上的,长度大的string类对象是建在堆上的。
int main()
{
string s1("Hello world");
string s2("Hello world!!!!!!!!!!!!!!!!");
}
可以看到s1的"Hello world"是在_Buf上的,_Buf其实在栈上的。
而s2的长度过长,是存在_Ptr上的,_Ptr是在堆上的。
这其中的缘由是因为,vs2022一开始是在栈上存字符串,而扩容的操作实际上的在堆上开空间,再把字符串拷贝进去的,这是vs2022对string类优化的一种方式。
⚡️1.3 max_size
这个函数一般没什么用,从字面意思上是string开辟的最大成员个数,但实际上string都开不到这么大的空间
⚡️1.4 resize
resize用于将字符串的大小调整为n个字符的长度,改变string对象中的_size属性,当n>_capacity,_capacity也会扩容。
用法:
- 当写入第二个参数char c还可以初始化调整后的内容,原先的字符内容会保留,多的size会被填充为 char c,
int main()
{
string s1("Hello world");
s1.resize(100,'!');
cout << s1 << endl;//输出Hello
}
2. 删除内容,resizen < 原先的size,会删除多的内容
int main()
{
string s1("Hello world");
s1.resize(5);
cout << s1 << endl;//输出Hello
}
⚡️1.5 reserve
reserve改变string对象中的_capacity属性,使用场景:当知道string大概有多长时,可以使用reserve先扩大,就可以减少频繁开空间带来的消耗,提高效率。
int main()
{
string s1("Hello world");
s1.reserve(20);
s1 += "!!!!!!!!";
cout << s1 << endl;
}
注意:不要轻易缩容!!,缩容的本质的时间换空间,效率很低
⚡️1.6 clear
clear用于清空string的所有内容,
int main()
{
string s1("Hello world");
s1.clear();
cout << s1 << endl;
}
⚡️1.7 empty
empty判断string是否为空,空则true,非空则false。
int main()
{
string s1("Hello world");
string s2;
cout << s1.empty() << endl;//false
cout << s2.empty() << endl;//ture
}
🚀2. string类对象访问元素
operator[]不必多说,就是像数组一样访问string里的元素。
⚡️2.1 at
at函数与[ ]的作用相同,但[ ]访问越界时,是暴力的直接报错,而at是报异常
int main()
{
string test("hello!");
try
{
test.at(10);//访问越界
}
catch (const exception& e)
{
cout << e.what() << endl;
}
}
⚡️2.2 back 与 front
back 与 front分别返回string的尾字符和头字符,这两个函数返回的是引用,是字符本身。
int main()
{
string test("hello!");
cout << test.front() << " " << test.back()<<endl;
test.front() = 'H';
test.back() = '?';
cout << test.front() << " " << test.back() << endl;
}
🚀3. string类对象的字符串操作(查找)
⚡️3.1 c_str
c_str会返回string类对象的字符数组。使用场景:因为c语言没有string,只有字符数组构成的字符串,c++在使用c语言的函数时,就可以调用c_str传参。
#include <iostream>
using namespace std;
int main()
{
string file("test.cpp");
//fopen是c语言库的函数,第一个参数类型为 char*
FILE* fout = fopen(file.c_str(), "r");
char ch = fgetc(fout);
while (ch != EOF)
{
cout << ch;
ch = fgetc(fout);
}
}
⚡️3.2 find 与 rfind
find 会从string类对象的第一个字符开始I(如果有pos参数,就从pos参数开始),正着找第一个相同的 字符串/字符,并返回其下标。如果找不到会返回 string::npos。
注意
:string::npos 字面意表示字符最大长度,数值等于 -1。
int main()
{
string file("test.cpp.zip");
// 1.find(const string & str, size_t pos = 0) const;
int test1= file.find("cpp");
// 2 find(char c, size_t pos = 0) const;
int test2 = file.find('.',5);
cout << "test1 = " << test1<<" " << "test2 = " << test2;
// 3 找不到
int test3 = file.find('.',5);
cout << "test1 = " << test1<<" " << "test2 = " << test2;
}
运行结果:
rfind:
rfind 与find 语法相同,但rfind 是倒着找。
⚡️3.3 substr
string substr (size_t pos = 0, size_t len = npos) const;
substr截断从pos下标开始,往后的len个字符,并返回这个截断的字符串(string类型)
substr常与 rfind 和find 配合使用,用于截断文件名的后缀和id。
int main()
{
string file("string.cpp.zip");
size_t pos_head = file.find('.');
size_t pos_end = file.rfind('.');
string suffix_1 = file.substr(0,0+ pos_head);
string suffix_2 = file.substr(pos_end+1);
cout << suffix_1 << endl;
cout << suffix_2 << endl;
}
运行结果:
⚡️3.4 find_first_of 与 find_last_of
第一个参数为字符串str,第二个位置为开始查找的下标pos, find_first_of会从pos开始,正序遍历字符与str内的字符相比较,如果这个字符 等于 str内的字符,返回其下标。
int main()
{
string file("string.cpp.zip");
int pos1 = file.find_first_of("crazy");//下标2的r符合
int pos2 = file.find_first_of("tiger");//下标1的t符合
cout << pos1 << pos2 << endl;
}
运行结果:
find_last_of:
find_last_of与find_first_of语法相同,但find_last_of 是从pos位置倒着找。
⚡️3.5 find_first_not_of 与 find_last_not_of
和find_first_of很像,find_first_not_of会从pos开始,正序遍历字符与str内的字符相比较,如果这个字符 不等于 str内的字符,返回其下标。
int main()
{
string file("string.cpp.zip");
int pos1 = file.find_first_not_of("crazy");//下标0的r符合
int pos2 = file.find_first_not_of("singer");//下标1的t符合
cout << pos1 <<" " << pos2 << endl;
}
运行结果:
感谢你能看到这里!!