Почему fscanf используется 2 раза с: while( !feof(File))

почему при использовании fscanf для получения данных из файла используется 2 раза, один раз перед "!feof(fin)" и позже, как показано в коде ниже:

fscanf(fin, "%s", letta);
while(!feof(fin)){

    fscanf(fin, "%s", letta);
}

слово читать не то же самое?


person ild0tt0re    schedule 20.06.2012    source источник
comment
Это неправильный способ использования feof: stackoverflow.com/questions/5431941/   -  person William Pursell    schedule 30.01.2013


Ответы (4)


Нет, прочитанное слово не будет одинаковым, поскольку вы читаете файл дважды, и каждый раз вы получаете разные данные.

Условие в while проверяет, находитесь ли вы в конце файла, для этого должна быть предпринята попытка чтения, для чего требуется fscanf() перед циклом.

Как только вы окажетесь внутри цикла, вы захотите продолжить чтение из файла. Предположительно, внутри цикла будет больше кода для обработки данных, которые вы читаете.

В опубликованном вами коде, если вы столкнулись с концом файла при первой попытке чтения, вы не вошли бы в цикл (while).

Сравните это с конструкцией do-while, где тест находится в нижней части цикла (т. е. чтение происходит только один раз, в «нижней части» цикла). Там вы всегда будете входить в цикл хотя бы один раз.

person Levon    schedule 20.06.2012

Вероятно, нет смысла использовать feof() здесь, как здесь, но многие люди, которые (я думаю, извиняюсь, если я ошибаюсь) изучают C, похоже, «хотят».

Дело в том, что fscanf() сама по себе имеет возвращаемое значение; если файл заканчивается, он не сможет выполнить запрошенное сканирование, и он сообщит вам об этом. Он даже вернет специальную константу EOF, если файл закончится. Так что просто зациклите на возвращаемом значении fscanf():

while( fscanf(fin, "%s", letta) == 1 )
{
   /* Process, parse, store or do whatever with letta. */
}
person unwind    schedule 20.06.2012
comment
Верно, верно, но это не дает прямого ответа на вопрос. - person Mr Lister; 20.06.2012

Поскольку флаг EOF устанавливается только после вызова fscanf. Условие while(!feof(fin)) не имеет смысла, если fscanf еще не было вызвано.

person Mr Lister    schedule 20.06.2012

feof не возвращает значение true до тех пор, пока вы не попытаетесь прочитать конец файла. Представьте себе файл, подобный следующему:

This is a test$
^

где ^ указывает текущее местоположение в файле, а $ представляет конец файла. После первого вызова fscanf(fin, "%s", letta); поток выглядит так:

This is a test$
    ^

После трех итераций цикла (чтение «is», «a» и «test») у вас есть это:

This is a test$
              ^

В этот момент feof(fin) по-прежнему возвращает false, потому что в этот момент все, что вы знаете, это то, что вы достигли конца строки «тест». Таким образом, ваш цикл будет выполнен еще раз. Поскольку вы находитесь в конце файла, читать нечего, поэтому содержимое letta не будет изменено, так что это будет выглядеть так, как будто вы прочитали слово «тест» дважды. Теперь feof(fin) возвращает значение true.

Мораль этой истории в том, что вы не должны использовать feof в качестве условия цикла; скорее, вы должны использовать результат самой операции чтения, например:

errno = 0;
while (fscanf(fin, "%s", letta) == 1)
{
  // process letta
}
if (feof(fin))
{
  printf("Reached end of file\n");
}
else
{
  perror("Error on read");
} 
person John Bode    schedule 20.06.2012