Давным-давно я делал что-то подобное
#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.