Чтение разделенного табуляцией содержимого строка за строкой с последней строкой пустой строки

У меня есть такой формат файла

1.9969199999999998  2.4613199999999997  130.81278270000001  AA
2.4613199999999997  2.5541999999999998  138.59131554109211  BB
2.5541999999999998  2.9953799999999995  146.83238401449094  CC
...........................

Я должен прочитать первые три столбца как float и последний столбец как char массив в C, Все столбцы разделены табуляцией, и в конце каждой строки есть символ новой строки. Все отлично работает с fscanf(fp1, "%f\t%f\t%f\t%s\n", ...) пока у меня не будет текста в конце каждой строки (часть строки символа).

Есть случаи, когда вместо AA/BB/CC у меня есть пустая строка в файле. Как справиться с этим делом. я пытался fscanf(fp1, "%f\t%f\t%f\t%s[^\n]\n", ...) и многое другое, но я не могу придумать правильный путь. Не могли бы вы помочь мне здесь?

1 ответ

Решение

С помощью float скорее, чем double выбросит около половины показанных цифр. Вы получаете 6-7 десятичных цифр с float; вы получаете 15+ цифр с double,

Что касается вашего основного вопроса: используйте fgets() (или POSIX getline()) читать строки, а затем sscanf() разобрать строку, которая читается. Это позволит избежать путаницы. Если ввод основан на строках, но недостаточно регулярен, не используйте fscanf() и семья, чтобы читать данные - чтение файла scanf() функции не заботятся о новых строках, даже когда вы это делаете.

Обратите внимание, что sscanf() вернет либо 3, либо 4, указывая, была ли строка в конце строки или нет (или EOF, 0, 1 или же 2 если ему дана пустая строка, или строка, которая не начинается с числа, или строка, которая содержит только одно или два числа). Всегда проверяйте возвращаемое значение из scanf() и друзья - но делайте это осторожно. Ищите ожидаемое количество значений (3 или 4 в этом примере), а не "не EOF".

Это приводит к примерно:

#include <stdio.h>

int main(void)
{
    double d[3];
    char text[20];
    char line[4096];

    while (fgets(line, sizeof(line), stdin) != 0)
    {
        int rc = sscanf(line, "%lf %lf %lf %19s", &d[0], &d[1], &d[2], &text[0]);
        if (rc == 4)
            printf("%13.6f  %13.6f  %13.6f  [%s]\n", d[0], d[1], d[2], text);
        else if (rc == 3)
            printf("%13.6f  %13.6f  %13.6f  -NA-\n", d[0], d[1], d[2]);
        else
            printf("Format error: return code %d\n", rc);
    }
    return 0;
}

Если данный файл указан в качестве стандартного ввода:

1.9969199999999998  2.4613199999999997  130.81278270000001  AA
2.4613199999999997  2.5541999999999998  138.59131554109211  BB
2.5541999999999998  2.9953799999999995  146.83238401449094  CC
19.20212223242525  29.3031323334353637 3940.41424344454647
19.20212223242525  29.3031323334353637 3940.41424344454647  PolyVinyl-PolySaccharide

выход:

 1.996920       2.461320     130.812783  [AA]
 2.461320       2.554200     138.591316  [BB]
 2.554200       2.995380     146.832384  [CC]
19.202122      29.303132    3940.414243  -NA-
19.202122      29.303132    3940.414243  [PolyVinyl-PolySacch]

Вы можете настроить выходной формат под себя. Обратите внимание, что %19s избегает переполнения буфера, даже если текст длиннее 19 символов.

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