user-0 提问: C语言读文件的问题

回复:
user: user-1
content: 推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  “多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

user: user-1
content: feof Tests for end-of-file on a stream.  int feof( FILE *stream );  Function Required Header Compatibility  feof <stdio.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  The feof function returns a nonzero value after the first read operation that attempts to read past the end of the file. It returns 0 if the current position is not end of file. There is no error return.  Parameter  stream  Pointer to FILE structure  Remarks  The feof routine (implemented both as a function and as a macro) determines whether the end of stream has been reached. When end of file is reached, read operations return an end-of-file indicator until the stream is closed or until rewind, fsetpos, fseek, or clearerr is called against it.  Example  /* FEOF.C: This program uses feof to indicate when  * it reaches the end of the file FEOF.C. It also  * checks for errors with ferror.  */  #include <stdio.h> #include <stdlib.h>  void main( void ) {    int  count, total = 0;    char buffer[100];    FILE *stream;     if( (stream = fopen( "feof.c", "r" )) == NULL )       exit( 1 );     /* Cycle until end of file reached: */    while( !feof( stream ) )    {       /* Attempt to read in 10 bytes: */       count = fread( buffer, sizeof( char ), 100, stream );       if( ferror( stream ) )      {          perror( "Read error" );          break;       }        /* Total up actual bytes read */       total += count;    }    printf( "Number of bytes read = %d\n", total );    fclose( stream ); }   Output  Number of bytes read = 745   Error Handling Routines |  Stream I/O Routines  See Also   clearerr, _eof, ferror, perror

user: user-2
content: 放弃使用feof吧。直接用fread的返回值作为是否读取完毕的判断。  因为feof是要等到别的读函数读取，发现没有数据了，才有用的。比如说，你用fread读取最后一个数据，此时，因为fread还能读取到数据，所以feof还不能判断到了文件尾。等下一次fread读取时，发现没有了数据了，此时feof才能检查出来。而当fread没有读取到数据时，并不修改buff参数。所以就出现了楼主说的读取两次的现象。

user: user-0
content: [quote=引用 2 楼 zhao4zhong1 的回复:] [code=c]不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 对此，还是不是太理解，为何非要 b=fgetc(f);之后才判断feof(f)，而读入的b就不起作用了

user: user-1
content: 不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

user: user-3
content: while(!feof(f)) {   fread(...); }   改成   for(;;){   fread(....);   if(feof(f)) break;   // using the read data  }   每一个IO操作都要检查是否成功（判断函数返回值，判断流状态）