前言
STL 中的 string 类是处理文本数据最常用的容器之一。在掌握迭代器、auto 关键字和范围 for 循环的基础上,深入理解 string 的常用接口能显著提升开发效率。本文将重点梳理 string 类的构造、容量管理、访问遍历及修改操作。
一、string 类对象的常见构造
1.1 空字符串构造函数
无参构造函数 string() 会创建一个长度为 0 的空字符串对象。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1; // 调用默认构造函数,构造一个空字符串
cout << "s1: " << s1 << endl;
cout << "s1.size(): " << s1.size() << endl; // 输出 0
return 0;
}
1.2 C 字符串构造函数
可以通过 C 风格字符串(const char*)直接初始化 string 对象。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s2("Hello world"); // 通过 C 类型字符进行构造
cout << "s2: " << s2 << endl;
return 0;
}
1.3 n 个字符构造函数
指定数量 n 和字符 c,构造包含 n 个 c 的字符串。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s3(5, 'x'); // 通过 n 个字符进行构造
cout << "s3: " << s3 << endl;
return 0;
}
1.4 拷贝构造函数
支持通过另一个 string 对象进行拷贝初始化。
#include <iostream>
#include <string>
using namespace std;
int main() {
string original = "Hello C++";
string str(original); // 调用拷贝构造函数
cout << "str: " << str << endl; // 输出 "Hello C++"
return 0;
}
二、string 类的容量操作
2.1 size
返回字符串的实际长度(字节数)。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World";
cout << "s.size(): " << s.size() << endl; // 输出 11
return 0;
}
2.2 capacity
返回当前为字符串分配的存储空间大小,通常大于或等于 size。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1("Hello World");
cout << "s1.capacity(): " << s1.capacity() << endl;
return 0;
}
2.3 empty
检查字符串是否为空,返回 bool 值。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "hello world";
string s2;
cout << "s1.empty(): " << s1.empty() << endl; // false
cout << "s2.empty(): " << s2.empty() << endl; // true
return 0;
}
2.4 clear
清空字符串内容,使其变为空串,但可能保留原有容量。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World";
s.clear();
cout << "After clear, s: " << s << endl; // 输出空
cout << "s.size(): " << s.size() << endl; // 输出 0
cout << "s.capacity(): " << s.capacity() << endl; // 容量可能不变
return 0;
}
2.5 reserve
请求将字符串容量调整为至少 n 个字符。这不会改变字符串长度,仅影响底层内存分配,常用于避免频繁扩容。
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1;
string str2;
cout << "=== 不使用 reserve ===" << endl;
cout << "初始 str1 容量:" << str1.capacity() << ", 长度:" << str1.length() << endl;
str1 = "This is a demonstration of the string reserve function in C++.";
cout << "赋值后 str1 容量:" << str1.capacity() << ", 长度:" << str1.length() << endl;
cout << "\n=== 使用 reserve ===" << endl;
cout << "初始 str2 容量:" << str2.capacity() << ", 长度:" << str2.length() << endl;
str2.reserve(100); // 预先分配至少 100 个字符的内存
cout << "reserve(100) 后,str2 容量:" << str2.capacity() << ", 长度:" << str2.length() << endl;
str2 = "This is a demonstration of the string reserve function in C++.";
cout << "赋值后 str2 容量:" << str2.capacity() << ", 长度:" << str2.length() << endl;
return 0;
}
2.6 resize
调整字符串的实际长度。若新长度小于原长度则截断;若大于则填充(可指定填充字符)。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello C";
s.resize(9, '+'); // 扩展至 9 个字符,不足部分用 '+' 填充
cout << "s: " << s << endl; // 输出 "Hello++++"
cout << "s.size(): " << s.size() << endl;
s.resize(5); // 截断至 5 字符
cout << "s: " << s << endl; // 输出 "Hello"
cout << "s.size(): " << s.size() << endl;
return 0;
}
三、string 类的访问及遍历操作
3.1 operator[]
支持下标访问,返回字符引用,可读写。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s2("hello world");
cout << "下标访问元素:";
for (int i = 0; i < s2.size(); i++) {
cout << s2[i] << " ";
}
s2[0] = 'H';
cout << "\n更改后下标位置 2 处的字符串:";
for (int i = 0; i < s2.size(); i++) {
cout << s2[i] << " ";
}
return 0;
}
3.2 迭代器获取:begin 和 end
通过迭代器可以遍历并修改字符串内容。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s2("hello world");
cout << "迭代器访问元素:";
string::iterator it = s2.begin();
while (it != s2.end()) {
cout << *it << " ";
++it;
}
cout << "\n利用迭代器更改元素:";
it = s2.begin();
while (it != s2.end()) {
*it += 2;
cout << *it << " ";
++it;
}
return 0;
}
3.3 范围 for 循环
现代 C++ 推荐写法,简洁且高效。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s2("hello world");
cout << "范围 for 循环访问元素:";
for (auto& ch : s2) {
cout << ch << " ";
}
cout << "\n范围 for 循环更改元素:";
for (auto& ch : s2) {
ch += 2;
cout << ch << " ";
}
return 0;
}
四、string 类的修改操作
4.1 push_back
向字符串末尾追加单个字符。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s("hello world");
cout << "尾插前的 s:" << s << endl;
s.push_back(' ');
s.push_back('s');
cout << "push_back 尾插字符后的 s:" << s << endl;
return 0;
}
4.2 operator+= 和 append
operator+= 更常用,支持追加字符、C 字符串或 string 对象;append 功能类似但略显繁琐。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s("hello world");
cout << "尾插前的 s:" << s << endl;
s += 'x';
cout << "尾插单个字符的 s:" << s << endl;
s += " Welcome";
cout << "尾插 C 类型字符串后的 s:" << s << endl;
string s2(" Hello C++");
s += s2;
cout << "尾插字符串 s2 后的 s:" << s << endl;
return 0;
}
4.3 c_str
转换为 C 风格字符串指针,常用于与旧 API 交互。
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
string s = "C++";
const char* p = s.c_str();
cout << "C-string: " << p << endl;
cout << "Length via strlen: " << strlen(p) << endl;
return 0;
}
4.4 find
查找子串或字符首次出现的位置,未找到返回 string::npos。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s("text.cpp.zip");
size_t pos1 = s.find('.');
cout << "字符串 s 中 . 的位置为:" << pos1 << endl;
size_t pos2 = s.find("cpp");
cout << "字符串 s 中 cpp 的位置为:" << pos2 << endl;
size_t pos3 = s.find("C++");
if (pos3 == string::npos) {
cout << "Not find!" << endl;
}
return 0;
}
4.5 substr
截取子字符串,返回新的 string 对象。
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "We think in generalities, but we live in details.";
string str2 = str.substr(3, 5); // "think"
cout << "截取得到下标从 3 开始之后的五个字符:" << str2 << endl;
size_t pos = str.find("live");
string str3 = str.substr(pos); // 从 "live" 到结尾
cout << "截取 pos 位置之后的字符串:" << str3 << '\n';
return 0;
}
4.6 insert
在指定位置插入内容。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s("hello world");
cout << "尾插前的 s:" << s << endl;
s.insert(0, " Byte ");
cout << "insert 在下标 0 处插入字符串后的 s:" << s << endl;
string s2(" Welcome to C++");
size_t pos = s.size();
s.insert(pos, s2);
cout << "insert 在下标 pos 处插入字符串后的 s:" << s << endl;
s.insert(0, 5, '6');
cout << "insert 在下标 0 处插入 5 个字符后的 s:" << s << endl;
return 0;
}
4.7 erase
删除指定范围的字符。
#include <iostream>
#include <string>
using namespace std;
int main() {
string str("This is an example sentence.");
cout << str << '\n';
// 从索引 10 开始,删除 8 个字符
str.erase(10, 8);
cout << str << '\n';
return 0;
}
五、string 类的非成员函数
5.1 operator+
用于拼接两个字符串,返回新对象。
#include <iostream>
#include <string>
using namespace std;
int main() {
string firstlevel("com");
string secondlevel("cplusplus");
string scheme("http://");
string hostname;
string url;
hostname = "www." + secondlevel + '.' + firstlevel;
url = scheme + hostname;
cout << url << '\n';
return 0;
}
5.2 operator>> 和 operator<<
标准输入输出流的重载,>> 遇空格停止,<< 直接输出。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "Enter a word: ";
cin >> s;
cout << "You entered: " << s << endl;
string name = "Alice";
cout << "Name: " << name << endl;
return 0;
}
5.3 getline
读取整行输入,包括空格,直到遇到换行符或指定分隔符。
#include <iostream>
#include <string>
using namespace std;
int main() {
string line;
cout << "Enter a line: ";
getline(cin, line);
cout << "Line: " << line << endl;
getline(cin, line, ';');
cout << "Until ';': " << line << endl;
return 0;
}
5.4 字符串大小比较
支持字典序比较(==, !=, <, >, <=, >=)。
#include <iostream>
#include <string>
using namespace std;
int main() {
string foo = "alpha";
string bar = "beta";
if (foo == bar) cout << "foo and bar are equal\n";
if (foo != bar) cout << "foo and bar are not equal\n";
if (foo < bar) cout << "foo is less than bar\n";
if (foo > bar) cout << "foo is greater than bar\n";
if (foo <= bar) cout << "foo is less than or equal to bar\n";
if (foo >= bar) cout << "foo is greater than or equal to bar\n";
return 0;
}


