Reputation: 1713
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?
Upvotes: 2
Views: 12896
Reputation: 4515
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
Upvotes: 3
Reputation: 4731
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.
Upvotes: 2
Reputation: 732
Upvotes: 0
Reputation:
Try it replacing "a"
with "w+"
on the second fopen()
call. "a"
is intended for appending information at the end of the file. =)
Edit: However I would also pad the written number with some fixed spaces, otherwise, as the code is currently written, when the count exceeds 9 you will probably overwrite the end-of-line marker of the first line.
Upvotes: 0