问题
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;
}
回答1:
Using ungetc()
to push back a character can clear the EOF indicator for a stream.
C99 §7.19.7.11 The
ungetc
functionint 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.
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/19744423/recover-stdin-from-eof-in-c