Как разобрать строку в C ++ - PullRequest
2 голосов
/ 18 февраля 2009

Я хочу разобрать строки, чтобы проверить, имеют ли они заданный синтаксис или нет.

Пример:

Str = Z344-R565l t

Здесь мое требование заключается в том, что после Z должно быть число, а после этого -, после которого R должно следовать число, затем l, затем пробел и затем, наконец, t.

Если что-то кроме этого, это должно быть ошибкой.

Мне нужно проанализировать много разных типов синтаксиса, подобных этому. Я был бы неловко, если написать функцию для каждого типа синтаксиса требуется. Я слышал, что yacc или lex могут решить эту проблему.

Кто-нибудь может пролить свет на мою проблему?

Ответы [ 5 ]

6 голосов
/ 18 февраля 2009

Вы делаете это с помощью регулярного выражения.

Z344-R565l т

Ваше регулярное выражение должно выглядеть примерно так. Не уверен, какую библиотеку регулярных выражений использовать для c ++, но это общее регулярное выражение, чтобы убедиться, что ваша строка соответствует.

Z[0-9]+-R[0-9]+l t
4 голосов
/ 18 февраля 2009

Boost :: Regex хорошо, если вы просто хотите проверить синтаксис. Если вы хотите что-то сделать, когда читаете такое выражение, я предлагаю вам использовать Boost :: Spirit с чем-то вроде:

rule<> testFormula = 
    (ch_p('Z') >> int_p) 
    >> (ch_p('-')>>ch_p('R')>>int_p>>ch_p('l')) 
    >> space_p >> ch_p('t');

У меня есть отдельные части выражения, которые вы можете подключить к какому-либо действию (используя оператор []).

См. Документацию для получения дополнительной информации

4 голосов
/ 18 февраля 2009

Используйте boost :: regex

#include <string>
#include <boost/regex.hpp>

bool isMatch(std::string input){
    boost::regex r("Z[0-9]*-R[0-9]*l t");
    return boost::regex_search(input, r);
}

Другая вещь, которую вы могли бы сделать, это предоставить список выражений регулярных выражений в файле, по одному выражению на строку. Создайте вектор объектов boost :: regex, используя входные данные файла, и итерируйте вектор шаблонов для каждой строки, которую необходимо проверить. Это не очень эффективно, но это будет работать.

1 голос
/ 22 июля 2009

Если у вас есть недавний компилятор (VC 2008 SP1 и т. Д.), Нет необходимости использовать boost, регулярные выражения являются частью TR1, и вы можете использовать их с этим заголовком: #include <regex>

Пример для даты ( вы должны использовать двойной \ в качестве escape-символа ):

string dateorder = "12/07/2009";

tr1::regex expr("^([1-2][0-9]|0?[1-9]|30|31)/([1-9]|10|11|12)/(2\\\d{3})$");

if (!regex_match(dateorder.begin(),dateorder.end(),expr))
{
    ...
    break;  
}
1 голос
/ 18 февраля 2009

Вы могли бы Google "runtime parser generation" или что-то подобное ...

lex и yacc (или их эквиваленты GNU flex и bison) выполняют свою работу во время компиляции и могут быть недостаточно гибкими для ваших нужд. (или они могут, вы не очень конкретны).

...