Невозможно получить результаты сопоставления с регулярным выражением - MFC / C++

Я читаю HTML-страницу и пытаюсь извлечь из нее определенную строку.

У меня есть следующий код:

    std::string str = test.GetString(); // someString ( the string i have checked it, it's basically an html page )
    std::smatch match;
    std::regex re("0x(\\d|[A-Z]).*0000"); // the pattern I'm searching for
    if (std::regex_search(str, match, re)){
        test = "found"; // found gets printed
    }
    TRACE("%s\n",match[0]); // this outputs some garbage like this '˜ò'

Я хочу напечатать / сохранить результат найденного совпадения, но вместо этого получаю мусор.

Отказ от ответственности: я новичок в C++ регулярных выражений. Я мог бы сделать основную ошибку

2 ответа

Решение
std::smatch match;
...
TRACE("%s\n",match[0]); // this outputs some garbage like this '˜ò'

%s спецификатор типа в TRACE макрос ожидает необработанный указатель строки C (char* в сборках ANSI/MBCS; wchar_t* в сборках Unicode - я предполагаю, что вы делаете сборку ANSI/MBCS здесь.).

Но match[0] не является необработанным указателем строки C

Таким образом, у вас есть несоответствие между тем, что вы обещали TRACE с помощью %s (т.е. необработанная строка C char* указатель), и что вы на самом деле передаете ему (т.е. match[0]).

Согласно некоторой онлайн-документации, std::smatch это специализация std::match_results шаблон, в частности:

smatch --> match_results<string::const_iterator>

smatch::operator[] (который вы вызываете в своем коде как match[0]) возвращает ссылку на другой объект, который является std::sub_match, это std::sub_match Класс представляет собой пару итераторов, обозначающих последовательности совпадающих символов.

Итак, вы обещаете TRACE передать необработанный указатель на строку C (через %s спецификатор типа), но вы фактически передаете совершенно другую вещь, то есть ссылку на std::sub_match объект (через ваш match[0] код): неудивительно, что печатный текст не имеет смысла.

Что вам нужно сделать, это получить указатель строки C из match[0] выражение.

Для этого вы можете вызвать std::sub_match "s str() метод. Это возвращает std::string объект.

Тем не менее, это std::string объект не совсем то, что %s ожидает: на самом деле, %s представляет необработанный указатель строки C (например, const char*), а не std::string пример.

Итак, последний шаг - извлечь этот необработанный указатель строки C из std::string объект, и это делается путем вызова std::string::c_str() метод.

Подводя итог этих логических шагов:

std::smatch match;
...
match[0]               --> reference to std::sub_match object
match[0].str()         --> std::string object
match[0].str().c_str() --> raw C string pointer (const char*)

Так что ваши TRACE Заявление можно записать в виде:

TRACE("%s\n", match[0].str().c_str());

Проблема здесь в том, что match[0] возвращает объект типа sub_match, который просто пара итераторов. Если этот первый аргумент макроса TRACE является спецификатором формата в стиле C, преобразуйте sub_match объект в строку C, как это:

TRACE("%s\n", std::string(match[0]).c_str());

То есть использовать sub_match"s operator string() чтобы получить (временный) строковый объект C++, затем вызовите его функцию-член c_str(), чтобы получить (временный) строковый объект C.

Другие вопросы по тегам