Как использовать select() для чтения ввода с клавиатуры в C
Я пытаюсь использовать select() для чтения ввода с клавиатуры, и я застрял в том, что я не знаю, как читать с клавиатуры, и для этого использую файловый дескриптор. Мне сказали использовать STDIN и STDIN_FILENO для решения этой проблемы, но я все еще в замешательстве.
Как мне это сделать?
3 ответа
Ваш вопрос звучит немного запутанным. select()
используется для блокировки до тех пор, пока ввод не будет доступен. Но вы делаете реальное чтение с обычными функциями чтения файлов (например, read
,fread
,fgetc
, так далее.).
Вот быстрый пример. Он блокируется, пока в stdin не появится хотя бы один символ, доступный для чтения. Но, конечно, если вы не переключите терминал в какой-нибудь сырой режим, он будет блокироваться до тех пор, пока вы не нажмете клавишу ввода, когда любые введенные символы будут сброшены в буфер файлов (из некоторого буфера терминала).
#include <stdio.h>
#include <sys/select.h>
int main(void) {
fd_set s_rd, s_wr, s_ex;
FD_ZERO(&s_rd);
FD_ZERO(&s_wr);
FD_ZERO(&s_ex);
FD_SET(fileno(stdin), &s_rd);
select(fileno(stdin)+1, &s_rd, &s_wr, &s_ex, NULL);
return 0;
}
Как уже было сказано, с помощью select вы можете просто контролировать, например, stdin, чтобы проверить, доступны ли входные данные для чтения или нет. Если он доступен, вы можете использовать, например, fgets для безопасного чтения входных данных в некоторый буфер, как показано ниже:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
fd_set rfds;
struct timeval tv;
int retval, len;
char buff[255] = {0};
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1){
perror("select()");
exit(EXIT_FAILURE);
}
else if (retval){
/* FD_ISSET(0, &rfds) is true so input is available now. */
/* Read data from stdin using fgets. */
fgets(buff, sizeof(buff), stdin);
/* Remove trailing newline character from the input buffer if needed. */
len = strlen(buff) - 1;
if (buff[len] == '\n')
buff[len] = '\0';
printf("'%s' was read from stdin.\n", buff);
}
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}
Может быть, вы хотите посмотреть способ ввода с клавиатуры на "WINDOWS"? В Windows он не может получить результат от select() для STDIN. Вы должны использовать PeekConsoleInput(). И используйте дескриптор стандартного ввода, как показано ниже.
hStdin = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, ...
stdin может стать каналом ввода. если это так, вы не получите никакого ввода с клавиатуры.
PS Если вы не спрашиваете о Windows, извините очень.