2013-06-14 2 views
0
fwrite(&studentg,sizeof(studentg),1,p); 
while(!feof(p)) 
{ 
    printf("flag"); 
    fread(&studentg,sizeof(studentg),1,p); 
    printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",studentg.name,studentg.add,studentg.tel,studentg.pc,studentg.qq,studentg.email); 
} 

Почему я помещаю только один объект в файл, но он выводит две одинаковые строки? И если я помещаю два объекта в файл, он выводит один объект правильно, но другой повторяется. Я пытаюсь показать возвращаемое значение feof (p), это покажет мне, что после fread значение feof (p) все равно 0. Может ли кто-нибудь объяснить, как это происходит?Путаница о файле I/O (C)

+5

Вы не читали comp.lang.c FAQ, ни feof человек страницы. EOF обнаруживается только * после * операции, никогда раньше, и вы должны искать при переключении с операций записи на чтение. – Jens

+0

Вы можете принять ответ, который вам больше всего помог. – Abhineet

ответ

4

Вы не получите окончание файла, пока не попытаетесь прочитать его за пределами файла. Это означает, что вы должны проверить EOF перед печатью:

fwrite(&studentg,sizeof(studentg),1,p); 
finish = 0; 
while(!finish) 
{ 
    printf("flag"); 
    fread(&studentg,sizeof(studentg),1,p); 
    finish = feof(p); 
    if (!finish) 
    { 
     printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",studentg.name,studentg.add,studentg.tel,studentg.pc,studentg.qq,studentg.email); 
    } 
} 

или

fwrite(&studentg,sizeof(studentg),1,p); 
while(1) 
{ 
    printf("flag"); 
    fread(&studentg,sizeof(studentg),1,p); 
    if (feof(p)) break; 
    printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",studentg.name,studentg.add,studentg.tel,studentg.pc,studentg.qq,studentg.email); 
} 
+0

О, дополнительный комментарий ... fwrite, а затем fread не будет работать. Вам нужно искать начало файла после записи или, может быть, закрыть его и снова открыть для чтения. – victor

0

Прежде всего, вы должны включить полный, воспроизводящий пример к тому, что вы хотите сделать, а не комбинированный фрагмент кода, который трудно воспроизвести. В противном случае обратите внимание, что с помощью функции fwrite()/fread() непосредственно в структуре содержимого is not portable (см. Бесплатную онлайн-книгу Porting UNIX Software), и она подвержена ошибкам. Но вы не предоставили достаточного контекста, чтобы понять, что пошло не так.

3

От http://www.cplusplus.com/reference/cstdio/feof/:

«Этот показатель, как правило, устанавливается с помощью предыдущей операции на поток, который пытался читайте в конце файла или за ним ».

Это означает, что конец файла обычно обнаруживается после операции.

Чтобы исправить ваш код, вы можете, например, заменить условие во время цикла с помощью 1 или true и выполнить разрыв при достижении eof (запуск внутри цикла).

2

Использование feof является одним из самых больших заблуждений среди новичков в File I/O. Каждый в какой-то момент совершил ту же ошибку один или два раза.

То, как вы использовали это путь Паскаля, но C-путь отличается. Разница заключается в следующем:

  1. Функция Паскаля возвращает true, если следующее считывание завершится неудачно из-за конца файла.
  2. Функция C возвращает true, если последняя функция не удалась.

Вот почему ваш код печатает последнюю строку дважды, потому что после того, как последняя строка будет считана и распечатана, feof() все равно вернет 0 (false), и цикл продолжится. Следующий fgets() терпит неудачу, и поэтому переменная строки, содержащая содержимое последней строки, не изменяется и снова распечатывается. После этого feof() вернет true (поскольку fgets() не удалось), и цикл завершается.

Правильный способ использовать это ::

while(1) { 
    fgets(line, sizeof(line), fp); 
    if (feof(fp)) /* check for EOF right after fgets() */ 
     break; 
    fputs(line, stdout); 
    } 

Еще лучше путь ::

while(fgets(line, sizeof(line), fp) != NULL) 
    fputs(line, stdout); 
+0

Идиома C для бесконечных циклов - 'for (;;)' (что также позволяет избежать предупреждений lint о постоянном выражении в булевом контексте). – Jens

Смежные вопросы