string::find 查找成功时返回子串首次出现的起始下标(从0开始),失败时返回string::npos;该值为size_t类型的最大值,非-1,故判断必须用== string::npos而非== -1。

string::find 返回什么值?
string::find 查找成功时返回子串首次出现的起始下标(从 0 开始),失败时返回 string::npos。这不是 -1,而是一个无符号整数最大值(通常是 size_t 类型的全 1 值),所以不能直接和 -1 比较。
常见错误写法:if (s.find("abc") == -1) —— 这会把 -1 转成很大的正数,永远不成立。
正确判断方式只有这一种:if (s.find("abc") == string::npos)。
find 的重载形式与常用参数组合
最常用的是两个重载:
立即学习“C++免费学习笔记(深入)”;
-
s.find(sub):从开头查找整个sub -
s.find(sub, pos):从位置pos开始向后查找(pos超出长度时自动按npos处理)
注意:sub 可以是 string、const char* 或单个 char;pos 类型是 size_t,传负数会隐式转成极大正数,导致行为异常。
示例:s.find("x", 5) 表示跳过前 5 个字符再找;s.find('a') 查单个字符,效率略高于构造临时 string。
为什么 find 找不到时不能用
因为返回类型是 size_t(无符号),任何负数比较都会被提升为无符号数。比如 string::npos == -1 在某些平台可能为 true,但这是巧合,不是标准行为。
更危险的是:if (s.find("x") 永远为 false —— 编译器通常会警告「比较无符号数与 0」,但若忽略,逻辑就彻底错了。
其他易错点:
- 用
int接收返回值(如int i = s.find("x")):当结果是npos时,截断导致值变成 -1,看似“能用”,但一旦字符串长度超过INT_MAX就崩 - 在循环中反复调用
find却没更新pos,导致无限循环
查找所有匹配位置的惯用写法
要遍历全部匹配,必须手动推进查找起点:
size_t pos = 0;
while ((pos = s.find("ab", pos)) != string::npos) {
cout << "found at " << pos << endl;
pos += 1; // 或 += "ab".length(),取决于是否允许重叠匹配
}
关键点:
- 赋值和判断必须写在同一条件里,否则
pos不会更新 - 推进步长决定是否重叠:查 "aaa" 中 "aa",用
pos += 1可找到位置 0 和 1;用pos += 2只找到 0 - 别用
pos++代替pos += sub.length(),除非明确要重叠匹配
实际项目中,如果需要频繁查找或支持正则,find 很快会不够用——它不支持模式、不支持反向、也不返回迭代器,这时候该考虑 std::regex 或第三方库了。










