如何用C++查找文本中所有笑脸符号(:)、:-])的起始位置
C++ 查找所有笑脸符号的起始位置问题
问题说明
需要在文本中找出所有笑脸符号(:)、:-])的起始位置,但现有代码仅能找到第一个匹配项,且输出了无效的分组内容。
原代码
#include <iostream> #include <string> #include <regex> int main () { std::string s ("Best :) bookseller :) today. :-]"); std::smatch m; std::regex e (":\\)|:\\-\\]"); if (std::regex_search(s, m, e)) { std::cout << "matched" << std::endl; std::cout << m[0] << " -> " << m.position(0) << std::endl; std::cout << m[1] << " -> " << m.position(1) << std::endl; std::cout << m[2] << " -> " << m.position(2) << std::endl; } else std::cout << "not matched" << std::endl; return 0; }
预期输出
matched :) -> 5 :) -> 19 :-] -> 29
实际输出
matched :) -> 5 -> 32 -> 32
问题原因
std::regex_search默认只查找第一个匹配项,不会遍历所有结果;- 正则表达式没有定义捕获分组(未用
()包裹子模式),所以m[1]和m[2]是无效的空匹配,position()返回字符串总长度(32)。
正确实现
要遍历所有匹配项,需循环调用regex_search,每次从上次匹配的结束位置继续搜索。正则表达式无需修改,它已能正确匹配两种笑脸模式。
修改后的代码:
#include <iostream> #include <string> #include <regex> int main () { std::string s ("Best :) bookseller :) today. :-]"); std::smatch m; std::regex e (":\\)|:\\-\\]"); std::cout << "matched" << std::endl; // 从字符串起始位置开始搜索 auto search_start = s.cbegin(); while (std::regex_search(search_start, s.cend(), m, e)) { // 输出当前匹配的内容和原字符串中的绝对起始位置 std::cout << m[0] << " -> " << m.position(0) + (search_start - s.cbegin()) << std::endl; // 更新搜索起始位置为当前匹配的结束位置 search_start = m.suffix().first; } return 0; }
输出结果
matched :) -> 5 :) -> 19 :-] -> 29
关键说明
- 用
search_start变量记录每次搜索的起始位置,初始为字符串开头; - 每次匹配后,将
search_start更新为m.suffix().first(当前匹配之后的第一个字符); - 计算绝对位置时,需加上
search_start - s.cbegin(),因为m.position(0)是相对于当前搜索起始位置的偏移量,转换后才能得到原字符串中的真实位置。
内容的提问来源于stack exchange,提问作者jack sparow
相关产品推荐
相关产品推荐

