尝试在C++中查找正则表达式匹配数,返回零

kzipqqlq  于 2023-02-06  发布在  其他
关注(0)|答案(3)|浏览(129)

我实现了下面的代码来尝试计算给定字符串中的匹配数;在这种情况下,它应该是1。

#include <iostream>
#include <string>
#include <regex>

unsigned countMatches(std::string text, std::regex expr);
    
int main()
{
    std::string phrase = "Hello world";

    std::regex pattern = std::regex("world");

    std::cout << countMatches(phrase, pattern) << std::endl;
    
    return 0;
}

unsigned countMatches(std::string text, std::regex expr)
{
    std::smatch matches;
    
    while(std::regex_search(text, matches, expr))
    text = matches.suffix().str();
   
    return matches.size();
}

然而,它总是打印0,我不明白为什么。

xt0899hw

xt0899hw1#

然而,它总是打印0,我不明白为什么。
你在while循环中调用regex_search,循环体(即使错误地缩进)正在更新text,第一次迭代确实找到了1个匹配项,但随后你将text更新为空字符串(匹配项的后缀),在下一次迭代中没有匹配项,这就是你的函数返回的值。
相反,您应该累积匹配的数量:

#include <iostream>
#include <string>
#include <regex>

size_t countMatches(std::string text, std::regex const & expr)
{
    std::smatch matches;
    size_t result{ 0 };

    while (std::regex_search(text, matches, expr))
    {
        result += matches.size();  // <--- accumulate number of matches
        text = matches.suffix().str();
    }

    return result;
}

int main()
{
    std::string phrase = "Hello world";
    std::cout << countMatches(phrase, std::regex("world")) << std::endl;
    std::cout << countMatches(phrase, std::regex("o")) << std::endl;
    return 0;
}

输出:

1
2
    • 请注意**我将返回值更改为size_t,因为这是matches.size()的类型。我还将const &添加到expr参数以避免复制。
dzhpxtsq

dzhpxtsq2#

如果只想迭代输入字符串,并计算匹配的数量,可以使用std::sregex_iterator
Demo(https://godbolt.org/z/saxj8z8eK)

unsigned countMatches(const std::string& text, std::regex expr) {
    unsigned ret{};
    for (auto it = std::sregex_iterator(text.begin(), text.end(), expr);
        it != std::sregex_iterator{};
        ++it, ++ret);
    return ret;
}

// Outputs: 1
8i9zcol2

8i9zcol23#

典型的一行程序有专门的函数来解决这个问题。

  1. std::sregex_token_iteraor。这可以迭代由std::string中的std::regex定义的令牌。请参见here
  2. std::distance。这将使用2个迭代器,并计算从第一个迭代器到第二个迭代器的跳数。请参见here
    有了可用的constructors,我们将迭代器设置为第一个元素和最后一个元素,最后一个元素将使用默认的初始化器{}设置为空的默认构造函数(编号1)。
    std::distance将计算从第一个发现的令牌到最后一个发现的令牌之间的跳数,这就是发现的令牌总数,这就是结果。
    使用上面的代码,我们可以得到下面的一行代码:
#include <iostream>
#include <string>
#include <regex>
#include <iterator>

const std::string s{ "abcabcd abcde xab a b"};
const std::regex re{ "ab" };

int main() {
    std::cout << std::distance(std::sregex_token_iterator(s.begin(), s.end(), re), {});
}

相关问题