scanf("%[^\n]s", inputLineArray);
неверно и неуместно:
- у спецификатора конверсии нет завершающего
s
, просто %[^\n]
; scanf
читаетпоток и сохраняет любые символы перед новой строкой в inputLineArray
и оставляет новую строку ожидающей в потоке; scanf
должно быть задано максимальное количество символов для хранения, чтобы избежать неопределенного поведения на длинных строках: scanf("%999[^\n]", inputLineArray)
; - Вы должны проверить возвращаемое значение
scanf()
, чтобы определить, было ли преобразование успешным.Тест while (!feof(stdin))
патологически неуместен: Почему «while (! Feof (file))» всегда неверно? ; - , тогда вы увидите другую проблему: это преобразование завершается неудачно в пустых строкахпоскольку в массиве назначения нет символов, которые нужно сохранить, и поскольку
scanf()
оставляет перевод новой строки в ожидании, второй вызов завершается неудачно и все последующие тоже.
Обратите также внимание, что вызов с высокой степенью рискаprintf
с предоставленными пользователем данными в виде строки формата.Поведение не определено, если строка содержит нетривиальные спецификации формата.
Вот лучший способ прочитать файл построчно:
#include <stdio.h>
#include <string.h>
...
char inputLineArray[1001];
while (fgets(inputLineArray, sizeof inputLineArray, stdin)) {
buf[strcspn(buf, "\n")] = '\0'; // strip the trailing newline if present
printf("%s\n", inputLineArray);
}
...
Обратите внимание, что строки ввода с 1000 байтов илибольше будет разбито на несколько выходных строк.
scanf()
- не тот инструмент, который вам подходит, действительно, он полон причуд и недостатков, но если вам необходимо использовать scanf()
, вотисправленная версия:
char inputLineArray[1000];
while (scanf("%c", &inputLineArray[0]) == 1) {
/* one byte was read, check if it is a newline */
if (inputLineArray[0] == '\n') {
/* empty line must be special cased */
inputLineArray[0] = '\0';
} else {
/* set the null terminator in case the next `scanf` fails */
inputLineArray[1] = '\0';
/* attempt to read the rest of the line */
scanf("%998[^\n]", inputLineArray + 1);
/* consume the pending newline, if any */
scanf("%*1[\n]");
}
printf("%s\n", inputLineArray);
}
if (feof(stdin)) {
/* scanf() failed at end of file, OK */
} else {
printf("read error\n");
}
Обратите внимание, что feof()
не используется, так как scanf("%c", ...)
вернет EOF
в конце файла, поэтому цикл while()
с остановкой, как и ожидалось.
feof()
используется только для того, чтобы отличить конец файла от состояния ошибки чтения в потоковом вводе / выводе.Большинству программ на С не нужно различать их, поскольку ошибки чтения могут обрабатываться так же, как и усеченные входные файлы.Эта функция почти всегда используется неправильно.Короче говоря, вы никогда не должны использовать feof()
или другие подверженные ошибкам или устаревшие функции, такие как gets()
и strncpy()
.Будьте также очень осторожны с sprintf()
, strcpy()
, strcat()
...