Почему Boost.Regex не находит несколько совпадений в одной строке? - PullRequest
5 голосов
/ 15 ноября 2010

Я пишу небольшую программу командной строки, которая запрашивает у пользователя полиномы в виде 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 Ответ

7 голосов
/ 15 ноября 2010

Вы используете не то, что нужно - regex_match предназначен для проверки того, соответствует ли (одно) регулярное выражение всей последовательности символов.Таким образом, вам нужно либо указать регулярное выражение, которое соответствует всему вводу, либо использовать что-то еще.В вашей ситуации , вероятно, имеет смысл просто изменить регулярное выражение, как вы уже сделали (сгруппируйте его и добавьте звезду Клини).Если вы хотите перебрать отдельные термины полинома, вы, вероятно, захотите использовать что-то вроде 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...