editing a specific line of a file in C

12,224

Solution 1

For fopen modes see http://www.cplusplus.com/reference/cstdio/fopen/. I think you need to use the option r+ because you are modifying the file in a random-access way fior both read and write.

"r+" read/update: Open a file for update (both for input and output). The file must exist.

"w+" write/update: Create an empty file and open it for update (both for input and output). If a file with the same name already exists its contents are discarded and the file is treated as a new empty file.

"a+" append/update: Open a file for update (both for input and output) with all output operations writing data at the end of the file. Repositioning operations (fseek, fsetpos, rewind) affects the next input operations, but output operations move the position back to the end of file. The file is created if it does not exist.

I would suggest storing the number of lines in the file as an unsigned integer and not a string. The reason is that as a string 0-9 lines take one byte, but the minute you have 10 lines you need two byes, 100, 3 bytes and so on. In each case when an extra character is required you would have to re-write the entire file. I presume this is why you check that number of scores is less than 10.

A better solution would be to keep the first 4 bytes of the file as an unsigned integer and then start the ascii text after.

int      result;
uint32_t number_of_scores;
size_t   bytesRead;
FILE     *data;

...

/* Open a file for update (both for input and output).
* The file must exist. */
data = fopen("highscore.txt","r+");
if( !data ) 
    exit(SOME_ERROR_CODE);

/* Read a 32-bit unsigned integer from the file. NOTE there is no endianess
 * "protection" here... ignoring this issue for the sake of simplicity and relevance */
bytesRead = fread (&number_of_scores, sizeof(number_of_scores), 1, data);   
if( bytesRead != 1 )
    exit(SOME_ERROR_CODE);

/* Seek to end of file */
result = fseek(data, 0, SEEK_END);    
if( result )
    exit(SOME_ERROR_CODE);

/* Write in the next line */
result = fprintf(data,
                 "%s  %s  %s  %s\n", 
                 user[current_user].name,
                 user[current_user].age, 
                 user[current_user].college,
                 resultVariableRenamedToAvoidNameCollision);

 /* Up the number of scores and write it back to the start of the file */
 number_of_scores++;
 result = fseek(data, 0, SEEK_SET);      
 if( result )
     exit(SOME_ERROR_CODE);

 bytesRead = fwrite (data, sizeof(number_of_scores), 1, data);
 if( bytesRead != 1 )
    exit(SOME_ERROR_CODE);

 fclose(data);

Doh, and I've just realised how late this answer is... never mind :S

Solution 2

You need to open the file in read-and-write mode ("r+"), not append ("a"). The write position will be at the start, initially, so you might as well update the line count first. Then you can fseek(data, 0, SEEK_END) before appending your new line.

Share:
12,224
Nasif Imtiaz Ohi
Author by

Nasif Imtiaz Ohi

Updated on June 27, 2022

Comments

  • Nasif Imtiaz Ohi
    Nasif Imtiaz Ohi almost 2 years

    I am facing a problem in C to edit a specific line of a file. There is a number in the beginning of the file which is followed by a number of lines. It kind of looks like this.

    2
    Nasif  20  BUET  130
    Oishi  24  KMC  131
    

    After each execution, I append one more line in the file. And the first number in the file (which actually indicates the number of lines) increases by 1. This process seems not to be working.

    data=fopen("highscore.txt","r");
    fscanf(data,"%d",&number_of_scores);
    fclose(data);
    if(number_of_scores<10){
        data=fopen("highscore.txt","a");
        fprintf(data,"%s  %s  %s  %s\n", user[current_user].name,
                user[current_user].age, user[current_user].college,result);
        number_of_scores++;
        fseek(data,0,0);
        fprintf(data,"%d",number_of_scores);
        fclose(data);
    }
    else{
    
    }
    

    So, what should be the right approach?