如何从文件中读取数字并计算平均值?

时间:2014-01-19 12:06:41

标签: c file fopen

我的*.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;
}

3 个答案:

答案 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,导致循环中止。