我的*.txt
文件中有一个数字列表:
1 2
3
名为numbers.txt
。我需要读取它们并计算平均值,对于我的文件它将是:(1 + 2 + 3) / 3 = 2;
虽然我的代码显示了一些错误的结果,但它读取了两次。为什么,如何解决?
我的代码:
#include <stdio.h>
#include <stdlib.h>
double fun(const char *filename)
{
double sum = 0, mean = 0, tmp = 0;
int i = 0;
FILE *f;
if((f = fopen(filename, "r")) == NULL)
{
exit(-1);
}
while(!feof(f))
{
fscanf(f, "%lf", &tmp);
printf("tmp = %f \n", tmp);
sum += tmp;
++ i;
}
i = i - 1;
mean = sum / i;
fclose(f);
printf("i = %d\n", i);
printf("sum = %f\n", sum);
printf("mean = %f\n", mean);
return mean;
}
int main(int argc, char **argv)
{
fun("numbers.txt");
return 0;
}
答案 0 :(得分:4)
您实际上并没有两次阅读3
。
问题是在最后一个数字(3
)之后,还有其他字符,即空格。因此,读取最后一个数字后不会引发EOF标志,并且while
循环进入另一个迭代。 fscanf
没有读取任何值,但前一个仍在tmp
,会再次处理。
你应该做的是检查fscanf
的返回值,它会告诉你实际扫描和转换的参数数量。它应该是1
,因为您正在尝试扫描一个变量。修复您的代码,如:
while(!feof(f))
{
if (fscanf(f, "%lf", &tmp) != 1) {
// No numbers
break;
}
printf("tmp = %f \n", tmp);
sum += tmp;
++ i;
}
并删除i = i - 1
。你必须编写它来补偿循环再次迭代一次的事实。
答案 1 :(得分:3)
从测试feof()
更改为测试fscanf()
while(fscanf(f, "%lf", &tmp) != EOF) {
printf("tmp = %f \n", tmp);
sum += tmp;
++ i;
}
在尝试读取文件结尾之前, feof(f)
不成立。因此,fscanf(f, "%lf", &tmp)
之前的调用在OP的原始代码中返回EOF
,而不是更新tmp
。因此tmp
似乎是3
两次。
正如@BLUEPIXY指出的那样,不需要i = i - 1;
。如果在没有输入的罕见情况下可以添加if (i==0)
的任何测试。
答案 2 :(得分:2)
它读取3次,因为feof(f)比你期望的更多次进入循环。
在这种情况下,在读取任何数据之前调用feof(),因此返回false。进入循环,调用fgetc()(并返回EOF),并递增计数。然后调用feof()并返回true,导致循环中止。