Продолжая мой предыдущий комментарий, при чтении столбцов данных из текстового файла, как правило, лучше читать строку ввода одновременно с строчно-ориентированной функцией ввода, такой как fgets
или POSIX getline
и затем для анализа данных из буфера, заполненного sscanf
(или перемещения указателя вниз по буферу, выбирая то, что вам нужно)
В вашем случае при работе с фиксированным числом столбцов (10), где может присутствовать меньше, чем все значения, sscanf
предоставляет способ точно определить, сколько значений присутствует в каждой строке, позволяя при этом использовать данные, если присутствуют менее 10.
sscanf
(как и для всех функций scanf
) возвращает количество успешных преобразований на основе предоставленной вами строки формата (или возвращая EOF
, если конец ввода встречался раньше). конверсия происходит). Если вы хотите прочитать 10-целочисленные значения из каждой строки данных в имена целых массивов arr
, вы можете использовать fgets
, чтобы прочитать строку в буфер (скажем buf
), а затем разделить целочисленные значения в начале buf с sscanf
, например
...
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
/* parse into integer values with sscanf saving return */
int rtn = sscanf (buf, "%d %d %d %d %d %d %d %d %d %d",
&arr[0], &arr[1], &arr[2], &arr[3], &arr[4],
&arr[5], &arr[6], &arr[7], &arr[8], &arr[9]);
...
Затем вы просто проверяете возврат (rtn
), используя все необходимые операторы if..else
или switch...
. Здесь мы можем просто суммировать число значений, считанных и вывести номер строки для любой строки, содержащей менее чем COL
количество значений для целей этого примера, например,
...
if (rtn > 0) /* did at least one conversion take place? */
n += rtn; /* increment count of values read */
if (rtn < COL) /* were less than COL values read? */
printf ("row[%zu]: %d values read.\n", row + 1, rtn);
row++; /* increment row count */
}
В целом, вы можете сделать что-то вроде следующего:
#include <stdio.h>
#define COL 10
#define MAXC 1024
int main (int argc, char **argv) {
char buf[MAXC];
int arr[COL] = {0};
size_t n = 0, row = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
/* parse into integer values with sscanf saving return */
int rtn = sscanf (buf, "%d %d %d %d %d %d %d %d %d %d",
&arr[0], &arr[1], &arr[2], &arr[3], &arr[4],
&arr[5], &arr[6], &arr[7], &arr[8], &arr[9]);
if (rtn > 0) /* did at least one conversion take place? */
n += rtn; /* increment count of values read */
if (rtn < COL) /* were less than COL values read? */
printf ("row[%zu]: %d values read.\n", row + 1, rtn);
row++; /* increment row count */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
printf ("%zu values read from file.\n", n);
}
Пример входного файла
Чтение файла данных с 10 целыми числами на строку для 119 строк и чтение последней строки с 9 целыми числами, как вы описали в своем вопросе, вы можете использовать входной файл, например:
$ head -n4 dat/1199_10col.txt; echo "<snip>"; tail -n4 dat/1199_10col.txt
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
<snip>
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
1191 1192 1193 1194 1195 1196 1197 1198 1199
Пример использования / Вывод
Выполнение кода для вышеуказанного файла даст ожидаемые результаты чтения 1199 значений, 10-целых чисел на строку с 9-целыми числами, прочитанных из последней строки с уведомлением о короткой строке:
$ ./bin/read10col <dat/1199_10col.txt
row[120]: 9 values read.
1199 values read from file.
Хотя есть много способов сделать это, и, возможно, использование fgets
с strtol
предоставляет возможность для более детального обнаружения ошибок, это, вероятно, один из более простых и простых подходов.
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.