目录
1、string 类概述
C++标准库中的string类是一个专门用于处理字符串的类,它封装了字符串的常见操作,比C风格的字符数组更安全、更方便。string类位于<string>头文件中,是std命名空间的一部分。
2. string的构造函数
string(); // 默认构造,创建空字符串
string(const char* s); // 用C风格字符串构造
string(const string& str); // 拷贝构造
string(size_t n, char c); // 用n个字符c构造
string s1; // 空字符串
string s2("Hello"); // 从C字符串构造
string s3(s2); // 拷贝构造
string s4(5, 'A'); // "AAAAA"
string s5(s2.begin(), s2.begin()+3); // "Hel"
易错点:
-
未初始化的字符串:默认构造的字符串是空的,直接访问可能导致未定义行为
-
NULL指针:用NULL指针构造会引发未定义行为
-
拷贝开销:大字符串的拷贝构造可能带来性能问题(C++11后可用移动语义优化)
3. 字符串存取
//字符的存取
//char& operator[](int n); //通过[]方式取字符
//char& at(int n); //通过at方法获取字符
string str = "Hello World";
// 1. 使用[]访问字符
cout << "使用[]访问: ";
for(size_t i = 0; i < str.size(); i++) {
cout << str[i] << " ";
}
cout << endl;
// 2. 使用at()访问字符
cout << "使用at()访问: ";
for(size_t i = 0; i < str.size(); i++) {
cout << str.at(i) << " ";
}
cout << endl;
// 3. 修改字符
str[0] = 'h'; // 修改第一个字符
str.at(6) = 'w'; // 修改第七个字符
cout << "修改后字符串: " << str << endl;
易错点:
-
越界访问:使用operator[]越界访问是未定义行为
-
修改const对象:对const字符串使用非const访问方法会导致编译错误
3.1 下标运算符[ ]与at()的区别:
3.1.1 使用下标运算符[ ]访问:
char c1 = str[1]; // 获取第2个字符'e'
-
高效:不进行边界检查,直接访问
-
不安全:如果索引越界(如
str[10]
)会导致未定义行为
3.1.2 使用at()成员函数访问
char c2 = str.at(1); // 获取第2个字符'e'
-
安全:会进行边界检查
-
稍慢:因为多了边界检查的开销
-
如果索引越界(如
str.at(10)
)会抛出std::out_of_range
异常
4. 赋值操作
//string& operator=(const char* s); //char*类型字符串 赋值给当前的字符串
//string& operator=(const string& s); //把字符串s赋给当前的字符串
//string& operator=(char c); //字符赋值给当前的字符串
//string& assign(const char* s); //把字符串s赋给当前的字符串
//string& assign(const char* s, int n); //把字符串s的前n个字符赋给当前的字符串
//string& assign(const string& s); //把字符串s赋给当前字符串
//string& assign(int n, char c); //用n个字符c赋给当前字符串
// 1. 使用=赋值
string str1;
str1 = "直接赋值C字符串"; // 使用C字符串赋值
cout << "str1: " << str1 << endl;
string str2;
str2 = str1; // 使用string对象赋值
cout << "str2: " << str2 << endl;
string str3;
str3 = 'A'; // 使用单个字符赋值
cout << "str3: " << str3 << endl;
// 2. 使用assign()赋值
string str4;
str4.assign("使用assign赋值"); // 完整字符串赋值
cout << "str4: " << str4 << endl;
string str5;
str5.assign("Hello World", 5); // 只赋值前5个字符
cout << "str5: " << str5 << endl; // 输出: Hello
string str6;
str6.assign(str5); // 使用string对象赋值
cout << "str6: " << str6 << endl;
string str7;
str7.assign(10, 'B'); // 赋值10个'B'
cout << "str7: " << str7 << endl;
// 3. 使用assign()部分赋值
string str8 = "ABCDEFGHIJK";
string str9;
str9.assign(str8, 2, 5); // 从str8的第2个位置开始取5个字符
cout << "str9: " << str9 << endl; // 输出: CDEFG
易错点:
-
自我赋值:虽然string处理了自我赋值,但在复杂操作中仍需注意
-
链式赋值:注意赋值顺序和可能的临时对象
5. 查找和替换
5.1 find()与rfind()
find()与rfind()在以下链接中
https://blog.csdn.net/2403_83972754/article/details/147255405?spm=1001.2014.3001.5501
5.2 replace()
5.2.1基本语法
string& replace(size_type pos, size_type count, const string& str);
-
pos:起始位置(从 0 开始)
-
count:要替换的字符数
-
str:替换的新字符串
5.2.2其他版本
// 用子字符串替换
string& replace(size_type pos, size_type count, const string& str, size_type subpos, size_type sublen);// 用 C 风格字符串替换
string& replace(size_type pos, size_type count, const char* s);// 用多个相同字符替换
string& replace(size_type pos, size_type count, size_type n, char c);// 使用迭代器范围替换
string& replace(iterator first, iterator last, const string& str);
string str = "I like Java!";
// 1. 简单替换
str.replace(7, 4, "C++"); // 从位置7开始替换4个字符
cout << "After replace: " << str << endl;
// 2. 替换为不同长度的字符串
str = "C++ is great!";
str.replace(4, 2, " programming language ");
cout << "After long replace: " << str << endl;
// 3. 使用子串替换
string insert_str = "awesome";
str.replace(8, 7, insert_str); // 用string对象替换
cout << "After string replace: " << str << endl;
// 4. 替换为多个相同字符
str.replace(0, 3, 5, 'X'); // 替换为5个'X'
cout << "After char replace: " << str << endl;
6. 拼接
//string& operator+=(const char* str); //重载+=操作符
//string& operator+=(const char c); //重载+=操作符
//string& operator+=(const string& str); //重载+=操作符
//string& append(const char* s); //把字符串s连接到当前字符串结尾
//string& append(const char* s, int n); //把字符串s的前n个字符连接到当前字符串结尾
//string& append(const string& s); //同operator+=(const string& str)
//string& append(const string& s, int pos, int n); //字符串s中从pos开始的n个字符连接到字符串结尾(注意是从pos开始后的n个字符)
// 1. 使用+=操作符
string str1 = "Hello";
str1 += " World"; // 追加C字符串
cout << "str1: " << str1 << endl;
str1 += '!'; // 追加单个字符
cout << "str1: " << str1 << endl;
string str2 = " C++";
str1 += str2; // 追加string对象
cout << "str1: " << str1 << endl;
// 2. 使用append()
string str3 = "I love";
str3.append(" programming"); // 追加完整字符串
cout << "str3: " << str3 << endl;
str3.append(" in Java", 2, 4); // 从位置2开始追加4个字符
cout << "str3: " << str3 << endl; // 输出: I love programming Java
string str4 = " and C++";
str3.append(str4); // 追加string对象
cout << "str3: " << str3 << endl;
// 3. 追加部分字符串
string str5 = "Python";
str3.append(str5.begin(), str5.begin()+3); // 追加前3个字符
cout << "str3: " << str3 << endl; // 输出: ... and C++Pyt
// 4. 追加多个相同字符
str3.append(3, '!');
cout << "str3: " << str3 << endl; // 输出: ...Pyt!!!
易错点:
-
多次拼接性能:频繁拼接小字符串会导致多次内存重分配
-
迭代器失效:拼接操作可能使指向字符串的迭代器失效
string result;
result.reserve(1000); // 预分配足够空间
for(int i=0; i<100; i++) {
result.append(data[i]);
}
7. 字符串比较
字符串比较方法:
* 1. compare() - 返回int表示比较结果
* 2. 比较运算符 - ==, !=, <, <=, >, >=
* 比较规则:按字典序逐个字符比较(基于ASCII码)
//int compare(const string& s) const; //与字符串s比较
//int compare(const char* s) const; //与字符串s比较
string str1 = "apple";
string str2 = "banana";
string str3 = "Apple";
string str4 = "apple";
// 1. 使用compare()比较
cout << "apple vs banana: " << str1.compare(str2) << endl; // 负值
cout << "banana vs apple: " << str2.compare(str1) << endl; // 正值
cout << "apple vs apple: " << str1.compare(str4) << endl; // 0
// 2. 比较大小写敏感
cout << "apple vs Apple: " << str1.compare(str3) << endl; // 正值('a' > 'A')
// 3. 比较子串
cout << "app vs apple: " << str1.compare(0, 3, "app") << endl; // 0(前3字符相同)
// 4. 使用比较运算符
if(str1 == str4) {
cout << "str1 equals str4" << endl;
}
if(str1 > str2) {
cout << "str1 > str2" << endl;
} else {
cout << "str1 < str2" << endl;
}
// 5. 实用案例 - 字符串排序
string fruits[] = {"banana", "apple", "orange", "grape"};
sort(fruits, fruits+4);
cout << "排序后的水果: ";
for(const auto& fruit : fruits) {
cout << fruit << " ";
}
cout << endl;
比较方法选择
-
compare():需要知道具体差异值时使用
-
关系运算符:简单比较时更直观
注意事项:
-
大小写敏感:标准比较是大小写敏感的
-
区域设置影响:某些语言环境下字符顺序可能不同
-
性能:长字符串的比较可能较耗时
8.获得子串
子串操作:
substr() - 提取子串
参数:
pos - 起始位置(默认为0)
len - 子串长度(默认为到字符串末尾)
string str = "Hello World! Programming is fun!";
// 1. 基本用法
string sub1 = str.substr(6, 5); // 从位置6开始取5个字符
cout << "sub1: " << sub1 << endl; // 输出: World
// 2. 省略长度参数
string sub2 = str.substr(13); // 从位置13到末尾
cout << "sub2: " << sub2 << endl; // 输出: Programming is fun!
// 3. 实用案例 - 分割字符串
string email = "user@example.com";
size_t at_pos = email.find('@');
if(at_pos != string::npos) {
string username = email.substr(0, at_pos);
string domain = email.substr(at_pos + 1);
cout << "用户名: " << username << endl;
cout << "域名: " << domain << endl;
}
// 4. 实用案例 - 提取文件扩展名
string filename = "document.pdf";
size_t dot_pos = filename.rfind('.');
if(dot_pos != string::npos) {
string extension = filename.substr(dot_pos + 1);
cout << "文件扩展名: " << extension << endl;
}
// 5. 注意边界检查
try {
string sub3 = str.substr(100, 5); // 超出范围
} catch(const out_of_range& e) {
cerr << "错误: " << e.what() << endl;
}
substr() 使用技巧
-
参数默认值:pos=0, len=npos
-
边界处理:pos超出范围会抛出异常
-
性能:返回新字符串,大子串可能影响性能
实用模式(安全提取子串):
// 安全子串提取
string safe_substr(const string& s, size_t pos, size_t len) {
pos = min(pos, s.size());
len = min(len, s.size()-pos);
return s.substr(pos, len);
}
9. 字符串的插入和删除
字符串插入和删除:
插入方法:
insert() - 在指定位置插入字符串/字符
删除方法:
erase() - 删除指定位置的字符
注意:所有位置都是从0开始计数
//string& insert(int pos, const char* s); //插入字符串(pos位置后插入)
//string& insert(int pos, const string& str); //插入字符串
//string& insert(int pos, int n, char c); //在指定位置插入n个字符c
//string& erase(int pos, int n = npos); //删除从Pos开始的n个字符
string str = "Hello Programming!";
// 1. 插入字符串
str.insert(6, "C++ "); // 在位置6插入
cout << "插入后: " << str << endl; // Hello C++ Programming!
// 2. 插入部分字符串
string lang = "Java and Python";
str.insert(10, lang, 0, 4); // 插入"Java"
cout << "插入部分后: " << str << endl; // Hello C++ JavaProgramming!
// 3. 插入多个相同字符
str.insert(5, 3, '*'); // 插入3个'*'
cout << "插入字符后: " << str << endl; // Hello*** C++ JavaProgramming!
// 4. 删除字符
str.erase(5, 3); // 从位置5删除3个字符
cout << "删除后: " << str << endl; // Hello C++ JavaProgramming!
// 5. 删除到末尾
str.erase(10); // 从位置10删除到末尾
cout << "删除到末尾: " << str << endl; // Hello C++
// 6. 删除单个字符
str.erase(str.begin() + 5); // 删除位置5的字符
cout << "删除单个字符: " << str << endl; // HelloC++
// 7. 实用案例 - 删除空格
string sentence = "This is a test sentence.";
size_t pos;
while((pos = sentence.find(" ")) != string::npos) {
sentence.erase(pos, 1); // 删除多余空格
}
cout << "删除多余空格后: " << sentence << endl;
愿你在代码的世界里如鱼得水,bug退散,灵感如泉涌!保持热爱,奔赴下一场山海,轻松快乐永远是主旋律~ 🎉(附赠一只蹦跶的电子猫:=^・ω・^=)