I am trying to use select() to read keyboard input and I got stuck in that I do not know how to read from keyboard and use a file descriptor to do so. I've been told to use STDIN and STDIN_FILENO to approach this problem but I am still confused.
How can I do it?
问题:
回答1:
Youre question sounds a little confused. select()
is used to block until input is available. But you do the actual reading with normal file-reading functions (like read
,fread
,fgetc
, etc.).
Here's a quick example. It blocks until stdin has at least one character available for reading. But of course unless you change the terminal to some uncooked mode, it blocks until you press enter, when any characters typed are flushed into the file buffer (from some terminal buffer).
#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;
}
回答2:
As it was already said, by using select you can just monitor e.g. stdin to check if the input data is already available for reading or not. If it is available, you can then use e.g. fgets to safely read input data to some buffer, like shown below:
#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);
}
回答3:
Perhaps, you want the way to peek keyboard input on "WINDOWS"? On windows, it can't get result from select() for STDIN. You should use PeekConsoleInput(). And use handle of stdin like following.
hStdin = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, ...
stdin may become pipe input. if so, you don't get any keyboard input.
P.S. If you don't ask about Windows, Sorry much.