字符串处理是编程中最频繁的操作之一。C 的 char[] + strcpy/strlen 既啰嗦又容易越界;C++ 的 std::string 自动管理内存、支持运算符重载,一行顶 C 三行。本文带你掌握最常用的字符串操作。

1. 构造与基本操作

#include <string>
using namespace std;

string s1 = "hello";          // 字面量构造
string s2(5, 'a');            // "aaaaa"
string s3 = s1 + " world";    // 拼接:"hello world"

s3.push_back('!');            // 尾部加字符
s3 += "!!";                   // 追加字符串
int n = s3.length();          // 长度(与 size() 相同)
bool empty = s3.empty();
char c = s3[0];               // 下标访问,越界不检查
char c2 = s3.at(1);           // 越界抛 out_of_range

2. 拼接与比较

拼接直接用 +,比较直接用 ==/<(按字典序),告别 C 的 strcmp:

string a = "abc", b = "abd";
if (a < b) { /* abc 排在 abd 前面 */ }

// 字符串与数字混拼
int score = 95;
string msg = "分数: " + to_string(score);

3. 查找与子串

string s = "hello world, hello cpp";

size_t pos = s.find("world");     // 返回下标 6
if (pos != string::npos) {        // npos 表示"没找到"
    string sub = s.substr(6, 5);  // 从 6 开始取 5 个字符:"world"
}

// 反向查找、查找任一字符
size_t last = s.rfind("hello");   // 13
size_t comma = s.find_first_of(",;!");  // 11

// 用 find 循环统计子串出现次数
int cnt = 0;
pos = s.find("hello");
while (pos != string::npos) {
    ++cnt;
    pos = s.find("hello", pos + 1);
}

4. 数字与字符串互转

#include <string>
using namespace std;

// 数字 → 字符串
string a = to_string(3.14);   // "3.140000"
string b = to_string(42);     // "42"

// 字符串 → 数字(C++11 起,失败抛异常)
int i = stoi("42");           // 42
long l = stol("123456789");
double d = stod("3.14");
float f = stof("2.5f");

// 带进制解析
int hexv = stoi("ff", nullptr, 16);   // 255

老项目里常见的 atoi/atof 失败时不报错、返回 0,容易掩盖 bug;新代码优先用 stoi 系列。

5. 与 C 字符串互转

// C++ → C:只读,别修改返回值指向的内容
const char* cstr = s.c_str();

// C++ → C:可写副本
vector<char> buf(s.begin(), s.end());
buf.push_back('\0');          // C 字符串需要结尾 '\0'
char* writable = buf.data();

// C → C++:直接构造
const char* old = "from c";
string now(old);

6. 处理中文时的注意事项

操作说明
length()UTF-8 下返回字节数,不是字符数
s[0]取到的是字节,中文会取到半个字
substr按字节切,可能切开汉字
find("你")按字节序列查找,一般仍能正确找到

简单场景按字节处理没问题;要按"字符"处理中文,建议用 std::wstring 或第三方库(如 ICU)。

💡 练习:实现一个 split(s, delim) 函数把字符串按分隔符拆成 vector<string>,再实现 trim 去掉首尾空格。这两个工具函数在刷题和工程里天天用。