C: strange behavior of feof [duplicate] - c

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 5 years ago.
I am new to C. I have stumbled upon certain behavior of feof I can't explain. Specifically in the code below I create a file, write one byte of information int it, then close and open it again, read the information (my 1 byte) till EOF is reached, then move the current position of the file pointer by 0 byte (i.e. do not change the current position at all) and suddenly I am not at the EOF any longer. How come?
#include <stdio.h>
#include <stdint.h>
typedef uint8_t BYTE;
int main(void) {
FILE* f = fopen("myfile.txt","w");
BYTE b = 0x0000;
fwrite(&b,1,1,f);
fclose(f);
f = fopen("myfile.txt","r");
while (!feof(f)){
fread(&b,1,1,f);
}
printf("We have reached EOF: %i \n",feof(f));
fseek(f,0,SEEK_CUR);
printf("We have reached EOF: %i \n",feof(f));
}
Output
We have reached EOF: 1
We have reached EOF: 0

From the fseek docs:
The end-of-file internal indicator of the stream is cleared after a successful call to this function, and all effects from previous calls to ungetc on this stream are dropped.

Related

Why extra 'ÿ' added when writing into a .txt file in C? [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 11 months ago.
I searched about this problem everywhere, but none of the suggested solutions worked for me.
char currentChar;
FILE *fp_read = fopen("../input.txt", "r");
FILE *fp_write = fopen("../textArranged.txt", "w");
while (!feof(fp_read)){
currentChar = fgetc(fp_read);
...
}
I tried to change the while condition (using getc()), but it didn't work.
feof() seems to return 0 after reading the last byte of the file. It returns 1 after fgetc() already made the attempt to read one more byte after the end of the file.
When fgetc() makes the attempt to read data after the end of the file, fgetc() returns -1.
If you perform fputc(x, ...) and x is not in the range 0...255, fputc() will actually write the byte (x & 0xFF).
On nearly all modern computers, (-1 & 0xFF) is 0xFF which equals the character 'ÿ'.
So the following happens:
...
Your program reads the last byte of the file using fgetc()
It writes that character using fputc()
Although there are no more bytes left in the file, feof() returns 0 because you did not make the attempt to read bytes after the end of the file, yet.
Your program calls fgetc() and because there are no more bytes left, fgetc() returns -1.
Your program calls fputc(-1, ...) which writes the character 'ÿ'.
feof() returns 1 because fgetc() already tried to read bytes after the end of the file.

What will fprintf do if it caused an error before? why? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Comment on the output of this C code:
#include <stdio.h>
int main()
{
char c;
int i = 0;
FILE *file;
file = fopen("test.txt", "w+");
fprintf(file, "%c", 'a');
fprintf(file, "%c", -1);
fprintf(file, "%c", 'b');
fclose(file);
file = fopen("test.txt", "r");
while ((c = fgetc(file)) != -1)
printf("%c", c);
return 0;
}
a) a
b) Infinite loop
c) Depends on what fgetc returns
d) Depends on the compiler
Answer: a
Explanation: None.
Why is the answer a?
I think it may result from the answer from the statement: “fprintf(file,"%c",-1)”.
After the error occurs,
why didn't the program output b?
Technically, the answer is (d), depends on the compiler. This is because char may be unsigned, in which case c = fgetc(file) will never evaluate to -1. Conversely, char may be signed, in which case c = fgetc(file) may evaluate to -1.
The result of an assignment is the value assigned to the left side (which is not the value of the right side but rather the value of the right side converted to the type of the left side). Thus, if char is unsigned, then c = fgetc(file) always has some value of an unsigned char, so it is never negative and can never be -1. The program then loops forever.
If char is signed, then, in normal conditions, the second fgetc(file) evaluation returns the character that was written to the file when -1 was written. Note that, for %c, fprintf converts its int argument to unsigned char (even if char is signed) and writes that. Thus, writing -1 results in writing UCHAR_MAX to the file. Similarly, fgetc returns an unsigned char converted to an int. Thus, in c = fgetc(file), we have the signed char being assigned the value UCHAR_MAX (typically 255). For assignment, this value is converted to signed char. When a value being converted does not fit in the new type, there is either an implementation-defined result or an implementation-defined signal. If the implementation produces -1, then the program normally stops after printing “a”. If the implementation raises a signal, it will be handled, typically by terminating the program. If the implementation neither signals nor produces -1, the program will continue by printing the resulting character and then printing “b”. After that, fgetc will normally return EOF. If the result of converting EOF to char is -1, then program will then stop. Otherwise, it will either raise a signal or continue printing the result of converting EOF to char indefinitely.
(Note: The question alludes to an error caused in or by fprintf. In normal circumstances, there is no error in fprintf(file, "%c", -1). For this call, fprintf writes the result of converting -1 to an unsigned char to the file.)
Additionally, we must consider that fopen could fail (e.g., due to permissions), fclose could fail (e.g., due to available disk space or a device error), and fopen could fail (e.g., due to another process removing the file between the fclose and the fopen). So none of the answers is complete.

