string::find找不到子串时返回string::npos;这是size_t类型的最大值,不能与-1直接比较,正确判断应为s.find("abc")==string::npos。

string::find 找不到子串时返回什么
string::find 没找到子串,不返回 -1,而是返回 string::npos —— 这是个无符号整数(通常是 size_t 类型的最大值),直接跟 -1 比较会出问题。
常见错误现象:
写成 if (s.find("abc") == -1),结果永远为假,因为 string::npos 转成有符号 int 是个巨大正数,不是 -1。
- 正确判断方式:用
if (s.find("abc") == string::npos) - 别用
int pos = s.find(...)接收返回值,应声明为size_t pos - 如果后续要当索引用(比如传给
substr),必须先确认不是npos,否则越界
find 重载版本太多,该选哪个
最常用的是从头开始找:s.find(substr);但实际场景常需要控制起点或限定长度。
- 从位置
pos开始搜:s.find(substr, pos),pos超过s.length()会直接返回npos - 只在前
count个字符里搜:s.find(substr, pos, count),注意第三个参数是「搜索范围长度」,不是子串长度 - 搜 C 风格字符串:
s.find("abc")和s.find(string("abc"))效率不同,前者免构造临时string,更推荐
find 不区分大小写?没有内置支持
string::find 是纯字节匹配,完全不处理大小写。想实现忽略大小写的查找,得自己处理。
立即学习“C++免费学习笔记(深入)”;
- 简单做法:把原字符串和目标子串都转成小写(或大写)再查,但要注意拷贝开销
- 高效做法:手写循环比对,用
std::tolower逐字符比较,避免额外分配 - 别用
std::search+std::toupper谓词——容易因 locale 导致行为不一致,尤其处理非 ASCII 字符时
性能陷阱:反复调用 find 可能 O(n²)
如果在循环里不断用 find 查同一个子串(比如分隔字符串),每次都是从头扫,效率很低。
- 替代方案:用
string_view+ 手动推进起始位置,避免重复扫描已知不匹配区域 - 更稳的选择:改用
std::string::find_first_of或find_last_of做字符集查找(如找分隔符) - 极端情况(大量文本+高频查找):考虑
std::boyer_moore_searcher(C++17),但要注意它只适用于固定模式,且构建 searcher 有开销
真正麻烦的不是语法,是 npos 的类型语义、大小写逻辑的归属边界,还有那个看似无害却悄悄吃掉性能的“从头开始”。











