string::find 查找成功时返回子串首次出现的起始下标(从0开始),失败时返回string::npos;该值为size_t类型的最大值,非-1,故判断必须用== string::npos而非== -1。
string::find 查找成功时返回子串首次出现的起始下标(从 0 开始),失败时返回 string::npos。这不是 -1,而是一个无符号整数最大值(通常是 size_t 类型的全 1 值),所以不能直接和 -1 比较。
常见错误写法: if (s.find("abc" —— 这会把 -1 转成很大的正数,永远不成立。
正确判断方式只有这一种:if (s.find("abc") == string::npos)。
最常用的是两个重载:
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。
因为返回类型是 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 不会更新pos += 1 可找到位置 0 和 1;用 pos += 2 只找到 0pos++ 代替 pos += sub.length(),除非明确要重叠匹配实际项目中,如果需要频繁查找或支持正则,find 很快会不够用——它不支持模式、不支持反向、也不返回迭代器,这时候该考虑 std::regex 或第三方库了。