清除stdin之前如何检查stdin是否为空

时间:2019-07-04 18:47:10

标签: c windows visual-c++ stdin

我一直在使用代码

while (getchar() != '\n');

清除程序中stdin中的所有内容。但是,在某些情况下,我遇到了一个小问题。在程序中,有时我调用getchar()时,stdin中可能没有任何内容。在stdin中什么也没有的情况下,最终发生的是getchar()被调用,并且它正在等待stdin中的某些内容。然后,我必须在键盘上输入\ n,否则程序只会停留在那一行上。我想知道是否有一种简单的方法可以在执行stdin之前先检查while (getchar() != '\n');是否为空,以避免出现此问题?

不确定编译器是否对答案很重要,但是我正在使用Visual Studio 2017。 编辑:当我说标准输入时,我指的是键盘输入的字符

3 个答案:

答案 0 :(得分:1)

stdin是流。如果某个进程正在从控制台中读取,则只要您不关闭流,该进程仍会从该流中读取。在终端,您可以通过按^ D来关闭输入流。

应用程序不是读心者。它不知道流何时为“完成”。如果要读取流中的数据并要在未完成流之前关闭进程,则需要将流设置为非阻塞。阅读,直到什么都没有回来并且该过程退出。

How do you do non-blocking console I/O on Linux in C?

答案 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;
}