Как безопасно слить stdin? - PullRequest
2 голосов
/ 30 сентября 2019

Я прочитал несколько одинаковых вопросов, и ответ меня не удовлетворяет.

Они думают, что лучший ответ:

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

Существует проблема, если я хочу слить stdin до того, как язапрашивая ответ, например:

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

Цель 'aaa' - слить символы в stdin, оставленные предыдущим кодом, возможно, перед вводом fun () с помощью другого неизвестного кода.

Но, если в 'aaa' нет символов в stdin, 'aaa' там заблокируется.

Так какой же лучший выбор?

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

Я пробовал ниже, без эффекта.

#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

==== 2-е редактирование ====

Кажется, это работает, я в 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 Ответ

0 голосов
/ 30 сентября 2019

В старые времена DOS я использовал следующую последовательность:

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

kbhit() был определен в conio.h и является не переносимым , насколько яПомните. Однако вам может повезти, что у вас есть доступ к нему.

...