2012-02-17 3 views
2

Я пытаюсь разобрать текстовый файл, содержащий числовые данные. У меня есть много линий, которые выглядят какC++ регулярное выражение соответствия целая строка

129,3 72,7 121,6 173,6 203,3 120,7 40,5 79,2 94,0 123,2 165,8 178,8 135,5 78,5 66,2

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

Использование

std::getline(is, line); 

std::tr1::regex rx("[0-9-\.]+"); 
std::tr1::cmatch res; 
std::tr1::regex_search(line.c_str(), res, rx); 

соответствует только первым номером. Если вместо этого я использую якоря линии, такие как

"^[0-9-\.]+$" 
"^[0-9-\.]+" 

я не получаю матчей и

"[0-9-\.]+$" 

просто совпадает с последним номером. Поэтому я, вероятно, что-то делаю неправильно. Спасибо за любую помощь.

+0

res - это массив, то есть res [1], res [2], res [3] ... должны иметь ваши совпадения. Вы проверили это или просто получаете разрешение? –

+0

regexp действительно не лучшее решение здесь, просто использование оператора >> в float гораздо проще в использовании и намного лучше подходит. – PlasmaHH

+0

Я согласен с PlasmaHH, но кто знает, по какой причине, кто-то хочет играть с регулярным выражением ... –

ответ

2

Um, псевдокод

for str in strtok(input string) 
    vector[index] = convert str to float 

Вот пример использования много потока магии: Split a string in C++?

Вот пример с использованием вектора: Splitting a string by whitespace in c++

Но старый добрый strtok, вероятно, проще всего: http://www.cplusplus.com/reference/clibrary/cstring/strtok/

, в котором е вы получите что-то вроде

Vector flts = // create it 
for(int ix=0, char * cp; cp = strtok(str," "); ix++){ 
    flts[ix] = atof(cp); 
} 

Теперь, это очень C, как, потому что я из практики C++, но ключевым моментом здесь является то, что при попытке использовать регулярное выражение, вы сделаете это усложненной.

+0

согласен, strtok - лучший! – macduff

+0

Действительно ... когда вы хотите выбирать между стандартами и безопасностью потоков, strtok выигрывает! – jkerian

+0

это не C++, но c. –

0

Вам нужно указать пробел между номерами в вашем матче, чтобы он соответствовал всей строке.

ОТМЕТЬТЕ, взгляните на C++ tokenize a string using a regular expression, чтобы увидеть довольно близкий ответ.

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

0

Я выглядит как регулярное выражение имеет небольшой вопрос:

"[0-9-\.]+" 

должно быть больше как:

"[0-9\.]" 
0

ваше регулярное выражение может быть неправильным, вы должны попробовать:

[0-9\.]+ 

также имейте в виду, что std :: tr1 :: cmatch возвращает массивы совпадений, т. е.res[2] содержит 72.7

Использование Вы можете задать расширенное немного поэкспериментировать:

egrep "[0-9-\.]+" /tmp/x 
egrep: Invalid range end 

но

egrep "^[0-9\.]+" /tmp/x 

матчи только

129.3 

и

egrep "[0-9\.]+" /tmp/x 

матчи все

129.3 72.7 121.6 173.6 203.3 120.7 40.5 79.2 94.0 123.2 165.8 178.8 135.5 78.5 66.2 

вам не нужно перед ^, поскольку он совпадает с нулевым символом в начале строки, то есть вы генераторных только первая последовательность чисел.

вам не нужно $, потому что это соответствует только нулевому символу в конце, таким образом, вы получите только последнюю последовательность чисел

вам нужно +, так как вы хотите, чтобы все атомы соответсвующего типа [0-9\.].

Также вы можете получить краткое руководство соответствие регулярных выражений в любой системе UNIX по issueing

man -S 7 regex 

P.S. /tmp/x - файл с линией, заданной в вопросе.

Смежные вопросы