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

Mor*_*eu5 8 c++ regex c++11

我对以下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;
}
Run Code Online (Sandbox Code Playgroud)

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

Wik*_*żew 9

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

matches是......:

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

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

这是一个可以找到多个匹配项的代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

请参阅IDEONE演示返回abc3次.

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

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;
}
Run Code Online (Sandbox Code Playgroud)

请参阅IDEONE演示,返回

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
Run Code Online (Sandbox Code Playgroud)


Arn*_*gel -1

编辑:有些人否决了这个答案。这可能有多种原因,但如果是因为它不适用于我批评的答案(没有人留下评论来解释这一决定),他们应该注意 W. Stribizew 在我两个月后更改了代码写了这篇文章,直到今天,2021-01-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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

for (int j = 0; j < 20; ++j)
    str = str + str;
Run Code Online (Sandbox Code Playgroud)