std::begin对std::string数组的适配问题及多字符串搜索grep替代方案咨询
问题1:std::begin对动态传入的数组无效的原因及替代方案
C++中数组作为函数参数传递时会自动退化为指针,std::begin/std::end依赖编译期已知的数组长度信息才能工作,定义在局部作用域的静态数组长度对编译器可见,所以可以正常调用;但退化为指针后丢失了长度信息,因此无法调用。
最简单的替代方案有两种:
- 改用
std::vector<std::string>传递关键词列表,无需额外处理长度问题 - 如果要保留数组传参,可以用模板固定数组长度:
template<size_t N> bool contains(const std::string& input, const std::string (&keywords)[N]) { return std::any_of(std::begin(keywords), std::end(keywords), [&](const std::string& str) {return input.find(str) != std::string::npos; }); }
C++20及以上版本也可以用std::span<const std::string>作为参数,同时兼容数组、vector等多种连续容器输入,无需重复写模板。
多关键词搜索不需要复杂的grep实现或者正则,上面的实现已经足够精简高效,完全覆盖日常使用需求。
问题2:vector版本contains无法正常工作的原因
你给出的vector版本逻辑本身没有错误,运行异常大概率是调用侧的问题,常见原因包括:
- 传入的vector为空
- 关键词拼写、大小写和目标内容不匹配
- 函数参数是值传递,虽然不影响逻辑,但会产生不必要的字符串拷贝,建议改为常量引用减少开销:
const std::vector<std::string>& keywords
参数包版本的正确实现
你之前写的参数包代码有两个错误:基函数中打印了不存在的变量var1,递归逻辑没有处理多参数的比较逻辑。C++17及以上可以用折叠表达式实现更简洁的版本:
// 检查是否包含任意一个关键词 template<typename... Args> bool contains(const std::string& input, const Args&... keywords) { static_assert((std::is_same_v<std::decay_t<Args>, std::string> && ...), "所有关键词必须是std::string类型"); return ((input.find(keywords) != std::string::npos) || ...); } // 查找所有关键词中第一个出现的位置 template<typename... Args> size_t find_first_of(const std::string& line, size_t pos, const Args&... keywords) { size_t min_pos = std::string::npos; auto update_min = [&](const std::string& kw) { size_t cur = line.find(kw, pos); if (cur != std::string::npos && cur < min_pos) min_pos = cur; }; (update_min(keywords), ...); return min_pos; }
如果需要兼容C++11/14,把折叠表达式替换为递归的参数包逻辑即可。
原有find函数的bug提示
你最开始写的find函数存在几个明显逻辑问题,容易触发异常:
- 把
line.find返回的无符号size_t转为int,长字符串场景下会发生溢出 - 没有处理
find返回std::string::npos(未找到)的情况,且判断eol2>0会漏掉关键词出现在字符串开头(索引0)的场景 - 默认返回两个索引中较大的值,不符合常规多关键词查找返回第一个出现位置的需求,注意根据你的业务逻辑调整判断条件
内容的提问来源于stack exchange,提问作者MathArt
相关产品推荐
相关产品推荐

