std::string::find 是判断子串存在的最直接方法,返回位置或 std::string::npos;注意 npos 不可与 -1 比较,且需关注 std::string_view 的生命周期和 std::search 的定制匹配场景。

用 std::string::find 判断子串是否存在最直接
绝大多数情况下,std::string::find 是首选:它返回子串首次出现的位置(size_t 类型),没找到时返回 std::string::npos。注意 npos 是一个极大值(通常是 size_t 的最大值),**不能和 -1 比较**——这是新手最常踩的坑。
示例:
立即学习“C++免费学习笔记(深入)”;
std::string s = "hello world";
if (s.find("world") != std::string::npos) {
// 找到了
}-
find区分大小写;如需忽略大小写,得自己转小写或用std::search配合std::tolower谓词 - 搜索起始位置可传第二个参数(如
s.find("o", 5)),适合多次查找 - 对空字符串
"",find总是返回0(C++11 起标准规定)
用 std::string_view::find 更轻量,但要注意生命周期
如果原始字符串是只读且已存在(比如函数参数、全局 const 字符串),用 std::string_view 替代 std::string 能避免拷贝,性能更好。它的 find 行为和 std::string 一致。
示例:
立即学习“C++免费学习笔记(深入)”;
void check(const std::string_view sv) {
if (sv.find("error") != std::string_view::npos) { /* ... */ }
}
// 调用:check("network error"); // OK
// 但别这样:std::string s = "temp"; check(s); s.clear(); // sv 可能悬空-
string_view不拥有数据,必须确保它引用的内存在整个使用期间有效 - C++17 起才支持,老项目需确认编译器版本(GCC 7+/Clang 5+/MSVC 2017)
- 不支持
substr等修改操作,纯用于查看和查找
用 std::search 做更灵活的匹配(比如自定义比较)
当需要忽略大小写、按 Unicode 规则比较、或匹配某种模式(非纯子串)时,std::search 更合适。它在一对迭代器范围内查找另一段迭代器所指的序列,支持传入二元谓词。
示例(忽略大小写的子串查找):
#include <algorithm>
#include <cctype>
<p>bool icase_equal(char a, char b) {
return std::tolower(a) == std::tolower(b);
}</p><p>std::string s = "Hello WORLD";
std::string target = "world";
auto it = std::search(s.begin(), s.end(),
target.begin(), target.end(),
icase_equal);
if (it != s.end()) {
// 找到了,it 指向匹配起点
}- 比
find开销略大,仅在需要定制逻辑时用 - 目标序列可以是任意迭代器范围(比如
std::vector<char>),不限于std::string - 没有内置的“是否包含”布尔接口,得手动判断返回迭代器是否等于
end()
别用 strstr 或手写循环,除非有特殊约束
strstr 是 C 风格函数,要求输入是 null-terminated 的 const char*。用它前得调用 c_str(),且无法处理含 '\0' 的字符串(std::string 允许内部含空字符)。手写 for 循环不仅易错,还容易漏掉边界检查或性能低下(比如未用 KMP 优化)。
- 除非在嵌入式环境禁用 STL,否则没必要绕开
find -
strstr返回指针,需转换为索引再判断是否为空,多一步且不直观 - 所有标准库方案都已做充分优化,
find在多数实现中就是朴素匹配 + 小字符串快速路径,够用
真正要注意的是:别把 npos 当成 -1 用,也别在 string_view 上忽视数据生命周期——这两点出错时调试起来最花时间。


















