You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

问题原因

  1. std::regex_search 默认只查找第一个匹配项,不会遍历所有结果;
  2. 正则表达式没有定义捕获分组(未用()包裹子模式),所以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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:31:22