Чтение разделенного табуляцией содержимого строка за строкой с последней строкой пустой строки
У меня есть такой формат файла
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 символов.