2

I read several same question and the answer does not satisfy me.

They think the best answer is:

while((ch = getchar()) != '\n') && ch != EOF);

There is a problem if I want to drain stdin before I asking for answer, like:

#define DRAIN() while((ch = getchar()) != '\n') && ch != EOF)
int fun() {
    ...
    DRAIN();       //aaa, wipe other's ass before me
    ch = getchar();//bbb, ask my answer
    DRAIN();       //ccc, wipe myown ass
    ...
}

The purpose of 'aaa' is to drain characters in stdin left by previous code, maybe before entering fun() by other unknow code.

But, if at 'aaa', there is no characters in stdin, 'aaa' will block there.

So what's the best choice?

=================

I tried below, no effect.

#define DRAIN() do {                                        \
    char ch___ = 0;                                                \
    fd_set fds___;                                                 \
    struct timeval tv___;                                          \
    int ret___ = 0;                                                \
    FD_ZERO(&fds___);                                              \
    FD_SET(STDIN_FILENO, &fds___);                                 \
    tv___.tv_sec = 0;                                              \
    tv___.tv_usec = 5000;                                          \
    ret___ = select(STDIN_FILENO + 1, &fds___, NULL, NULL, &tv___);\
    printf("ret:%d\n", ret___);                                    \
    if (ret___ > 0) {                                              \
        while(getchar());                                          \
    }                                                              \
}while(0)

int main()
{
    printf("#");
    fflush(stdout);

    getchar();

    DRAIN();

    printf(">");
    fflush(stdout);
    printf(":%c\n", getchar());

    DRAIN();

    return 0;
}

$ ./a.out
#123
ret:0
>:2
ret:0

====2nd edit====

Seem this works, I am in Linux env:

#define DRAIN() do {                             \
    int flg___ = 0;                              \
    int flg___bak = 0;                           \
    char ch___ = 0;                              \
    flg___    = fcntl(STDIN_FILENO, F_GETFL, 0); \
    flg___bak = flg___;                          \
    flg___    |= O_NONBLOCK;                     \
    fcntl(STDIN_FILENO, F_SETFL, flg___);        \
    while((ch___ = getchar()) != '\n' && ch___ != EOF);  \
    fcntl(STDIN_FILENO, F_SETFL, flg___bak);     \
}while(0)
  • 1
    Use ioctl. Look at [this](https://stackoverflow.com/questions/26948723/checking-the-stdin-buffer-if-its-empty). – fredrik Sep 30 '19 at 08:30
  • Are you making a game in console? Console is not intended for real-time input. It is not its purpose. There are so many problems, which you have to solve, that it's better to just make a GUI app, with windows and such. – Dialecticus Sep 30 '19 at 08:32
  • You cannot do this with a `FILE*`. You have to `read` from a file descriptor. So no `getchar`. – n. m. could be an AI Sep 30 '19 at 09:00
  • 3
    @Dialecticus there are plenty of console games. There is nothing wrong with the concept. – n. m. could be an AI Sep 30 '19 at 09:01
  • 1
    At any rate the whole thing is highly dubious. There are no "characters in stdin left by previous code". There are characters in stdin **typed ahead by the user**. If you just discard them, the user will not be happy. – n. m. could be an AI Sep 30 '19 at 09:04
  • There is no simple answer to this question. If there might be some leftover input, or might not be, and you want to drain it without blocking, there is no defined way to do this in portable C. You will have to use some feature specific to your operating system. With that said, it's straightforward to do in Unix/Linux, MacOS, and Windows. – Steve Summit Sep 30 '19 at 10:29
  • Why `DRAIN()` isn't a function? Instead of `fcntl F_SETFL` just `fcntl(...O_NONBLOCK...)` `char ch___ = 0;` and `ch___ = getchar()` is a common error, `EOF` may not fit inside `ch___`. – KamilCuk Sep 30 '19 at 10:58

1 Answers1

0

In the old days of DOS I was using the following sequence:

while ( kbhit() )
{
    ch = getch();
}

kbhit() was defined in conio.h, and is not portable, as far as I remember. However, you may be lucky to have access to it.

virolino
  • 2,073
  • 5
  • 21