std::string::find 查不到子串时返回 std::string::npos,需用 != npos 判断;replace 仅替换首次匹配,全局替换需循环并更新位置;反转应使用 std::reverse。

std::string::find 查不到子串?检查返回值是不是 std::string::npos
很多新手写 find 后直接当 bool 用,结果逻辑翻车。它不返回 0/1,而是在没找到时返回一个特殊常量 std::string::npos(通常是 size_t 类型的最大值)。拿它跟 0 或 false 比,几乎一定出错。
- 正确判断方式:
if (s.find("abc") != std::string::npos) - 注意类型:返回值是
size_t,别用int接收,否则在 64 位系统上可能截断或符号扩展出问题 - 区分大小写:
find默认严格匹配,要忽略大小写得自己转小写或用std::search配合std::tolower - 性能提示:
find是朴素 O(nm) 算法,长文本搜长模式别指望它快;真有性能要求,换std::boyer_moore_searcher(C++17)
用 std::string::replace 替换所有匹配项,别只调一次
replace 只替换第一次出现的位置,不是正则那种“全局替换”。想替所有,得循环找 + 替,但要注意下标更新,否则容易无限循环或越界。
- 安全做法:从前往后找,每次替换后把搜索起点设为
pos + new_str.length()(不是原长度) - 避免迭代器失效:不要边遍历边
replace,std::string内部可能 realloc,所有迭代器立即失效 - 更稳的替代:先用
find收集所有位置,再倒序替换(避免下标偏移),或直接构造新字符串 - 示例片段:
while ((pos = s.find(old_str, pos)) != std::string::npos) { s.replace(pos, old_str.length(), new_str); pos += new_str.length(); }
反转字符串用 std::reverse,别手写 for 循环交换
手写双指针虽然能跑通,但易错、可读性差,还容易忘边界条件(比如 i 还是 <code>i )。标准库的 <code>std::reverse 经过充分测试,支持任意迭代器,且编译器通常能内联优化。
- 正确用法:
std::reverse(s.begin(), s.end())—— 注意是左闭右开区间 - 别传字符数组地址:比如
std::reverse(&arr[0], &arr[n])虽然语法对,但不如用std::span(C++20)或明确长度更安全 - 性能无差别:它就是个封装好的双指针,没有额外开销
- 如果只是想反向遍历,用
rbegin()/rend()更轻量,不用改原字符串
截取子串用 substr,但小心越界和参数顺序
substr 两个参数:起始位置 pos 和长度 count。很多人误以为第二个参数是结束位置,结果截出空串或抛异常。
立即学习“C++免费学习笔记(深入)”;
- 越界行为:
pos > size()直接抛std::out_of_range;pos == size()返回空串;count超出剩余长度会自动截断到末尾 - 安全写法:先检查
if (pos ,再调 <code>s.substr(pos, count) - 常用场景简化:
s.substr(pos)表示从 pos 到结尾;s.substr(0, n)表示前 n 个字符 - 注意:C++20 前没有“从右往左截”的内置方法,想取后 n 个得写
s.substr(s.length() - n),记得判长度
这些操作看着简单,但 npos 的语义、substr 的越界规则、replace 的单次性,都是实际调试时卡半小时的点。尤其在跨平台或处理用户输入时,边界稍一松动就崩。


















