2014-01-19 3 views
0

У меня есть список номеров в моем *.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; 
} 

ответ

3

Переход от тестирования feof() для тестирования fscanf()

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

feof(f) это не так, пока чтение не пройдет конец файла была предпринята попытка. Таким образом, предыдущий вызов fscanf(f, "%lf", &tmp) возвратил EOF в исходном коде OP, не обновляя tmp. Таким образом, tmp оказался 3 дважды.


Как @BLUEPIXY указывает, i = i - 1; не требуется. Если что-то может быть добавлено к if (i==0) для редкого случая без ввода.

+0

Лучшее решение для 'int cnt; while ((cnt = fscanf (f, "% lf", & tmp)! = 1) {'Тогда test' cnt'. 'EOF' означает EOF или IO Error, 0 означает, что не удалось преобразовать в' double', 1: означает 1 успешное преобразование. – chux

+0

Цифры в круглых скобках не совпадают в предыдущем комментарии. – BLUEPIXY

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. Вы должны были написать это, чтобы компенсировать тот факт, что цикл повторяется еще раз, чем предполагалось.

2

Это 3 раза, потому что feof (f) входит в цикл еще раз, чем вы ожидаете.

В этом случае функция feof() вызывается перед чтением любых данных, поэтому возвращает false. Петля введена, вызывается fgetc() (и возвращает EOF), а счет увеличивается. Затем вызывается feof() и возвращает true, в результате чего цикл прерывается.

Смежные вопросы