Как проверить, пустой ли stdin перед очисткой stdin - PullRequest
0 голосов
/ 04 июля 2019

Я использовал код

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

чтобы очистить все в stdin в моих программах. Однако в некоторых случаях я сталкиваюсь с небольшой проблемой. В моих программах бывают случаи, когда, когда я звоню getchar(), в stdin может быть или не быть ничего. Когда случается, что в stdin ничего нет, то в итоге происходит getchar(), и он ждет чего-то в stdin. Затем я должен ввести \ n на клавиатуре, иначе программа просто застрянет на этой строке. Мне интересно, есть ли простой способ сначала проверить, является ли stdin пустым, прежде чем делать while (getchar() != '\n');, чтобы избежать этой проблемы?

Не уверен, что компилятор имеет значение для ответа, но я использую Visual Studio 2017. Изменить: когда я говорю stdin, я имею в виду символы, введенные с клавиатуры

Ответы [ 3 ]

1 голос
/ 04 июля 2019

stdin - это поток. Если процесс читает из консоли, пока вы не закроете поток, процесс все еще будет читать из потока. С терминала вы закрываете входной поток, нажимая ^ D.

Приложение не умеет читать мысли. Он не может знать, когда поток «ГОТОВО». Если вы хотите прочитать данные в потоке и хотите завершить процесс до того, как поток не будет завершен, вам нужно установить поток в неблокированный. Читайте, пока ничего не вернется и процесс не завершится.

Как вы делаете неблокирующий консольный ввод / вывод в Linux в C?

0 голосов
/ 08 июля 2019

Поскольку вы работаете в Windows с VS, используйте _kbhit (), который проверяет, есть ли в стандартном файле ny символов.

#include <conio.h>

int main()
{
  if (_kbhit()) while (getchar() != '\n');
  ...
  return 0;
}
0 голосов
/ 04 июля 2019

Давным-давно я делал что-то подобное

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...