#include <stdio.h>
int main()
{
FILE* f=fopen("book2.txt","r");
char a[200];
while(!feof(f))
{
fscanf(f,"%s",a);
printf("%s ",a);
printf("%d\n",ftell(f));
}
fclose(f);
return 0;
}
我有上面的代码。 book2.txt包含“abcdef abcdef”,光标移动到换行符(即:abcdef abcdef \ n)。我得到以下结果。
abcdef 6
abcdef 13
abcdef 19
我希望得到
abcdef 6
abcdef 13
15
我做错了什么?
答案 0 :(得分:4)
自行测试I / O操作;不要使用feof()
,除非您正在编写Pascal(并且C不是Pascal!)
#include <stdio.h>
int main(void)
{
FILE *f = fopen("book2.txt", "r");
char a[200];
if (f != 0)
{
while (fscanf(f, "%199s", a) == 1)
{
printf("%s ", a);
printf("%ld\n", ftell(f));
}
putchar('\n');
fclose(f);
}
return 0;
}
请注意,修订后的代码在使用之前测试f
,并通过指定字符串在转换规范中的时长来防止缓冲区溢出。请注意,%s
会读取空格字符;除非每行没有空格,否则它不会读取行。
使用feof()
来区分转换失败,I / O错误和fscanf()
等操作报告故障后的EOF。例如:
#include <stdio.h>
int main(void)
{
FILE *f = fopen("book2.txt", "r");
char a[200];
if (f != 0)
{
while (fscanf(f, "%199s", a) == 1)
{
printf("%s ",a);
printf("%ld\n", ftell(f));
}
putchar('\n');
if (feof(f))
printf("EOF\n");
else if (ferror(f))
printf("I/O error\n");
else
printf("Conversion failed\n");
fclose(f);
}
return 0;
}
使用%s
,您将无法转换失败,并且I / O错误也非常不可能。但是,如果转化说明符为%d
,则数据中的标点符号可能会导致“转换失败”。
在超过25年的C编码中,我的代码中有2个位置使用数千个文件中的feof()
(几个月前我做了check),并且在这两种情况下,代码都区分EOF和错误(大致如图所示)。
答案 1 :(得分:2)
feof
不会告诉您已经到达文件的末尾,直到。检查fscanf
的结果(返回值)。它会告诉你什么时候它不能再读了。如果fscanf
到达文件末尾,它将返回EOF(并且feof
将在发生这种情况后返回true。)
现在只是为了好玩,看看这种做法。实际上不要这样做。
while(1) {
switch(fscanf(f,"%s",a)){
case 1:
printf("%s ",a);
printf("%d\n",ftell(f));
continue;
case EOF:
break;
}
break;
}
这种方式错了,因为它是聪明的。在一些案例中,整个循环的行为将变得非常难以辨别(例如this program)。使用fscanf
,您实际上只需要知道是否获得了所需的所有数据。让下一个输入读取函数在找到它时处理EOF。 对fscanf
的此调用需要填写 x 数量的值,
if (fscanf(f,"%d %d %d", &i, &j, &k) != 3)
/* cannot continue. need i j k values for next computation */
然后执行错误响应,或退出循环,或者您的程序下一步需要做什么。但如果fscanf
返回3以外的任何内容,则它不会读取3个值。