目录
[string类对象的其他操作(string operations)](#string类对象的其他操作(string operations))
前言
本篇我们将继续讲解string类的内容,本篇着重聚焦各个类型接口的使用和部分注意事项
先附上文档:string - C++ Reference
string构造
构造函数我们在string类第一篇中以有解释,需要请移步「C++」string类(1)-CSDN博客
string类对象的容器操作(capacity)

使用及注意点:
size:返回字符串的有效字符长度;
size和lenght效果相同,引入size是为了和其他容器保持接口保持一致,一般都使用size接口;
resize:将有效字符的个数改成n个,n小于size时,保留前n个字符,n大于size时多出的空间用参数填充(默认为'\0')(VS2022)
capacity:返回容量大小,不包含"\0",即表示有效空间大小
reserve:为字符串预留空间,一般为扩容(申请改变空间)
VS2022环境下:只有当reserve空间大于容量时扩容,不存在缩容的情况;
g++4.8:除n比size()小的情况会将capacity()缩小到size()大小外,按照n值进行缩扩容
clear:清空有效字符,容量不变
empty:检测字符串是否为空,为空返回ture,否则返回false
相关测试代码:
cpp
void Text_StringCapacityFunc()
{
//size length max_size
string str1 = "hello world!";
cout << str1.size() << endl;//返回\0之前的字符个数
cout << str1.length() << endl;
cout << str1.max_size() << endl;
//capacity resize clear empty
string str2 = "hello world!";
str2.resize(8);
//设定长度小于原本字符串长度时,字符串将被截断,但capacity保持不变;
cout << str2 << endl;
str2 = "hello world!";
cout << str2 << endl;
cout << "size:" << str2.size() << endl;
cout << "capacity:" << str2.capacity() << endl;
str2.resize(16);
//设定字符串大于有效字符长度时,会用默认值\0代替
cout << "size:" << str2.size() << endl;
cout << "capacity:" << str2.capacity() << endl;
cout << str2.empty() << endl << endl;
//清除有效字符,不改变空间大小
str2.clear();
cout << str2.size() << endl;
cout << str2.capacity() << endl;
cout << str2.empty() << endl;
//reserve
string str3 = "string_reserve_testdoce";
cout << "size:" << str3.size() << endl;
cout << "capacity:" << str3.capacity() << endl;
cout << "输入78停止循环" << endl;
int i;
do
{
cin >> i;
str3.reserve(i);
cout << ".reserve(" << i << ") after:" << endl;
cout << "size:" << str3.size() << endl;
cout << "capacity:" << str3.capacity() << endl;
} while (i != 78);
// shrink_to_fit缩小capacity到有效字符需要的最小值
str3.shrink_to_fit();
cout << "shrink_to_fit" << endl;
cout << "size:" << str3.size() << endl;
cout << "capacity:" << str3.capacity() << endl;
}
string类对象的修改操作(modifiers)

使用及注意点:
修改操作中最常用的为+=重载;
append尾插时可以调整子字符串插入的子字符串的起始位置及插入长度(不指定子字符串的插入长度时参数缺省为npos(c++14));push_back只能插入一个字符;
assign进行替换操作时,会完全覆盖掉原本的数据并放入参数内容;当参数字符串小于原字符串的capacity时,不会改变容量大小;当参数字符串大于原字符串的capacity时,会自动进行扩容操作;
insert插入子字符串时,必须指定插入的起始位置;当容量不足时会自动扩容;
erase删除时,指定删除的起始位置和删除长度,删除长度缺省npos;
replace指定替换起始位置和长度,子字符串也可指定
swap交换时,会将两个对象的所有成员包括指针指向都进行交换;
pop_back只能删除一个字符;
相关测试代码:
cpp
void StringModifiersFunc()
{
string* str = new string("hello! have a nice day!");
//cout << *str << endl;
//*str1 += "xx";
//cout << *str << endl;
string& str1 = *str;
//cout << str2;
// operator+= \
append \
push_back \
assgin \
insert \
erase \
repalce \
swap \
pop_bakc
//string str2 = "good day!";
////str1.append(str2, 5);
//str1.append(str2, 1, 5);//插入内容为str2的pos=1开始往后5个字符长度的内容
////str1.append(str2);
//cout << str1 << endl;
//str1.push_back('z');
////str1.push_back("z");//报错,只能插入字符;
//cout << str1 << endl;
//cout << str1 << endl;
//cout << str1.size() << endl << str1.capacity() << endl;
//str1.assign("zxt");
////str1.assign("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
//cout << str1 << endl;
//cout << str1.size() << endl << str1.capacity() << endl;
//打印结果可看出,assign虽然会替换原本的数据,但不会改变capacity的大小;\
当替换内容大于capacity容量时,会扩容;
//string str2 = "good!zzzzzzzzzzzzz";
////pos=0时,为头插
//cout << str1.insert(0, str2) << endl;
////cout << str1.insert(0,str2, 1, 2) << endl;
//cout << "size:" << str1.size() << endl << "capacity:" << str1.capacity() << endl;
////pos=str1.size()时,即为尾插
//str1.insert(str1.size(), str2);
////str1.insert(str1.size(), str2, 1, 2);
//cout << str1 << endl;
//str1.insert(0, 2, 'x');//插入字符时,可指定插入个数
//cout << str1 << endl;
//erase头删
//cout << str1.erase(0) << endl;
//cout << typeid(str1.erase(str1.begin())).name() << endl;
//cout << str1 << endl;
//string::iterator i = str1.erase(str1.begin());
//cout << typeid(i).name() << endl;
//cout << str1 << endl;
//string str2 = "zzzzzzzzzzzzzzz";
//cout << str1 << endl;
//cout << str1.size() << endl << str1.capacity() << endl;
//str1.replace(2, 3, str2);//pos=2位置开始,替换原字符串往后三个字符长度的内容为str2
//cout << str1 << endl;
//cout << str1.size() << endl << str1.capacity() << endl;
//replace空间不足时会自动扩容
//string str2 = "hello!";
////swap交换两个对象的所有成员和指向
//str1.swap(str2);
cout << str1 << endl;
str1.pop_back();
cout << "pop_back after : \n" << str1 << endl;
delete(str);
}
string类对象的其他操作(string operations)

c_str:返回C格式的字符串;
copy可将指定位置开始,一定长度的字符串复制到目标中;
find从头开始查找一个字符或者字符串,并返回其下标位置;rfind为从后往前查找;没有查找到时返回npos
find_first_of:返回调用对象包含在 参数字符串范围内的字符 的位置,同理find_last_of则为反向查找;find_first_not_of和find_last_not_of则为返回不包含字符;
substr:获取指定位置开始的指定长度的子串:
当获取位置到结束的长度都小于指定长度len时,默认取到最后一个有效字符
相关测试代码:
cpp
void StringOperationsTest()
{
//c_str 返回字符串指针
//读取文件
//string filename;
//cin >> filename;
//FILE* fout = fopen(filename.c_str(), "r");
//char ch = fgetc(fout);
//while (ch != EOF)
//{
// cout << ch;
// ch = fgetc(fout);//fgetc()获取字符后会自动往后位移一位
//}
//fclose(fout);
//string str1 = "hello world!";
//cout << str1.c_str() << endl;
//cout << str1.data();
//char buffer[20];
//std::string str("Test string...");
//std::size_t length = str.copy(buffer, 6, 5);
//buffer[length] = '\0';
//std::cout << "buffer contains: " << buffer << '\n';
//使用find和substr获取文件后缀名
//string str1 = "7_21_string.cpp";
//size_t pos = str1.find(".");
//cout << "find \".\" opsition:" << pos << endl;
//cout << "file type: " << str1.substr(pos) << endl;
////当有多个后缀名时,使用rfind反向查找获取正确的pos和后缀名
//string str2 = "7_21_string.cpp.zip";
//size_t pos1 = str2.find(".");
//cout << "find \".\" opsition:" << pos1 << endl;
//cout << "file type: " << str2.substr(pos1) << endl;
//size_t pos2 = str2.rfind(".");
//cout << "find \".\" opsition:" << pos2 << endl;
//cout << "file type: " << str2.substr(pos2) << endl;
//使用find_first_of屏蔽指定字符
//string str1("Please, replace the vowels in this sentence by asterisks.");
//size_t pos = str1.find_first_of("abcd");
//while (pos != string::npos)
//{
// str1[pos] = '*';
// pos = str1.find_first_of("abcd", pos + 1);
//}
//cout << str1 << endl;
//同理使用find_first_not_of
string str1("Please, replace the vowels in this sentence by asterisks.");
size_t pos = str1.find_first_not_of("abcd");
while (pos != string::npos)
{
str1[pos] = '*';
pos = str1.find_first_not_of("abcd", pos + 1);
}
cout << str1 << endl;
}
string类相关非成员函数
swap
swap重载了一个针对于string类型的函数,其逻辑是,会调用string类中的成员函数swap
库中的swap函数:
由库中swap函数模板的实现逻辑可以看出,若string直接使用这个swap会导致多次的深拷贝,消耗资源;所以swap实现了string类的特化版本,使其去调用string中的swap成员函数,直接交换两个对象的内容,而不是使用深拷贝;
getline
在使用cin进行输入时,默认将空格和换行作为输入的分隔符,当需要将这些字符也写入对象中时,使用getline
- 当不指定getline的结束获取的字符时,将默认为换行'n';可以在第三个参数位指定作为界限的字符
后记
关于string类中的相关部分接口的讲解就到这里,文中没有提及或者不全的部分,大家可以查看文档来学习,我们下期再见
本期专栏:C++_海盗猫鸥的博客-CSDN博客
个人主页:海盗猫鸥-CSDN博客














