Редактирование строки в текстовом файле с помощью временного файла C

Я пытаюсь отредактировать строку в текстовом файле, но у меня неожиданное поведение при редактировании файла. Что я хочу сделать, так это настроить определенную строку (точки: 100) текста, который выглядит так. В функции я передаю аргументы по значению новых монет, которые нужно настроить, и смещению файла с помощью ftell->user_point. То, что я получаю в качестве вывода, странно. Я пытаюсь скопировать остальную часть файла во временный файл с отредактированной строкой, а затем скопировать его обратно в исходный файл из точки, которую я скопировал во временный файл (это смещение user_point с помощью ftell). Вот оригинальный фай с такими записями:

...    
_______________________________________
    nickname     : geo
    password     : cuvctq
    Name         : george
    Surname      : papas
    points       : 100
    participated : 
    past draws   : 0
    Chosen No.   : 
    future draws : 0
    Registered   : Sun Feb 05 19:23:50 2012
...

Что я получаю после второго запуска редактирования:

...
    _______________________________________
    nickname     : geo
    password     : cuvctq
    Name         : george
    Surname      : papaspoints       : 98
    participated : 
    past draws   : 0
    Chosen No.   : 
    future draws : 0
    Registered   : Sun Feb 05 19:23:50 2012
...
At the end of the text i get one extra \n after i edit the 
file whch is something i dont want :/

и поэтому дальнейшее редактирование испортит текст... Я также получаю ДОПОЛНИТЕЛЬНУЮ \n в конце строки, что, по крайней мере, я так думаю, из-за режима "r+", чего я тоже не хочу...

void coins_adjust(int coins_new,int user_point)
{
    int lines,i,ln_point_copy;
    char buffer[50],buff_copied[50];
    FILE *lottary,*temp;

    memset(buff_copied,'\0',sizeof(char)*50);
    lottary=fopen("customers.txt","r");
    temp=fopen("temp.txt","w");
    fseek(lottary,user_point,SEEK_SET);
    for (lines=0;lines<5;lines++)
    {
        memset(buffer,'\0',sizeof(char)*50);
        if (lines==5)
            ln_point_copy=ftell(lottary);       //from TEMP to CUSTOMERS
        fgets (buffer ,50 , lottary);
    }
    coins_new+=atoi(buffer+15);

    strncpy(buff_copied,buffer,15);     //copy 15 chars and fill with null
    memset(buffer,'\0',sizeof(char)*50);
    itoa (coins_new,buffer,10);          //fix the new line to be entered
    strcat(buff_copied,buffer);          //the edited line is as it is supposed
    strcat(buff_copied,"\n");            //to be with \n at the end.
    puts(buff_copied);

    printf("%s",buff_copied);fflush(stdout);
    fprintf(temp,"%s",buff_copied);
    for(i=getc(lottary); i!=EOF; i=getc(lottary))  //copy to temp
    {
        putc(i, temp);
    }
    fclose(lottary);
    fclose(temp);

    temp=fopen("temp.txt","r");
    lottary=fopen("customers.txt","r+");
    fseek(lottary,ln_point_copy,SEEK_SET);
    for(i=getc(temp); i!=EOF; i=getc(temp))     //copy until eof
    {
        putc(i, lottary);
    }
    fclose(lottary);fclose(temp);

}

Я отладил программу, и все, кажется, работает, по крайней мере, на том, какие значения передаются в массивы, где я храню символы строки, но я не понимаю, почему она игнорирует \n предыдущей строки, когда я пытаюсь скопировать ее обратно в оригинал. .. Кажется, есть символ \r, от которого я не могу избавиться, пока копирую обратно в оригинал... Заранее спасибо.


person BugShotGG    schedule 06.02.2012    source источник
comment
Почему бы не читать по одной строке за раз, и если она содержит то, что вы хотите изменить, измените ее и запишите строку в новый файл. Тогда фактическое положение строки, которую вы хотите изменить, может быть где угодно, и вам не нужно беспокоиться о вашей программе, если формат файла изменится.   -  person Some programmer dude    schedule 06.02.2012
comment
@JoachimPileborg На самом деле это то, что я делаю более или менее, но таких записей может быть сотни и т. Д. Поэтому мне нужно отредактировать строку и поместить ее туда, где она была.   -  person BugShotGG    schedule 06.02.2012


Ответы (1)


Я больше думал о чем-то вроде этого:

void change_points(int new_points)
{
    FILE *input  = fopen("customers.txt", "r");
    FILE *output = fopen("temp.txt", "w");

    char buffer[256];

    while (fgets(buffer, sizeof(buffer), input))
    {
        /* Look for the correct line */
        /* Can also use e.g. "if (strncmp(buffer, "points", 6) == 0)"
         * if it's at the start of the line
         */
        if (strstr(buffer, "points") != NULL)
        {
            int old_points;

            sscanf(buffer, "%*s : %d ", &old_points);

            /* Format how you like it */
            fprintf(output, "%-13s: %d\n", "points", new_points + old_points);
        }
        else
            fputs(buffer, output);
    }

    fclose(output);
    fclose(input);

    /* The file "temp.txt" now contains the modifeed text */
    /* Copy either using "fgets"/"fputs", or using "fread"/"fwrite" */

    input  = fopen("temp.txt", "r");
    output = fopen("customers.txt", "w");

    while (fgets(buffer, sizeof(buffer), input))
        fputs(buffer, output);

    fclose(output);
    fclose(input);
}

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

person Some programmer dude    schedule 06.02.2012
comment
Ну, мне нужно знать, где это, так как в файле сотни регистраций, а не только 1 :( Я до сих пор не понимаю, почему он пропускает \n после второй попытки. - person BugShotGG; 07.02.2012
comment
Я полностью переписал свой код, и он работает, но я до сих пор не понимаю, почему он не работает. Что-то, казалось, было неуместно с режимом файла r+. :( - person BugShotGG; 07.02.2012