C++ 标准库的 std::string(需包含 <string> 头文件)是处理字符串的核心工具,相比 C 风格字符数组(char[]),它支持动态内存管理、丰富的成员方法,且能避免缓冲区溢出等问题。以下是从基础到进阶的完整用法:
一、基础:创建与初始化
| 初始化方式 | 代码示例 | 说明 |
|---|---|---|
| 直接赋值(推荐) | string s = "hello"; | 最简洁,自动复用字符串常量池 |
| 构造函数初始化 | string s("world"); | 等价于直接赋值 |
| 重复字符初始化 | string s(5, 'a'); | 生成 "aaaaa"(5 个字符 'a') |
| 空字符串 | string s; / string s(""); | 初始长度为 0,可后续赋值 |
| 子串初始化 | string s("abcdef", 2, 3); | 从索引 2 取 3 个字符 → "cde" |
| 从 C 风格数组初始化 | char arr[] = "test"; string s(arr); | 兼容 C 语言字符数组 |
二、核心操作:访问与修改
std::string 是可变字符串,支持随机访问和直接修改单个字符:
1. 字符访问(两种方式)
#include <string>
#include <iostream>
using namespace std;
int main() {
string s = "hello";
// 方式1:下标 [](无越界检查,速度快)
cout << s[0] << endl; // 'h'
s[0] = 'H'; // 修改为 'H' → "Hello"
// 方式2:at()(有越界检查,抛出 out_of_range 异常,更安全)
cout << s.at(4) << endl; // 'o'
s.at(4) = '!'; // 修改为 '!' → "Hell!"
// 快捷访问首尾字符(C++11+)
cout << s.front() << endl; // 'H'(等价于 s[0])
cout << s.back() << endl; // '!'(等价于 s[s.size()-1])
s.back() = 'o'; // 改回 'o' → "Hello"
return 0;
}
2. 长度与容量(高频)
string s = "hello world";
// 1. 有效字符长度(size() 等价于 length())
cout << s.size() << endl; // 11(不含终止符 '\0')
// 2. 判空(比 s.size() == 0 更高效)
if (s.empty()) { /* 空字符串逻辑 */ }
// 3. 预分配容量(减少后续扩容开销)
s.reserve(100); // 预分配100字符空间,避免多次扩容
// 4. 收缩容量(释放未使用内存,C++11+)
s.shrink_to_fit();
三、常用操作:拼接、查找、替换、截取
1. 拼接 / 追加
string s = "hello";
// 方式1:+=(最常用,支持字符串/字符/C风格数组)
s += " world"; // → "hello world"
s += '!'; // → "hello world!"
// 方式2:append()(更灵活)
s.append("abc", 2); // 拼接前2个字符 → "hello world!ab"
s.append(3, '-'); // 拼接3个'-' → "hello world!ab---"
2. 查找子串 / 字符
string s = "hello world, hello c++";
// 1. 查找子串(返回首次匹配索引,无则返回 string::npos)
size_t pos = s.find("hello"); // 0(从开头找)
pos = s.find("hello", 1); // 13(从索引1开始找)
pos = s.rfind("hello"); // 13(反向查找最后一个)
// 2. 查找单个字符
pos = s.find('w'); // 6
// 3. 判断是否包含子串(封装find)
bool has_cpp = (s.find("c++") != string::npos); // true
3. 替换
string s = "hello world, hello c++";
// 替换:参数(起始索引,替换长度,新字符串)
s.replace(6, 5, "python"); // 从索引6替换5个字符 → "hello python, hello c++"
// 进阶:替换所有匹配的子串
size_t pos;
while ((pos = s.find("hello")) != string::npos) {
s.replace(pos, 5, "hi"); // 把所有"hello"换成"hi"
}
cout << s; // 输出:hi python, hi c++
4. 截取子串(substr)
string s = "hello world";
string sub1 = s.substr(0, 5); // 从索引0取5个字符 → "hello"
string sub2 = s.substr(6); // 从索引6取到末尾 → "world"
四、分割与连接(C++ 无内置 split,手动实现)
1. 分割字符串(按分隔符拆分)
#include <sstream>
#include <vector>
// 自定义split函数:将字符串按分隔符拆分为vector
vector<string> split(const string& s, char delim) {
vector<string> res;
stringstream ss(s); // 字符串流
string temp;
// 按分隔符读取
while (getline(ss, temp, delim)) {
res.push_back(temp);
}
return res;
}
// 调用示例
int main() {
vector<string> vec = split("a,b,c,d", ',');
for (auto& str : vec) {
cout << str << " "; // 输出:a b c d
}
return 0;
}
2. 连接字符串(批量拼接)
vector<string> vec = {"a", "b", "c"};
// 方式1:简单拼接(少量字符串)
string s = vec[0] + "-" + vec[1] + "-" + vec[2]; // "a-b-c"
// 方式2:ostringstream(大批量拼接更高效)
ostringstream oss;
for (int i = 0; i < vec.size(); ++i) {
if (i > 0) oss << "-"; // 分隔符
oss << vec[i];
}
string res = oss.str(); // "a-b-c"
五、删除与清空
string s = "hello world";
// 1. 删除指定范围字符(起始索引,删除长度)
s.erase(6, 5); // 删除索引6开始的5个字符 → "hello"
// 2. 删除最后一个字符(C++11+)
s.pop_back(); // → "hell"
// 3. 清空字符串(长度置0,容量保留)
s.clear();
// 4. 彻底清空(长度+容量都置0)
string().swap(s);
六、与 C 风格字符数组互转(高频场景)
string s = "hello";
// 1. string → const char*(只读,不可修改)
const char* c_str = s.c_str();
printf("%s\n", c_str); // 输出:hello
// 2. string → char*(可修改,需手动分配内存)
char* arr = new char[s.size() + 1]; // +1 留 '\0' 位置
strcpy(arr, s.c_str());
arr[0] = 'H'; // 修改为 "Hello"
delete[] arr; // 必须释放,避免内存泄漏
// 3. char[] → string(直接赋值)
char arr[] = "world";
string s2 = arr; // s2 = "world"
七、字符串比较(字典序)
std::string 重载了比较运算符,直接按字典序比较:
string s1 = "apple", s2 = "banana", s3 = "apple";
if (s1 == s3) cout << "相等" << endl; // 输出:相等
if (s1 < s2) cout << "s1更小" << endl; // 输出:s1更小(字典序 "apple" < "banana")
// 用compare()方法(返回int:0=相等,<0=小于,>0=大于)
int ret = s1.compare(s2); // ret < 0
八、遍历字符串(三种方式)
string s = "hello";
// 方式1:下标遍历
for (int i = 0; i < s.size(); ++i) {
cout << s[i];
}
// 方式2:迭代器遍历(兼容STL算法)
for (string::iterator it = s.begin(); it != s.end(); ++it) {
cout << *it;
}
// 方式3:C++11 范围for(最简洁)
for (char c : s) {
cout << c;
}
核心避坑点
- 越界访问:
[]无越界检查,建议在不确定索引时用at()(抛异常更易调试); - 容量与长度:
size()是有效字符数,capacity()是已分配内存,clear()只清空长度,不释放容量; - 拼接性能:大批量拼接避免频繁用
+,优先用ostringstream或reserve()预分配容量; - string::npos:是
size_t类型(无符号整数),判断时不要用int pos接收,否则可能出错。
总结
std::string 是 C++ 处理字符串的首选,核心优势是动态内存管理和丰富的成员方法。
832

被折叠的 条评论
为什么被折叠?



