I have written a code
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp=fopen("lets.txt","r+");
if(fp==NULL)
{
printf("ERROR");
exit(1);
}
else
{
char ch,ch1;
while(!feof(fp))
{
ch= fgetc(fp);
printf("%c",ch);
}
printf("\n\nYou want to write something? (1/0)");
int n;
scanf("%d",&n);
if(n==1)
{
fputs("Jenny",fp);
ch1 = fgetc(fp);
printf("%c\n", ch1);
while(ch1 != EOF)
{
ch1=fgetc(fp);
printf("%c",ch1);
}
fclose(fp);
}
else{
printf("File Closed ");
fclose(fp);
}
}
}
I have tried to insert a string inside an already existing file "lets.txt"
but when I run this code, this is shown in the Terminal
I was expecting this to just put Jenny into the final file but it's also adding other text which was present before it and lots of NULL. Is this because of something like temporary memory storage or something like that or just some mistake in the code?
First of all, the lines
char ch,ch1;
while(!feof(fp))
{
ch= fgetc(fp);
printf("%c",ch);
}
are wrong.
If you want ch
to be guaranteed to be able to represent the value EOF
and also want to be able to distinguish it from every possible character code, then you must store the return value of fgetc
in an int
, not a char
. Please note that fgetc
returns an int
, not a char
. See this other answer for more information on this issue.
Also, the function feof
will only return a non-zero value (i.e. true) if a previous read operation has already failed due to end-of-file. It does not provide any indication of whether the next read operation will fail. This means that if fgetc
returns EOF
, you will print that value as if fgetc
were successful, which is wrong. See the following question for further information on this issue:
Why is “while( !feof(file) )” always wrong?
For the reasons stated above, I suggest that you change these lines to the following:
int ch, ch1;
while ( ( ch = fgetc(fp) ) != EOF )
{
printf( "%c", ch );
}
Another issue is that when a file is opened in update mode (i.e. it is opened with a +
in the mode string, for example "r+"
as you are doing), you cannot freely change between reading and writing. According to §7.21.5.3 ¶7 of the ISO C11 standard,
output shall not be directly followed by input without an intervening call to the fflush
function or to a file positioning function (fseek
, fsetpos
, or rewind
), and
input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
If you break any of these rules, than your program will be invoking undefined behavior, which means that anything can happen, which includes the possibility that you get invalid output.
For this reason, I suggest that you change the lines
fputs("Jenny",fp);
ch1 = fgetc(fp);
to:
fseek( fp, 0, SEEK_CUR );
fputs("Jenny",fp);
fflush( fp );
ch1 = fgetc(fp);
In contrast to the line fflush( fp );
, which is absolutely necessary, the line fseek( fp, 0, SEEK_CUR );
actually isn't necessary according to the rules stated above, because you encountered end-of-file. But it probably is a good idea to keep that line anyway, for example in case you later change your program to stop reading for some other reason besides end-of-file. In that case, that line would be required.