Node:getc and fgetc, Next:, Previous:putchar, Up:Single-character input and output



getc and fgetc

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.

See File position, for information on ftell, fseek, and rewind. See End-of-file and error functions, for more information on feof and ferror.

#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.)