Why can't I access EOF using fseek()? [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 6 years ago.
#include <stdio.h>
int main()
{
FILE * fp = fopen("Introduce.txt","rt");
fseek(fp,0,SEEK_END);
int i = feof(fp);
printf("%d",i);
fseek(fp,1,SEEK_END);
i = feof(fp);
printf("%d",i);
fseek(fp,-1,SEEK_END);
i = feof(fp);
printf("%d",i);
return 0;
}
I tried to access EOF positioning 'file position indicator' at the end of the file.
But the result of this code is "000".
Why does this happen?
The feof() function doesn't report that it is at EOF until you try to read some data and there is no data to read.
You can seek beyond the current EOF of a file that's open for writing (or that's open for reading and writing).
See while (!feof(file)) is always wrong for more information on why you seldom if ever need to use feof(). In some ways, feof() is a function you should forget about — most of your programs will improve if you assume it doesn't exist.
This documentation on feof is very clear (emphasis mine):
This function only reports the stream state as reported by the most
recent I/O operation, it does not examine the associated data source.
For example, if the most recent I/O was a fgetc, which returned the
last byte of a file, feof returns zero. The next fgetc fails and
changes the stream state to end-of-file. Only then feof returns
non-zero.
In typical usage, input stream processing stops on any error; feof and
ferror are then used to distinguish between different error
conditions.

Reading from a binary file using fread() displays additional characters [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 8 years ago.
My question is about this fread() function that seems to be confusing for the time being. I create a binary file and put inside of it the values 1,2 and 3. And then I try to read the file and when I do using fread() it shows it like 1233 not 123.
#include <stdio.h>
#include <stdlib.h>
main ()
{
int x=1,y=2,z=3,i,j;
FILE *f;
f=fopen("Werid.bin","wb");
fwrite(&x,sizeof(int),1,f);
fwrite(&y,sizeof(int),1,f);
fwrite(&z,sizeof(int),1,f);
fclose(f);
f=fopen("Werid.bin","rb");
if (!f) perror("X");
while(!feof(f))
{
fread(&j,sizeof(int),1,f);
printf("%d",j);
}
fclose(f);
}
Why?
Change this
while(!feof(f))
to
while(fread(&j,sizeof(int),1,f) == 1)
From linux feof() manual
The function feof() tests the end-of-file indicator for the stream pointed to by stream, returning nonzero if it is set. The end-of-file indicator can only be
cleared by the function clearerr().
The feof() will return true after you try to call fread() at the end of file i.e. after you read the last number, you will need to call fread() again to set the end-of-file indicator.
So the loop will be executed one more time after the last read, and since it does not read anything but rather returns an error, it does not change the value of j either, so the previous value 3 is printed again.

Repetition of final line when computing sum? [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 9 years ago.
I'm taking my first programming class ever this year and I'm slight confused on this. I'm trying to learn the fopen and fclose functions currently.
My code is
int main(void)
{
FILE *input; /* Pointer to the input file */
double values;
double sum;
input = fopen("data.dat", "r"); /* Prepare file for input */
sum = 0;
while (!feof(input))
{ fscanf(input, "%lf", &values);
sum = sum + values;
}
printf("The sum of the values is %f\n", sum);
fclose(input);
return 0;
}
When I compile this to get the sum, the last value of the data.dat file is counted for twice.
I was wondering how I could fix this.
Thanks!
You should not use while(!feof(...)) because it's always wrong. Why?
It will, as you found out, loop one more time than you expect. That happens because the semantics of feof() are not what you think: that is, they are not to check if the next read will reach the end of file. Instead, feof allows you distinguish between a read error and the end of the file after you get a zero from a read (or some other similar call).
The solution to your problem is easy: use the functions you call properly. fscanf returns a value - you should find out what that value is and, more importantly, what it means.

Resources