关于文件I / O的混淆(C)

时间:2013-06-14 06:22:54

标签: c file-io

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 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:3)

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

“此指示符通常由尝试在文件结尾处读取或超过文件末尾的流上的上一个操作设置。”

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

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

答案 2 :(得分:2)

使用feof是文件I / O中初学者最大的误解之一。在某些时候,每个人都犯过一次或两次相同的错误。

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

  1. 如果由于文件结束而导致下一次读取失败,则Pascal的函数返回true。
  2. 如果最后一个函数失败,则C的函数返回true。
  3. 这就是为什么你的代码打印最后一行两次,因为在读入最后一行并打印出来之后,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);
    

答案 3 :(得分:0)

首先,你应该在你想要做的事情中包括一个完整的,复制的例子,而不是代码的组合片段,这很难再现。否则,请注意直接在结构内容上使用fwrite()/ fread()is not portable(请参阅免费在线书籍Porting UNIX Software),并且容易出错。但是你没有为我们提供足够的背景来理解出了什么问题。