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。谁能解释它是如何发生的?

4

4 回答 4

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);
}
于 2013-06-14T06:32:00.197 回答
3

来自http://www.cplusplus.com/reference/cstdio/feof/

“此指标通常由流上的先前操作设置,该操作试图在文件结尾处或之后读取。”

这意味着通常在操作后检测到文件结尾。

要修复您的代码,您可以例如将 while 循环中的条件替换为 1 或 true 并在达到 eof 时中断执行(在循环内运行 feof)。

于 2013-06-14T06:32:17.930 回答
2

使用 feof 是 File I/O 初学者最大的误解之一。每个人都曾在某个时候犯过同样的错误一两次。

您使用它的方式是 Pascal 的方式,但 C 方式是不同的。区别在于::

  1. 如果下一次读取由于文件结束而失败,Pascal 的函数将返回 true。
  2. 如果最后一个函数失败,C 的函数返回 true。

这就是为什么您的代码将最后一行打印两次的原因,因为在读入并打印出最后一行之后,feof() 仍将返回 0(假)并且循环将继续。下一个 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);
于 2013-06-14T06:37:12.413 回答
0

首先,您应该包含一个完整的、可复制的示例来说明您想要做什么,而不是难以复制的代码组合片段。否则,请注意直接在结构内容上使用 fwrite()/fread()是不可移植的(请参阅免费在线书籍Porting UNIX Software),并且容易出错。但是您没有提供足够的上下文让我们了解出了什么问题。

于 2013-06-14T06:31:27.143 回答