std::string::find找不到子串时返回std::string::npos(非-1或0),找到则返回首个字符下标;应显式与npos比较,避免类型转换错误;find匹配完整子串,find_first_of查找字符集合中任一字符;c++23新增contains仅作语法糖。

std::string::find 返回值怎么判断是否找到子串
find 找不到时返回 std::string::npos,不是 -1,也不是 0。这是最常踩的坑:直接拿返回值和 0 或 -1 比较会出错。
正确写法是显式和 std::string::npos 比较:
std::string s = "hello world";
if (s.find("world") != std::string::npos) {
// 找到了
}
-
find找到时返回子串**首个字符的下标(从 0 开始)**,可能为0(比如"abc".find("a") == 0) -
std::string::npos是一个静态常量,类型是size_t,值通常为static_cast<size_t>(-1)</size_t>,但绝不该手动写成-1 - 如果用
int pos = s.find(...)接收,可能因符号扩展或截断导致误判(size_t到int不安全)
find 和 find_first_of 有什么区别
名字像,行为完全不同:find 是找**完整连续子串**;find_first_of 是在字符串中找**任意一个指定字符**首次出现的位置。
-
"abccba".find("bc")→ 返回1(匹配整个"bc") -
"abccba".find_first_of("bc")→ 返回1(第一个是'b',位置 1) -
"acacca".find_first_of("bc")→ 返回1(第一个'c'在位置 1,'b'根本没出现) - 想查“是否含某字符集合中的任一字符”,用
find_first_of;想查“是否含某段固定文本”,必须用find
不区分大小写的子串查找怎么做
std::string::find 本身不支持忽略大小写,得自己处理。常见做法是把主串和子串都转成同一大小写后再查。
立即学习“C++免费学习笔记(深入)”;
- 推荐用
std::tolower配合std::transform构造临时小写副本(注意 locale 安全性,简单 ASCII 场景够用) - 不要原地修改原字符串,除非你确定不需要它了
- 性能敏感场景避免反复构造新字符串,可手写循环逐字符比较(转小写后比)
示例(ASCII 安全):
std::string lower_s = s;
std::string lower_sub = sub;
std::transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower);
std::transform(lower_sub.begin(), lower_sub.end(), lower_sub.begin(), ::tolower);
if (lower_s.find(lower_sub) != std::string::npos) { ... }
find 在 C++23 里有替代方案吗
C++23 引入了 std::string::contains,语义更清晰,直接返回 bool:
if (s.contains("xyz")) { ... } // C++23 起可用
但它只是 find != npos 的语法糖,底层仍调用 find。目前主流编译器(GCC 13+、Clang 16+、MSVC 19.35+)已支持,但若项目需兼容 C++17/C++20,还是得用 find。
另外注意:contains 只接受 std::string_view 或 C 字符串字面量,不支持其他容器;而 find 参数类型更灵活(支持 string_view、C 字符串、单字符、甚至带长度的字符指针)。
真正容易被忽略的是:所有这些函数对空字符串的处理——s.find("") 总是返回 0,即认为空串是任何字符串的子串(包括空串自身),这符合标准定义,但有时不符合业务直觉。










