С++ 11 ошибка регулярного выражения

Просто пример кода из C++ Primer 5th Edition: 17.3.3. Using the Regular Expression Library

Основной файл main.cpp:

#include <iostream>
#include "regexcase.h"
using namespace std;

int main() {
    using_regex();
    return 0;
}

Заголовочный файл regexcase.h:

#ifndef REGEXCASE_H_
#define REGEXCASE_H_

#include <regex>
#include <string>

void using_regex();
std::string parseCode(std::regex_constants::error_type etype);

#endif /* REGEXCASE_H_ */

Исходный файл regexcase.cpp:

#include "regexcase.h"
#include <iostream>
using namespace std;

void using_regex() {
    // look for words that violate a well-known spelling rule of thumb, "i before e, except after c":
    // find the characters ei that follow a character other than c
    string pattern("[^c]ei");
    // we want the whole word in which our pattern appears
    pattern = "[a-zA-Z]*" + pattern + "[a-zA-Z]*";  //[a-zA-Z]*   [[:alpha:]]*
    try {
        regex r(pattern, regex_constants::extended);    // construct a regex to find pattern                // , regex_constants::extended
        smatch results;     // define an object to hold the results of a search
        // define a string that has text that does and doesn't match pattern
        string test_str = "receipt freind theif receive";
        // use r to find a match to pattern in test_str
        if (regex_search(test_str, results, r)) // if there is a match
            cout << results.str() << endl;      // print the matching word
        else
            cout << "no match for " << pattern << endl;
    } catch (regex_error &e) {
        cout << "what: " << e.what() << "; code: " << parseCode(e.code()) << endl;
    }
}

string parseCode(regex_constants::error_type etype) {
    switch (etype) {
    case regex_constants::error_collate:
        return "error_collate: invalid collating element request";
    case regex_constants::error_ctype:
        return "error_ctype: invalid character class";
    case regex_constants::error_escape:
        return "error_escape: invalid escape character or trailing escape";
    case regex_constants::error_backref:
        return "error_backref: invalid back reference";
    case regex_constants::error_brack:
        return "error_brack: mismatched bracket([ or ])";
    case regex_constants::error_paren:
        return "error_paren: mismatched parentheses(( or ))";
    case regex_constants::error_brace:
        return "error_brace: mismatched brace({ or })";
    case regex_constants::error_badbrace:
        return "error_badbrace: invalid range inside a { }";
    case regex_constants::error_range:
        return "erro_range: invalid character range(e.g., [z-a])";
    case regex_constants::error_space:
        return "error_space: insufficient memory to handle this regular expression";
    case regex_constants::error_badrepeat:
        return "error_badrepeat: a repetition character (*, ?, +, or {) was not preceded by a valid regular expression";
    case regex_constants::error_complexity:
        return "error_complexity: the requested match is too complex";
    case regex_constants::error_stack:
        return "error_stack: insufficient memory to evaluate a match";
    default:
        return "";
    }
}

Вывод вызова using_regex();: what: regex_error; code: error_brack: mismatched bracket([ or ])

Кажется, что регулярное выражение не может разобрать скобку.

См. ответы в этом вопросе, я использую regex_constants::extended для инициализации объекта регулярного выражения, который затем равен regex r(pattern, regex_constants::extended);

Тогда выход no match for [[:alpha:]]*[^c]ei[[:alpha:]]*

Кажется, что регулярное выражение не может соответствовать шаблону.

Затем я использую [a-zA-Z]* для замены класса символов [[:alpha:]]* (с установленным regex_constants::extended). Выход по-прежнему no match for [a-zA-Z]*[^c]ei[a-zA-Z]*

Платформа: windows

Используемые инструменты: Eclipse for C/C++; MinGW (g++ --version: g++ 4.7.2)

EDIT: спасибо @sharth, добавьте основной файл, чтобы завершить код.


person zyy7259    schedule 08.02.2013    source источник
comment
Трудно отлаживать регулярное выражение, не зная, какой ввод вы ему даете. Иначе звездный вопрос.   -  person FrankieTheKneeMan    schedule 08.02.2013
comment
Он спрятан там как test_str.   -  person Bill Lynch    schedule 08.02.2013
comment
В gcc-4.7 std::tr1::regex не является полным/функциональным. Вместо этого используйте boost::regex.   -  person Maxim Egorushkin    schedule 08.02.2013
comment
Я сталкивался с подобными проблемами при использовании ‹regex› . Оказалось, что в моем gcc (4.6) не поддерживается полное регулярное выражение. Затем я использовал boost::regex, и все пошло гладко. (Я уже использовал boost).   -  person Dilawar    schedule 09.02.2013


Ответы (1)


Я только что провел тест, используя libc++ и clang++. Это работает, как и ожидалось. Вот мой основной:

int main() {
    string test_str = "receipt freind theif receive";
    string pattern = "[a-zA-Z]*[^c]ei[a-zA-Z]*";

    try {
        regex r(pattern, regex_constants::extended);
        smatch results;

        if (regex_search(test_str, results, r))
            cout << results.str() << endl;
        else
            cout << "no match for " << pattern << endl;
    } catch (regex_error &e) {
        cout << "what: " << e.what() << "; code: " << parseCode(e.code()) << endl;
    }
}

Вывод:

freind

С другой стороны, GCC 4.7.2 дает такой результат:

no match for [a-zA-Z]*[^c]ei[a-zA-Z]*

Это связано с тем, что в GCC 4.7.2 libstdc++ они по-прежнему не реализуют регулярное выражение. Вот реализация regex_search:

template<typename _Bi_iter, typename _Allocator, typename _Ch_type, typename _Rx_traits>
inline bool regex_search(_Bi_iter __first, _Bi_iter __last, match_results<_Bi_iter, _Allocator>& __m, const basic_regex<_Ch_type, _Rx_traits>& __re, regex_constants::match_flag_type __flags) {
    return false;
}

И просто отметим, что очень полезно включить небольшую программу, которую читатели могли бы скомпилировать. Таким образом, нет путаницы в том, какой код выполняется.

person Bill Lynch    schedule 08.02.2013
comment
Так что мне делать? Вместо этого используйте boost::regex, не так ли? (как сказал @Maxim Егорушкин выше) - person zyy7259; 08.02.2013
comment
Реализация Boost будет работать нормально. На самом деле, я только что провел быстрый тест с использованием Boost 1.53.0 и GCC 4.7.2, и он работал так же, как libc++. - person Bill Lynch; 08.02.2013
comment
Какая версия clang? Вышеупомянутое не работает на 3.3 rc2. - person ; 01.11.2013
comment
@wvxvw: я, вероятно, использовал любую версию clang, которая была включена в OS X в то время. Однако большая проблема заключается в том, что libstdc++ не включает поддержку regex. Итак, в OS X вы можете сделать -stdlib=libc++ -std=c++11. В Linux вам, вероятно, потребуется использовать реализацию boost. - person Bill Lynch; 01.11.2013