Невозможно получить результаты сопоставления с регулярным выражением - 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.