2016-10-19 4 views
0

У меня есть входной файл с помощью следующей формыКак читать строки с различными форматами

i 176064 Patterson Denise 8.58 11 DEN 15788 
q 188464 
ra 148702 167443 
a 73131 
d 163464 
f 6.00 
ct 73131 PHY 
b 3 
p 15703 
pe 
m 144626 6.51 8 
e 

Первый символ в каждой строке [я, д, ра, и ...] представляет собой код для функции , а остальные - значения, которые я должен хранить в переменных, в зависимости от этого кода. Каков наилучший способ достичь этого? Я думал об использовании fscanf, но каждая строка не имеет определенный формат, сам формат зависит от кода [я, д, га, а, б ..]

+2

С 'strtok'. Прочитайте строки с помощью 'fgets' и проверьте каждый токен, чтобы решить, как действовать. –

+0

Что бы вы ни делали, не используйте ничего, как fscanf. Абсолютно неправильный инструмент для работы. –

+0

Обратите внимание, что некоторые из «кодов» являются кодами мультиплекса, поэтому это первое «слово», а не «первый символ», который представляет код функции. Так как семейство функций 'scanf()' не заботится о строках, вы не можете использовать их для ввода файла. Вам нужно прочитать строки (например, 'fgets()'), а затем проанализировать их ('sscanf()' может быть ОК - проверьте [Использование 'sscanf()' в цикле] (http://stackoverflow.com/ вопросы/3975236/how-to-use-sscanf-in-loop), например). –

ответ

1

Чтобы прочитать линии используйте fgets()

char buffer[100]; 
while (fgets, buffer, sizeof buffer, istream) != NULL) { 

Затем отсканируйте линию против различных форматов, каждая из которых заканчивается с " %n". "%n" записывает положение сканирования, если оно так далеко. Дополнительные тесты могут проверять наличие постороннего персонажа, начиная с n.

int num1, num2, num3; 
    char last[sizeof buf]; 
    char first[sizeof buf]; 
    char code[sizeof buf]; 
    double rate; 
    int n = 0; 
    //    v..v..v..v...v..v..v spaces optional here 
    sscanf(buffer, "i %d %s %s %lf %d %s %d %n", 
    &num1, last, first, &rate, &num2, code, &num3, &n); 
    if (n) { 
    Handle_i(); 
    continue; 
    } 
    sscanf(buffer, "q %d %n", &num1, &n); 
    if (n) { 
    Handle_q(); 
    continue; 
    } 
    sscanf(buffer, "ra %d %n", &num1, &num2, &n); 
    if (n) { 
    Handle_ra(); 
    continue; 
    } 
    sscanf(buffer, "e %n", &n); 
    if (n) { 
    Handle_e(); 
    continue; 
    } 
    ... 
    fail(); 
} 

Поскольку каждый формат начинается с уникальным рисунком буквы, то sscanf() будет быстро выйти на неправильном матче.

Альтернативный код может анализировать начальные буквы для немного более эффективного дерева решений. Подозреваемый профилирование покажет небольшую разницу в производительности.

Как и в любом сложном формате, рассмотрите, как один из будет поддерживать код, и он обязательно будет развиваться.

+0

ok Я получил это, вы можете объяснить мне еще раз, что именно делает n целое число? –

+0

ОК, я получил это, не могли бы вы еще раз объяснить, что именно делает n целое число? –

+0

@EugG 'int n = 0;' дает 'n' начальное значение 0.' sscanf (buffer, "...% n", .... &n); 'сохраняет в' n' смещение сканирования строки 'buffer []' в этой точке сканирования.Если сканирование никогда не достигает ''% n ''из-за более раннего неправильного совпадения в проверке,' n' не изменяется. – chux