C文件处理记录搜索:最后一条记录显示两次

时间:2014-01-12 03:54:23

标签: c file-io

我在c中编写了简单的代码,用于将学生信息(卷号,姓名,课程,费用,部门)存储在文本文件student.txt中 - 代码片段:

FILE *fp;
fp=fopen("student.txt","r");
//Input details from user and ..
//store it in student.txt
fprintf(fp,"%d %s %s %d %s ",s.rollno,s.name,s.course,s.fee,s.dept);

我编写了以下代码来检索和打印文件中的所有记录,并检索最后一条记录TWICE!

while (!feof(fp))
            {
                fscanf(fp,"%d%s%s%d%s",&s.rollno,s.name,s.course,&s.fee,s.dept);

                printf("%d %s %s %d %s\n",s.rollno,s.name,s.course,s.fee,s.dept);

            }

//OUTPUT : 
46 mustafa be 12000 cse 
41 Sam BE 32000 CSE 
42 Howard BE 25000 EE  
44 Sheldon BE 25000 CSE 
44 Sheldon BE 25000 CSE

为什么最后一条记录(Sheldon ..)从文件中读取两次(虽然它只在文件中写入一次,但我检查过)。请帮忙,真的卡住了。

1 个答案:

答案 0 :(得分:0)

在您尝试读取超出文件末尾之后,才会设置流的EOF指示符。因此,除非您已经尝试过远,否则使用feof()的测试将无效。

您可以在ISO C11标准中看到此行为,其中指出fgetc

  

如果设置了流的文件结束指示符,或者流位于文件结尾,则设置流的文件结束指示符,并且fgetc函数返回EOF。

换句话说,第一次为流设置EOF标志是当你尝试读取文件中最后一个字符时的第一个字符。

在你的情况下发生的事情是文件指针是文件的末尾,刚刚成功读取了最后一个字符。考虑到fscanf()能够跳过前导空格等等,它比复制稍微复杂一点,但基本上,下一个fscanf()会在扫描任何项目之前读取超出文件末尾的内容。

而且,当你文件的末尾时,feof()还不是真的。然后,您的代码将尝试fscanf失败(并设置EOF标志),printf将再次输出之前的内容(因为fscanf没有更改它们)。

由于fscanf会返回成功扫描的项目数,因此您可以选择以下内容:

while (fscanf (fp, "%d%s%s%d%s", blah, blah) == 5) {
    printf (blah, blah);
}
// check feof here to deside if EOF or bad input line.

有关完整示例,请参阅以下程序:

#include <stdio.h>

int main (void) {
    int rollno, fee;
    char name[100], course[100], dept[100];
    FILE *fp = fopen ("qq.in", "r");
    if (fp == NULL) {
        puts ("Cannot open file");
        return 1;
    }
    while (fscanf (fp, "%d%s%s%d%s", &rollno, name, course, &fee, dept) == 5) {
        printf ("%d %s %s %d %s\n", rollno, name, course, fee, dept);
    }
    fclose (fp);
    return 0;
}