EOF considered harmful

Frank Wales frank at zen.co.uk
Tue Oct 24 22:49:19 AEST 1989


In article <266 at m1.cs.man.ac.uk> ian at r6.UUCP (Ian Cottam) writes:
>Some observations on the little program below (following some recent
>discussions in this group):
>_______________________
>#include <stdio.h>
>
>int
>main()
>{
>	char ch;
>	while ( ! feof(stdin) ) {
>		ch= getchar();
>		putchar(ch);
>	}
>
>	return 0;
>}

Unfortunately, this program may not work correctly.  The manual for
feof(3) states:

  "Feof returns non-zero when EOF has *previously* been detected reading
   the named input stream, otherwise zero".  [my emphasis]

This causes one extra getchar()/putchar() cycle to be executed after EOF
before the program stops, which in turn results in passing putchar() something
that probably doesn't look like EOF any more, not that putchar() has to
cope with being handed EOF in any case.  Pascal programmers beware.  :-)

Running this program on HP-UX 3.1 and SunOS 4.0.1, I always get at least
one extra char at EOF, usually a space.

Alternative versions of the above could be:

    #include<stdio.h>
    main()
    {
      char c=getchar();

      while (!feof(stdin))
      {
	(void)putchar(c);
	c=getchar(c);
      }
      return 0;
    }

or, according to taste:

    #include<stdio.h>
    main()
    {
      for(;;)
      {
	char c=getchar();
	if (feof(stdin))
	  return 0;
	(void)putchar(c);
      }
    }

On the very odd occasion when I have used feof() in a loop condition, I have
always ensured that it was valid to check it, if necessary by throwing in

    ungetc(getc(stream),stream);  /* grungy hack */

ahead of it.  I haven't done this too often, though, since it is rare that
I need to test for end of file on a stream separate from reading the
stream itself, and rarer that I can't rearrange the logic to avoid it.
--
Frank Wales, Systems Manager,        [frank at zen.co.uk<->mcvax!zen.co.uk!frank]
Zengrange Ltd., Greenfield Rd., Leeds, ENGLAND, LS9 8DB. (+44) 532 489048 x217 



More information about the Comp.lang.c mailing list