Как читать числа из файла и сохранять их среднее значение в тот же файл?

У меня есть текстовый файл с двумя столбцами:

1 2
3 4
5 6
7 8

Я хотел бы прочитать эти числа, вычислить среднее значение и сохранить результат в третий столбец того же файла. Я открыл свой файл для обновления "r+", но, похоже, он не работает. Чтение идет нормально, но когда я добавляю третий столбец, с файлом происходит что-то не то... Кажется, что он перезаписывается, в нем нет исходного содержимого, когда я вызываю свой fun - после первой инструкции цикла. Любые идеи?

#include <stdio.h>
#include <stdlib.h>

void fun(const char *filename)
{
    double num1 = 0, num2 = 0, num3 = 0;
    FILE *f;
    if((f = fopen(filename, "r+")) == NULL)
    {
        exit(-1);
    }

    while(fscanf(f, "%lf %lf", &num1, &num2) != EOF)
    {
        //printf("num1 = %.2f, num2 = %.2f\n", num1, num2);
        num3 = num1 + num2;
        fprintf(f, "%lf %lf %lf\n", num1, num2, num3/2.0);
    }

    fclose(f);
}

int main(int argc, char **argv)
{
    fun("numbers.txt");

    return 0;
}

Когда моя программа завершает выполнение, я хотел бы иметь в своем текстовом файле 3 столбца:

1 2 1.5
3 4 3.5
5 6 5.5
7 8 7.5

Попытался также это, но моя программа просто зависает:

#include <stdio.h>
#include <stdlib.h>

void fun(const char *filename)
{
    double num1 = 0, num2 = 0, num3 = 0;\

    FILE *f;
    if((f = fopen(filename, "r+")) == NULL)
    {
        exit(-1);
    }

    int write_at = 0, read_at = 0;

    while(fscanf(f, "%lf %lf", &num1, &num2) != EOF)
    {
        read_at = ftell(f);
        fseek(f, write_at, SEEK_SET);
        num3 = num1 + num2;
        fprintf(f, "%lf %lf %lf\n", num1, num2, num3/2.0);
        write_at = ftell(f);
        fseek(f, read_at, SEEK_SET);
    }

    fclose(f);
}

int main(int argc, char **argv)
{
    fun("numbers.txt");
    return 0;
 }

person Brian Brown    schedule 19.01.2014    source источник
comment
Происходит что-то не так - бесполезное описание...   -  person Oliver Charlesworth    schedule 19.01.2014
comment
Кажется, что вы читаете и пишете в файл [i]одновременно[/i]. Почему бы сначала не прочитать данные, не сохранить их, а затем, наконец, записать?   -  person rhughes    schedule 19.01.2014
comment
Вероятно, вы перезаписываете части файла (вы не можете просто добавлять символы в такую ​​строку, файлы — это просто необработанные двоичные данные на низком уровне). Считайте файл в массив, вычислите средние значения, затем запишите строки обратно в файл.   -  person    schedule 19.01.2014
comment
@ H2CO3: как насчет моего второго решения - вы можете помочь, почему оно не работает?   -  person Brian Brown    schedule 19.01.2014
comment
@BrianBrown Это не работает по той же причине.   -  person    schedule 19.01.2014
comment
@ H2CO3: так, как вы написали, это ЕДИНСТВЕННЫЙ правильный способ сделать это?   -  person Brian Brown    schedule 19.01.2014
comment
@BrianBrown Я не думаю, что это единственно правильный способ, но это, безусловно, один из самых очевидных / прямолинейных правильных способов.   -  person    schedule 19.01.2014
comment
@BrianBrown хорошо, решение H2CO3 - это простой способ его реализовать. Вы можете выполнять чтение/запись в одном цикле, используя getline(), но это сложно, потому что вам нужно позиционировать файловый курсор обратно в предыдущий конец, чтобы вставить туда данные.   -  person KarelG    schedule 19.01.2014


Ответы (1)


Откройте временный файл и сохраните там результаты. После успешного завершения чтения всего «numbers.txt» и записи временного файла удалите оригинал и переименуйте временный файл.

При обработке файлов это имеет приятное преимущество: если процесс каким-либо образом завершается сбоем (ошибка ввода-вывода, ошибка формата данных и т. д.), оригинал остается неповрежденным. Довольно часто встречается с редакторами.

Другой подход состоит в том, чтобы сохранить «новый» файл в памяти и записать его в конце.

person chux - Reinstate Monica    schedule 19.01.2014