If you want to read a single character from a stream other than
stdin, you can use the getc function. This function is
very similar to getchar, but accepts an argument that specifies
the stream from which to read. It reads the next character from the
specified stream as an unsigned char, and returns its value,
converted to an integer. If a read error occurs or the end of the file
is reached, getc returns EOF instead.
Here is a code example that makes use of getc. This code example
creates a text file called snazzyjazz.txt with fopen,
writes the alphabet in upper-case letters plus a newline to it with
fprintf, reads the file position with ftell, and gets the
character there with getc. It then seeks position 25 with
fseek and repeats the process, attempts to read past the end of
the file and reports end-of-file status with feof, and generates
an error by attempting to write to a read-only stream. It then reports
the error status with ferror, returns to the start of the file
with rewind and prints the first character, and finally attempts
to close the file and prints a status message indicating whether it
could do so.
#include <stdio.h>
int main()
{
int input_char;
FILE *my_stream;
char my_filename[] = "snazzyjazz.txt";
long position;
int eof_status, error_status, close_error;
my_stream = fopen (my_filename, "w");
fprintf (my_stream, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
/* Close stream; skip error-checking for brevity of example */
fclose (my_stream);
printf ("Opening file...\n");
my_stream = fopen (my_filename, "r");
position = ftell (my_stream);
input_char = getc (my_stream);
printf ("Character at position %d = '%c'.\n\n", position, input_char);
printf ("Seeking position 25...\n");
fseek (my_stream, 25, SEEK_SET);
position = ftell (my_stream);
input_char = getc (my_stream);
printf ("Character at position %d = '%c'.\n\n", position, input_char);
printf ("Attempting to read again...\n");
input_char = getc (my_stream);
eof_status = feof (my_stream);
printf ("feof returns %d.\n\n", eof_status);
error_status = ferror (my_stream);
printf ("ferror returns %d.\n", error_status);
printf ("Attempting to write to this read-only stream...\n");
putc ('!', my_stream);
error_status = ferror (my_stream);
printf ("ferror returns %d.\n\n", error_status);
printf ("Rewinding...\n");
rewind (my_stream);
position = ftell (my_stream);
input_char = getc (my_stream);
printf ("Character at position %d = '%c'.\n", position, input_char);
close_error = fclose (my_stream);
/* Handle fclose errors */
if (close_error != 0)
{
printf ("File could not be closed.\n");
}
else
{
printf ("File closed.\n");
}
return 0;
}
There is another function in the GNU C Library called fgetc. It
is identical to getc in most respects, except that getc is
usually implemented as a macro function and is highly optimised, so is
preferable in most situations. (In situations where you are reading
from standard input, getc is about as fast as fgetc, since
humans type slowly compared to how fast computers can read their input,
but when you are reading from a stream that is not interactively
produced by a human, fgetc is probably better.)