Once a file is open, we might want to read input from it. There are three common functions in C for reading from a file: fgetc
, fgets
, and fread
. Here’s a breakdown of how fgetc
works:
Prototype:
int fgetc(FILE * stream);
fgetc
to return a char
, it actually returns an int
. This allows it to return all possible character values, plus a distinct value to indicate the end of the file (EOF). The EOF value is defined as a constant in stdio.h
.fgetc
, it reads a character and advances the stream’s position.Common Issue in Loops:
When reading characters in a loop, beginners often encounter issues because fgetc
advances the stream’s position with each call. Consider this incorrect code:
//broken
FILE * f = fopen(inputfilename, "r");
if (f == NULL) { /* error handling code omitted */ }
while (fgetc(f) != EOF) {
char c = fgetc(f);
printf("%c", c);
}
Correct Approach:
To fix this, we can leverage the fact that assignment is also an expression, meaning it both assigns a value and evaluates to that value. This allows us to combine the assignment and the EOF check in one line:
//fixed
FILE * f = fopen(inputfilename, "r");
if (f == NULL) { /* error handling code omitted */ }
int c;
while ( (c = fgetc(f)) != EOF ) {
printf("%c", c);
}
Here’s what happens:
fgetc(f)
to c
inside the loop condition. This assignment is wrapped in parentheses to ensure the correct order of operations.Why int
Instead of char
?
The variable c
is declared as an int
, not a char
. If we used char
, our code would introduce a subtle bug:
fgetc
returns an int
so it can represent all possible character values plus the EOF value. If you store the result in a char
, which can only hold 256 different values, you might lose information.1
, but a char
can only hold values from 0 to 255. This means if your file contains a character with the value 255, your program would misinterpret it as EOF and stop reading prematurely.