10

我正在尝试使用 select() 来读取键盘输入,但我陷入了我不知道如何从键盘读取并使用文件描述符来做到这一点的困境中。我被告知使用 STDIN 和 STDIN_FILENO 来解决这个问题,但我仍然感到困惑。
我该怎么做?

4

3 回答 3

6

你的问题听起来有点困惑。select()用于阻塞直到输入可用。但是您使用普通文件读取函数(如readfreadfgetc等)进行实际读取。

这是一个简单的例子。它会一直阻塞,直到 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;
}
于 2011-06-21T02:36:40.380 回答
6

正如已经说过的,通过使用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);
}
于 2013-09-02T13:29:45.423 回答
1

也许,您想要在“WINDOWS”上查看键盘输入的方法?在 Windows 上,它无法从 STDIN 的 select() 中获取结果。您应该使用 PeekConsoleInput()。并使用标准输入的句柄,如下所示。

hStdin = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE, ...

标准输入可能成为管道输入。如果是这样,你不会得到任何键盘输入。

PS如果你不问Windows,很抱歉。

于 2011-06-21T03:14:23.417 回答