Разница между fgets и fscanf? - PullRequest
       15

Разница между fgets и fscanf?

8 голосов
/ 19 января 2012

У меня есть вопрос, касающийся fgets и fscanf в C. В чем разница между этими двумя? Например:

char str[10];
while(fgets(str,10,ptr))
{
counter++;
...

и второй пример:

char str[10];
while(fscanf(ptr,"%s",str))
{
counter++;
...

при наличии текстового файла, который содержит строки, разделенные пустым пространством, например: AB1234 AC5423 AS1433. В первом примере «счетчик» в цикле while не будет выдавать тот же вывод, что и во втором примере. При изменении значения «10» в функции fgets счетчик всегда будет давать разные результаты. Что является причиной этого? Кто-нибудь может также объяснить, что именно делает fscanf, какова длина строки в каждом цикле while?

Ответы [ 4 ]

7 голосов
/ 19 января 2012

Функция fgets читает до новой строки (а также сохраняет ее). fscanf со спецификатором %s читает до пустого места и не сохраняет его ...

В качестве примечания вы не указываете размер буфера в scanf, и это небезопасно. Попробуйте:

fscanf(ptr, "%9s", str)
3 голосов
/ 19 января 2012

fgets читает на новую строку. fscanf читает только до пробела.

2 голосов
/ 19 января 2012

В вашем примере fgets будет считывать максимум 9 символов из входного потока и сохранять их в str вместе с ограничителем 0. Это не будет пропускать ведущие пробелы. Он остановится, если увидит новую строку (которая будет сохранена в str) или EOF до максимального количества символов.

fscanf со спецификатором преобразования %s пропустит любой начальный пробел, затем прочитает все непробельные символы, сохранив их в str, за которым следует терминатор 0. Он прекратит чтение следующего символа пробела или EOF. Без явной ширины поля он будет читать столько непробельных символов, сколько в потоке, что может привести к переполнению целевого буфера.

Итак, представьте, что входной поток выглядит так: "\t abcdef\n<EOF>". Если вы используете fgets для чтения, str будет содержать "\t abcdef\n\0". Если вы использовали fscanf, str может содержать "abcdef\0" (где \0 обозначает терминатор 0).

1 голос
/ 19 января 2012

fgets читать всю строку. fscanf с %s читать строку, разделенную пробелом (или \ n, \ t и т. Д.). В любом случае, вы не должны использовать их, если вы не уверены, что массив, который вы читаете, достаточно большой, чтобы содержать входные данные. Вы написали When changing the "10" in the fgets function the counter will always give different results. Обратите внимание, что fgets и scanf не знают, сколько байтов нужно прочитать. ты должен сказать им. изменив «10», просто увеличьте буфер, в который записываются эти функции.

...