如何使用 select() 从 C 语言中读取键盘输入

发布于 2024-11-16 03:37:07 字数 119 浏览 4 评论 0原文

我试图使用 select() 来读取键盘输入,但我陷入困境,我不知道如何从键盘读取并使用文件描述符来执行此操作。我被告知使用 STDIN 和 STDIN_FILENO 来解决这个问题,但我仍然很困惑。
我该怎么做呢?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我恋#小黄人 2024-11-23 03:37:07

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

这是一个简单的例子。它会阻塞,直到 stdin 至少有一个字符可供读取。但是当然,除非您将终端更改为某种未处理的模式,否则它会阻塞,直到您按 Enter 键,此时键入的任何字符都会刷新到文件缓冲区(从某些终端缓冲区)。

#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;
}

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;
}
来世叙缘 2024-11-23 03:37:07

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

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);
}
怪我闹别瞎闹 2024-11-23 03:37:07

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

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

stdin 可能成为管道输入。如果是这样,您将无法获得任何键盘输入。

PS 如果你不问 Windows 的问题,非常抱歉。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文