【发布时间】:2020-01-29 10:37:14
【问题描述】:
我读了几个相同的问题,但答案并不让我满意。
他们认为最好的答案是:
while((ch = getchar()) != '\n') && ch != EOF);
如果我想在我要求答案之前耗尽标准输入,就会出现问题,例如:
#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
====第二次编辑====
看来这可行,我在 Linux 环境中:
#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)
【问题讨论】:
-
使用 ioctl。看this。
-
您是在控制台上制作游戏吗?控制台不适用于实时输入。这不是它的目的。有太多的问题需要解决,最好还是做个GUI应用,有windows之类的。
-
您无法使用
FILE*执行此操作。您必须从文件描述符中read。所以没有getchar。 -
@Dialectus 有很多主机游戏。这个概念没有错。
-
无论如何,整件事都非常可疑。没有“先前代码留下的标准输入中的字符”。 stdin 中有用户预先输入的字符。如果您只是丢弃它们,用户将不会高兴。