📌 基础操作
#include <string>
using namespace std;
string s1; // 空字符串
string s2 = "hello"; // 直接初始化
string s3(5, 'a'); // "aaaaa"
string s4(s2, 1, 3); // "ell"(从下标1开始取3个字符)
🚀 高频使用操作
1. 访问元素
s[0] = 'H'; // 修改首字符(不检查越界)
s.at(1) = 'E'; // 带越界检查的访问
s.front(); // 首字符(等价于s[0])
s.back(); // 末尾字符
2. 字符串拼接
string s = "Hello";
s += " World"; // "Hello World"
s.append("!!!"); // "Hello World!!!"
s.push_back('!'); // 追加单个字符
3. 子串操作
string sub = s.substr(6, 5); // "World"(位置6开始取5个字符)
s.substr(6); // "World!!!"(从6到末尾)
4. 查找操作
int pos = s.find("World"); // 返回首次出现位置(6)
pos = s.find("word"); // string::npos(未找到)
pos = s.rfind("l"); // 从后向前查找(返回最后一个'l'的位置)
🔧 算法竞赛实用技巧
1. 快速分割字符串
string data = "apple,orange,banana";
size_t pos = 0;
while ((pos = data.find(',')) != string::npos) {
string token = data.substr(0, pos);
cout << token << endl;
data.erase(0, pos + 1);
}
cout << data << endl; // 最后一个元素
2. 字符串与数值转换
// C++11标准方法
int num = stoi("42");
double d = stod("3.14");
string s_num = to_string(123);
// 传统C方法(更快但危险)
int num = atoi("42"); // 需要c_str()
3. 大小写转换
for (char &c : s) {
c = toupper(c); // 转大写
// c = tolower(c); // 转小写
}
4. 字符串流处理
#include <sstream>
string input = "123 3.14 hello";
istringstream iss(input);
int a; double b; string c;
iss >> a >> b >> c; // a=123, b=3.14, c="hello"
⚡️ 性能优化技巧
1. 预分配空间
string s;
s.reserve(1000); // 预分配内存,避免频繁扩容
2. 移动语义(C++11+)
string get_string() {
string tmp(1000000, 'x');
return tmp; // 触发移动构造而非拷贝
}
🏆 竞赛常见应用
1. 回文判断
bool is_palindrome(const string &s) {
return equal(s.begin(), s.end(), s.rbegin());
}
2. 字符串旋转
string rotate(const string &s, int k) {
string res = s;
rotate(res.begin(), res.begin() + k % res.size(), res.end());
return res;
}
3. KMP算法实现
vector<int> compute_lps(const string &pattern) {
vector<int> lps(pattern.size());
for (int i = 1, len = 0; i < pattern.size(); ) {
if (pattern[i] == pattern[len]) lps[i++] = ++len;
else if (len) len = lps[len-1];
else lps[i++] = 0;
}
return lps;
}
⚠️ 常见错误
-
越界访问
string s = "hello"; char c = s[10]; // 未定义行为!
-
混淆size()和length()
// 虽然功能相同,但建议统一使用size() for (int i = 0; i < s.size(); ++i) {...}
-
忽略npos的类型
if (s.find("x") == -1) {...} // 错误!npos是size_t类型 if (s.find("x") == string::npos) {...} // 正确
📊 与其他语言对比
操作 | C++ (string) | Python (str) | Java (String) |
---|---|---|---|
拼接 | s1 + s2 | s1 + s2 | s1.concat(s2) |
查找子串 | find() | find() | indexOf() |
长度 | s.size() | len(s) | s.length() |
切片 | substr(pos, len) | s[start:end] | substring(b,e) |
📌 竞赛建议:将常用字符串操作封装成函数模板,如split()/join(),可节省编码时间