为什么Boost.Regex在一个字符串中找不到多个匹配项?

时间:2010-11-15 04:22:04

标签: c++ regex boost

我正在编写一个小命令行程序,要求用户输入形式为ax ^ 2 + bx ^ 1 + cx ^ 0的多项式。我将在稍后解析数据但是现在我只是想看看我是否可以将多项式与正则表达式匹配(\+|-|^)(\d*)x\^([0-9*]*)我的问题是,它与用户输入的多个术语不匹配多项式,除非我将其更改为((\+|-|^)(\d*)x\^([0-9*]*))*(不同之处在于整个表达式已分组且末尾有星号)。如果我输入“4x^2”而不是“4x^2+3x^1+2x^0”之类的内容,则第一个表达式有效,因为它不会多次检查。

我的问题是,为什么Boost.Regex的regex_match()在同一个字符串中找不到多个匹配?它在我使用的正则表达式编辑器(Expresso)中,但在实际的C ++代码中没有。它应该是那样的吗?

如果某些事情没有意义,请告诉我,我会尽力澄清。谢谢你的帮助。

Edit1:这是我的代码(我在这里遵循教程:http://onlamp.com/pub/a/onlamp/2006/04/06/boostregex.html?page=3

int main()
{
    string polynomial;

    cmatch matches; // matches

    regex re("((\\+|-|^)(\\d*)x\\^([0-9*]*))*");

    cout << "Please enter your polynomials in the form ax^2+bx^1+cx^0." << endl;

    cout << "Polynomial:";
    getline(cin, polynomial);

    if(regex_match(polynomial.c_str(), matches, re))
    {
        for(int i = 0; i < matches.size(); i++)
        {
            string match(matches[i].first, matches[i].second);
            cout << "\tmatches[" << i << "] = " << match << endl;
        }
    }

    system("PAUSE");
    return 0;
}

1 个答案:

答案 0 :(得分:7)

你使用的是错误的东西 - regex_match旨在检查(单个)正则表达式是否与整个字符序列匹配。因此,您需要指定与整个输入匹配的正则表达式,或者使用其他内容。对于您的情况,可能最有意义的是只修改正则表达式(将其分组并添加Kleene星)。如果你想迭代多项式的各个项,你可能想要使用类似regex_token_iterator的东西。

编辑:当然,既然你将它嵌入到C ++中,你还必须加倍所有的反斜杠。看着它,我也对你正在使用的正则表达式感到困惑 - 它并不像我认为它应该真的很合适。例如,似乎在术语开头需要一个“+”,“ - ”或“^”,但第一个术语通常不会有。我也有点不确定为什么在一个学期开头会有一个“^”。由于指数在零时通常被省略,因此最好允许它被省略。考虑到这些,我得到类似的东西:“[ - +]?(\ d *)x(\ ^([0-9])*)”。

将其纳入某些代码中,我们可以得到类似的结果:

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

int main() { 

    std::string poly = "4x^2+3x^1+2x";

    std::tr1::regex term("[-+]?(\\d*)x(\\^[0-9])*");

    std::copy(std::tr1::sregex_token_iterator(poly.begin(), poly.end(), term),
        std::tr1::sregex_token_iterator(), 
        std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}

至少在我看来,每个术语都会单独打印出来:

4倍^ 2
+ 3×^ 1
+ 2×

请注意,目前,我刚刚打印出每个完整的字词,并修改了您的输入,以显示识别不包含电源的字词的能力(显然,无论如何)。

编辑:要将结果收集到矢量中而不是将其发送到std::cout,您可以执行以下操作:

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

int main() {   
    std::string poly = "4x^2+3x^1+2x";

    std::tr1::regex term("[-+]?(\\d*)x(\\^[0-9])*");
    std::vector<std::string> terms;

    std::copy(std::tr1::sregex_token_iterator(poly.begin(), poly.end(), term),
        std::tr1::sregex_token_iterator(), 
        std::back_inserter(terms));

    // Now terms[0] is the first term, terms[1] the second, and so on.

    return 0;
}