【问题标题】:How to use select() to read input from keyboard in C如何使用 select() 从 C 中的键盘读取输入
【发布时间】:2011-09-19 01:56:31
【问题描述】:

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

【问题讨论】:

  • 如果您不熟悉一般的 POSIX 编程,这是一件相当棘手的事情。一方面,您必须设置终端模式,以便设备不会缓冲接收到的字符。
  • 不需要使用 select( ),当然,除非它是家庭作业的一部分。您可以只读取(STDIN ...)或读取(STDIN_FILENO ...)。
  • 如果您需要完全的终端控制(按键等),那么使用 ncurses 之类的终端库可能会好多 (也有 Windows 端口)。
  • Pete Wilson:如果消息在用户按下键之前到达套接字,fread(stdin ...) 不会像 select 那样快速返回。在 Linux 中,我使用了 select。在 Windows 中更难。
  • 你能澄清一下为什么你需要去选择来阅读键盘输入吗?通常,当您需要从一系列描述符或输入中读取数据时,应使用 select 调用,因为它允许程序监视多个文件描述符,等待一个或多个文件描述符为某种 I/O 操作“准备好” (例如,可以输入)。

标签: c keyboard stdin textinput select-function


【解决方案1】:

你的问题听起来有点混乱。 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;
}

【讨论】:

  • 非常感谢,这真的澄清了我的问题。
【解决方案2】:

正如已经说过的,通过使用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);
}

【讨论】:

    【解决方案3】:

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

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

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

    附:如果您不询问 Windows,非常抱歉。

    【讨论】:

    • 我什至没有想到 Windows。很好的保存:覆盖所有角度。
    猜你喜欢
    • 1970-01-01
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    相关资源
    最近更新 更多