我在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 ..)从文件中读取两次(虽然它只在文件中写入一次,但我检查过)。请帮忙,真的卡住了。
答案 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;
}