std::match_results::size返回什么?

What does std::match_results::size return?

本文关键字:返回 什么 size results match std      更新时间:2023-10-16

我对下面的c++ 11代码有点困惑:

#include <iostream>
#include <string>
#include <regex>
int main()
{
    std::string haystack("abcdefabcghiabc");
    std::regex needle("abc");
    std::smatch matches;
    std::regex_search(haystack, matches, needle);
    std::cout << matches.size() << std::endl;
}

我希望它打印出3,但我得到的是1。我错过什么了吗?

您得到1,因为regex_search只返回1个匹配,而size()将返回捕获组的数量+整个匹配值。

你的matches是…

match_results类型的对象(如cmatch或smatch),由该函数填充有关匹配结果和找到的任何子匹配的信息。

如果[regex搜索]成功,它不是空的,并且包含一系列sub_match对象:第一个sub_match元素对应于整个匹配,并且,如果regex表达式包含要匹配的子表达式(即,括号分隔的组),它们对应的子匹配将作为连续的sub_match元素存储在match_results对象中。

下面的代码将找到多个匹配项:

#include <string>
#include <iostream>
#include <regex>
using namespace std;
int main() {
  string str("abcdefabcghiabc");
  int i = 0;
  regex rgx1("abc");
  smatch smtch;
  while (regex_search(str, smtch, rgx1)) {
        std::cout << i << ": " << smtch[0] << std::endl;
        i += 1;
        str = smtch.suffix().str();
  }
  return 0;
}

参见IDEONE demo返回abc 3次

由于此方法破坏了输入字符串,因此这里是基于std::sregex_iterator的另一种选择(当您的主题是std::wstring对象时应使用std::wsregex_iterator):

int main() {
    std::regex r("ab(c)");
    std::string s = "abcdefabcghiabc";
    for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
                             i != std::sregex_iterator();
                             ++i)
    {
        std::smatch m = *i;
        std::cout << "Match value: " << m.str() << " at Position " << m.position() << 'n';
        std::cout << "    Capture: " << m[1].str() << " at Position " << m.position(1) << 'n';
    }
    return 0;
}

参见IDEONE demo,返回

Match value: abc at Position 0
    Capture: c at Position 2
Match value: abc at Position 6
    Capture: c at Position 8
Match value: abc at Position 12
    Capture: c at Position 14

您缺少的是matches为每个捕获组填充了一个条目(包括作为第0个捕获的整个匹配子字符串)。

如果你写

std::regex needle("a(b)c");

然后你会得到matches.size()==2, matches[0]=="abc",和matches[1]=="b"

EDIT:有人对这个答案投了反对票。这可能有多种原因,但如果是因为它不适用于我批评的答案(没有人留下评论来解释这个决定),他们应该注意到W. Stribizew在我写这篇文章两个月后修改了代码,而我直到今天才知道,2021年1月18日。答案的其余部分与我第一次写它时一样。

对于相同的正则表达式,

@stribizhev的解具有二次最坏情况复杂度。对于疯狂的(例如"y*"),它不会终止。在某些应用程序中,这些问题可能是等待发生的DoS攻击。下面是一个固定的版本:

string str("abcdefabcghiabc");
int i = 0;
regex rgx1("abc");
smatch smtch;
auto beg = str.cbegin();
while (regex_search(beg, str.cend(), smtch, rgx1)) {
    std::cout << i << ": " << smtch[0] << std::endl;
    i += 1;
    if ( smtch.length(0) > 0 )
        std::advance(beg, smtch.length(0));
    else if ( beg != str.cend() )
        ++beg;
    else
        break;
}

根据我的个人偏好,这将在长度为n的字符串中找到n+1个空正则表达式匹配。您也可以在空匹配后退出循环。

如果您想比较具有数百万个匹配的字符串的性能,请在str的定义之后添加以下行(不要忘记打开优化),每个版本添加一次:

for (int j = 0; j < 20; ++j)
    str = str + str;