【问题标题】:Why doesn't Boost.Regex find multiple matches in one string?为什么 Boost.Regex 不能在一个字符串中找到多个匹配项?
【发布时间】:2010-11-15 04:22:04
【问题描述】:

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

我的问题是,为什么 Boost.Regex'sregex_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;
}

【问题讨论】:

    标签: c++ regex boost


    【解决方案1】:

    您使用了错误的东西——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;
    }
    

    至少对我来说,这会单独打印出每个术语:

    4x^2
    +3x^1
    +2x

    请注意,目前,我刚刚打印出每个完整的术语,并修改了您的输入以展示识别不包含幂的术语的能力(无论如何,明确地)。

    编辑:要将结果收集到向量中而不是将它们发送到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;
    }
    

    【讨论】:

    • 我一直在尝试修改正则表达式,但没有奏效。它会匹配,但“匹配”数组中的唯一信息是最后一个子表达式中的内容。例如,如果我输入“4x^2+3x^1”,我的输出为:matches[0] = 4x^2+3x^1 matches[1] = +3x^1 matches[2] = + matches[3 ] = 3 匹配[4] = 1 我只得到多项式的最后一项;我需要能够解析整个事情。
    • @Zeebo:也许我编辑到答案中的版本会有所帮助。
    • 对不起,我应该更清楚。我只需要系数和指数。我正在尝试编写一个程序来执行合成除法,所以我只需要知道系数(以及它们是正数还是负数)、有多少项以及指数(因为 0x^n 需要如果缺少术语,则插入;例如 4x^4 + 7x^2 需要为 4x^2 + 0x^3 + 7x^2。)
    • @Zeebo:是的,当然。但是,一旦您将多项式分解为单独的项,您就已经知道如何使用match 从每个项中获取系数和指数...
    • 哦,有道理。谢谢!出于好奇,有没有办法修改正则表达式以使所有子表达式都存储在matches数组中还是不可能的?
    猜你喜欢
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多