在C++中,std::string 是标准库提供的字符串类,用于代替C风格字符数组(char* 或 char[])。它封装了字符串的存储和操作,提供自动管理内存,无需手动分配/释放;支持动态扩展(如拼接操作);提供丰富的成员函数(查找、替换、子串等);通过 size() 获取长度,无需遍历到’\0’。
1.定义和初始化
string s1; // 定义空字符串
string s2(“Hello”); // 用C风格字符串初始化
string s3 = “World”; // 赋值初始化
string s4(5, ‘a’); // 生成 “aaaaa”
string s5(s2); // 用s2初始化s5
string变量可以用cin或者getline来赋值。例如:
string str1;
cin >> str1;//遇到空格或其他控制符即结束
getline(cin, str);//输入的字符串可以包含空格
getline(cin, str, ‘.’); //输入的字符串以’.’作为结束符
2.常用操作
(1)字符串连接
使用+或者+=运算法或者使用 append() 成员函数拼接两个字符串。例如:
string s = “Hello”;
s += ” World”; //s.append(” World”);
cout<<s<<endl;
控制台输出:Hello World
(2)访问单个字符
可以使用下标运算符 [] 或 at() 成员函数来访问字符串中的单个字符。[] 操作符不会进行边界检查,如果访问越界会导致未定义行为,但访问速度会更快。at() 函数会进行边界检查,如果访问越界会抛出 std::out_of_range 异常。例如:
char c1 = s[0]; // 不检查越界(更快)
char c2 = s.at(1); // 越界时抛出 out_of_range(更安全)
(3)比较字符串
可以使用关系运算符(==, !=, <, <=, >, >=)来比较两个字符串。比较是基于字典序进行的。例如:
if (s1 == s2) { /* … */ }
也使用 compare() 方法,例如:
int result = s1.compare(s2); // 返回0表示相等,负数表示s1 < s2,正数表示s1 > s2
(4)查找与字串
find():查找子串或字符的首次出现位置,例如:
size_t pos = s.find(“World”); // 返回子串位置,未找到返回 std::string::npos
rfind():功能与find()相似,但从后向前查找。
substr():提取子串。例如:
string sub = s.substr(6, 5); // 从位置6开始,取5个字符
(5)修改字符串
replace():替换子串。例如:
s.replace(0, 5, “Hi”); // 将前5个字符替换为 “Hi”
insert():插入字符串。例如:
s.insert(5, ” dear”); // 在位置5插入 ” dear”
erase():删除字符。例如:
s.erase(3, 2); // 从位置3开始删除2个字符
(6)容量操作
size() 或 length():获取字符串长度。
empty():判断是否为空。
reserve():预分配内存(减少动态分配次数)。例如:
s.reserve(100); // 预分配至少100字符的内存
capacity():查看当前分配的内存大小。
3.字符串与数值转换
(1)数值转字符串。使用to_string()函数。例如:
int num = 42;
string str = to_string(num); // “42”
(2)字符串转数值。使用 stoi(), stol(), stof() 等函数。例如:
string num_str = “123”;
int num = stoi(num_str); // 123
4.与C风格字符串交互
可以使用 c_str() 获取C风格字符串指针,例如:
const char* cstr = s.c_str(); // 以’\0’结尾,适用于C函数
5.注意事项
(1)string自动管理内存,但频繁修改可能导致多次重新分配,可使用 reserve() 优化性能。
(2)[]不检查越界,优先用 at() 或在操作前检查 size()。
(3)修改字符串可能导致指向其内容的迭代器失效。
6.迭代器
迭代器是 STL 中用于遍历容器元素的抽象指针。对string 来说,迭代器可以看作是指向字符的指针,但更安全、更通用。迭代器的类型包括:
正向迭代器:iterator
常量正向迭代器:const_iterator(不可修改元素)
反向迭代器:reverse_iterator
常量反向迭代器:const_reverse_iterator
(1)迭代器的基本操作
begin():返回指向第一个字符的迭代器。
end():返回指向最后一个字符之后的迭代器(哨兵位置)。
rbegin():返回反向迭代器,指向最后一个字符。
rend():返回反向迭代器,指向第一个字符之前的位置。
例如:
string str = “Hello”;
auto it_begin = str.begin(); // 指向 ‘H’
auto it_end = str.end(); // 指向 ‘o’ 之后
auto rit = str.rbegin(); // 指向 ‘o’
(2)遍历字符串
使用循环遍历所有字符:
for (auto it = str.begin(); it != str.end(); it++)
{
cout << *it << ” “; // 输出字符(Hello)
}
反向遍历:
for (auto rit = str.rbegin(); rit != str.rend(); rit++)
{
cout << *rit << ” “; // 输出olleH
}
范围 for 循环(底层使用迭代器):
for (char ch : str)
{
cout << ch << ” “; // 输出 Hello
}
(3)修改字符
auto it = str.begin();
*it = ‘h’; // 将第一个字符改为 ‘h’(”hello”)
(4)查找字符
auto it = find(str.begin(), str.end(), ‘e’);
if (it != str.end()) {
cout << “Found at position: ” << (it – str.begin());
}
(5)插入和删除
插入字符:使用 insert 方法:
str.insert(str.begin() + 3, ‘X’); // 在位置3插入 ‘X’ → “HelXlo”
删除字符:使用 erase 方法:
str.erase(str.begin() + 2); // 删除位置2的字符 → “HeXlo”
str.erase(str.begin(), str.begin() + 2); // 删除前两个字符 → “Xlo”
(6)字符串拼接
string s1 = “Hello”;
string s2(s1.begin(), s1.begin() + 3); // “Hel”
(7)字符转换
transform(str.begin(), str.end(), str.begin(), toupper); // 转大写
(8)反转字符串
reverse(str.begin(), str.end()); // “olleH”
使用迭代器的注意事项:
(1)修改字符串(如插入、删除)可能导致迭代器失效。
(2)如果不需要修改字符,使用 const_iterator 更安全。
(3)rbegin() 对应最后一个字符,rend() 对应第一个字符之前。反向迭代器的 ++ 操作是向前移动。
7.stringstream类
stringstream 是 C++ 标准库中的一个类,主要用于将字符串进行解析或者格式化输出,在处理字符串和数值类型之间的转换以及复杂字符串解析时非常有用。它允许用户像操作输入输出流(如 cin 和 cout)一样操作字符串。这意味着你可以使用熟悉的 >> 和 << 运算符进行输入输出操作,只不过操作的对象是字符串。
(1)字符串解析。将一个包含多种数据类型的字符串解析成不同的数据类型。例如:
string input = “10 20.5 hello”;
stringstream ss(input);
int intValue;
double doubleValue;
string stringValue;
ss >> intValue >> doubleValue >> stringValue;
cout << “Parsed int: ” << intValue << endl;
cout << “Parsed double: ” << doubleValue << endl;
cout << “Parsed string: ” << stringValue << endl;
运行的结果为:
Parsed int: 10
Parsed double: 20.5
Parsed string: hello
(2)字符串格式化输出。将不同数据类型组合成一个字符串。
int intValue = 10;
double doubleValue = 20.5;
string stringValue = “hello”;
stringstream ss;
ss << intValue << ” ” << doubleValue << ” ” << stringValue;
string result = ss.str();
cout << “Formatted string: ” << result << endl;
运行结果为:
Formatted string: 10 20.5 hello
(3)多次使用 stringstream。stringstream 对象可以被重复使用,在每次使用前需要清除其内部状态。
stringstream ss;
string input1 = “5 15.5”;
string input2 = “10 25.5”;
int intValue;
double doubleValue;
// 第一次使用
ss.str(input1);
ss >> intValue >> doubleValue;
cout << “First parse – int: ” << intValue << “, double: ” << doubleValue << endl;
// 清除状态,准备下一次使用
ss.clear();
// 第二次使用
ss.str(input2);
ss >> intValue >> doubleValue;
cout << “Second parse – int: ” << intValue << “, double: ” << doubleValue << endl;
运行结果为:
First parse – int: 5, double: 15.5
Second parse – int: 10, double: 25.5