我一直在使用代码
while (getchar() != '\n');
清除程序中stdin
中的所有内容。但是,在某些情况下,我遇到了一个小问题。在程序中,有时我调用getchar()
时,stdin
中可能没有任何内容。在stdin
中什么也没有的情况下,最终发生的是getchar()
被调用,并且它正在等待stdin
中的某些内容。然后,我必须在键盘上输入\ n,否则程序只会停留在那一行上。我想知道是否有一种简单的方法可以在执行stdin
之前先检查while (getchar() != '\n');
是否为空,以避免出现此问题?
不确定编译器是否对答案很重要,但是我正在使用Visual Studio 2017。 编辑:当我说标准输入时,我指的是键盘输入的字符
答案 0 :(得分:1)
stdin是流。如果某个进程正在从控制台中读取,则只要您不关闭流,该进程仍会从该流中读取。在终端,您可以通过按^ D来关闭输入流。
应用程序不是读心者。它不知道流何时为“完成”。如果要读取流中的数据并要在未完成流之前关闭进程,则需要将流设置为非阻塞。阅读,直到什么都没有回来并且该过程退出。
答案 1 :(得分:0)
很久以前,我曾经做过这样的事情
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int /* 0: success -1: error */
setBlockingFD(int fileDescriptor,
int blocking)
{
int r=fcntl(fileDescriptor,F_GETFL);
if(r==-1)
{
perror("fcntl(F_GETFL)");
return -1;
}
int flags=(blocking ? r & ~O_NONBLOCK : r | O_NONBLOCK);
r=fcntl(fileDescriptor,F_SETFL,flags);
if(r==-1)
{
perror("fcntl(F_SETFL)");
return -1;
}
return 0;
}
void
discardInput(void)
{
setBlockingFD(STDIN_FILENO, 0);
for(;;)
{
int c=fgetc(stdin);
if(c==EOF)
{
if(errno==EAGAIN) // just to understand the example
{
printf("nothing more in input\n");
}
break;
}
else
{
printf("discarding <%c>\n", c); // just to understand the example
}
}
setBlockingFD(STDIN_FILENO, 1);
}
int
main(void)
{
for(;;)
{
discardInput();
printf("enter an integer and something else\n");
int value;
if(scanf("%d", &value)==1)
{
printf("value=%d\n", value);
}
else
{
printf("no integer\n");
break;
}
}
return 0;
}
将输入文件描述符配置为非阻塞时,如果没有待处理的输入,则将errno
设置为EAGAIN
会失败。
注意:我更喜欢这种解决方案,而不是基于select()
的解决方案,因为select()
不会知道输入流(FILE *
的缓冲区中已经存在的数据不是文件描述符),必须将其丢弃。
edit:此解决方案仅适用于POSIX系统;在Windows上,仅适用于WSL。
答案 2 :(得分:0)
由于您在Windows上使用VS,请使用_kbhit()来检查stdin中是否有ny个字符。
#include <conio.h>
int main()
{
if (_kbhit()) while (getchar() != '\n');
...
return 0;
}