【问题标题】:How to read numbers from file and calculate the mean? [duplicate]如何从文件中读取数字并计算平均值? [复制]
【发布时间】:2014-02-08 14:11:41
【问题描述】:

我的*.txt 文件中有一个数字列表:

1 2  
3

呼叫numbers.txt。我需要阅读它们并计算平均值,对于我的文件,它将是:(1 + 2 + 3) / 3 = 2; 虽然我的代码显示了一些错误的结果,但它读取了 3 两次。为什么会这样,如何解决?

我的代码:

#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;
}

【问题讨论】:

    标签: c file fopen


    【解决方案1】:

    您实际上并没有阅读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。您必须编写它来补偿循环比预期迭代多一次这一事实。

    【讨论】:

      【解决方案2】:

      从测试feof() 更改为测试fscanf()

      while(fscanf(f, "%lf", &tmp) != EOF) {
        printf("tmp = %f \n", tmp);
        sum += tmp;
        ++ i;
      }
      

      feof(f) 在尝试读取文件末尾之前不为真。因此,之前对fscanf(f, "%lf", &amp;tmp) 的调用在OP 的原始代码中返回了EOF,而不是更新tmp。所以tmp 似乎是3 两次。


      正如@BLUEPIXY 指出的那样,不需要i = i - 1;。如果有什么可以添加 if (i==0) 的测试,以应对罕见的无输入情况。

      【讨论】:

      • 最好的解决方案是int cnt; while((cnt = fscanf(f, "%lf", &amp;tmp) != 1) { 然后测试cntEOF 表示 EOF 或 IO 错误,0 表示转换为 double 失败,1:表示 1 次转换成功。
      • 括号中的数字与上一条评论不一致。
      【解决方案3】:

      读取 3 两次是因为 feof(f) 进入循环的次数比您预期的多一次。

      在这种情况下,在读取任何数据之前调用 feof(),因此它返回 false。进入循环,调用 fgetc()(并返回 EOF),并且计数递增。然后调用 feof() 并返回 true,导致循环中止。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        • 2019-08-08
        • 1970-01-01
        • 2014-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多