lee77
lee77

Reputation: 1503

Recover stdin from eof in C

I am using the C code below to read user input from a terminal. If the user inputs EOF, e.g. by pressing ^C, stdin is closed and subsequent attempts to read from it, e.g. via getchar() or scanf(), will cause an exception.

Is there anything I can do in C to "recover" my program, in the sense that if some user accidently inputs EOF, this will be ignored, so I can read from stdin again?

#include <stdio.h>

int main(void)
{
    int res_getchar=getchar();
    getchar();
    return 0;
}

Upvotes: 5

Views: 1409

Answers (3)

zwol
zwol

Reputation: 140540

If I understand the situation correctly - you're reading from a terminal via stdin, the user types ^D, you want to discard that and ask again for input - you have two options, one more portable (and quite simple) but less likely to work, and one less portable (and considerably more programming) but certain to work.

  • The clearerr function is standard C, and is documented to clear both the sticky error and sticky EOF flags on a FILE object; if your problem is that the C library isn't bothering to call read again once it's indicated EOF once, this may help.

    If this solves your immediate problem, make sure that if you get some number of EOFs in a row (four to ten, say) you give up and quit, because if stdin is not a terminal, or if the terminal has genuinely been closed down, that EOF condition is never going to go away, and you don't want your program to get stuck in an infinite loop when that happens.

  • On POSIX-compliant systems only (i.e. "not Windows"), you can use cfmakeraw to disable the input preprocessing that turns ^D into an EOF indication.

    Doing this means you also have to handle a whole lot of other stuff yourself; you may instead want to use a third-party library that handles it for you, e.g. readline (GPL) or editline (BSD). If your program is any sort of nontrivial interactive command interpreter, using one of these libraries is strongly encouraged, as it will provide a much nicer user experience.

Upvotes: 4

Yu Hao
Yu Hao

Reputation: 122383

Using ungetc() to push back a character can clear the EOF indicator for a stream.

C99 §7.19.7.11 The ungetc function

 int ungetc(int c, FILE *stream);

A successful call to the ungetc function clears the end-of-file indicator for the stream. The value of the file position indicator for the stream after reading or discarding all pushed-back characters shall be the same as it was before the characters were pushed back.

Upvotes: 1

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81684

In a word, no. You read EOF when the OS has closed stdin.

I am sure there are Platform-dependent ways to preserve some info that would let you reconstruct stdin after it was closed -- ie, open a new stream connected to the keyboard and assign it to stdin -- but there's definitely no portable way.

Upvotes: 0

Related Questions