从控制台读取输入,无需无条件等待(非等待 scanf)

Posted

技术标签:

【中文标题】从控制台读取输入,无需无条件等待(非等待 scanf)【英文标题】:Read input from console without waiting unconditionally(Non waiting scanf) 【发布时间】:2020-01-26 08:11:05 【问题描述】:

我正在尝试编写代码以不断地从控制台读取输入并更新应用程序中的变量。但是如果我们使用 scanf 函数,每当该函数命中时,它都会期望用户通过控制台输入,并且只有在收到来自控制台的输入时才继续执行进一步的指令,否则它会无条件等待。

我的代码是这样的

    int x, y;
    while(1)
    
        scanf("%d", &x);
        y = x;
        ----
        ----
       //Remaining code for execution
    

我的期望是应用程序不应该等待来自控制台的输入。如果用户在控制台中输入了一些输入,它应该读取并使用该输入,否则即使没有输入,应用程序也应该执行剩余的指令或者它应该使用旧值。有没有其他方法可以在不使用 scanf 的情况下编写此类代码?谢谢!

【问题讨论】:

看看ncurses google搜索的第一个链接c-lang.thiyagaraaj.com/archive/c-blog/… @VolAnd : 所有获取输入函数都会无条件等待来自控制台的输入 ***.com/questions/15603082/… 【参考方案1】:

您可以使用 select()/epoll() 函数来获取输入,如果发生超时,它将继续进行。 由于 stdin 也是一个 FD,因此您可以注册 FD 以供 select 在给定的 FD 上工作。

参考:https://***.com/a/21198059/6686352

【讨论】:

【参考方案2】:

您可以使用 select() 和零(非 NULL)超时来检查数据是否可用,然后才调用 scanf。

示例(没有正确的错误处理):

#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>

int main()

    int x;
    fd_set fds;
    struct timeval tv =  .tv_sec = 0, .tv_usec = 0 ;

    while (1) 
        FD_ZERO(&fds);
        FD_SET(0, &fds);  // Watch stdin (fd 0)
        if (select(1, &fds, NULL, NULL, &tv)) 
            scanf("%d", &x);
            printf("Got %d from stdin", x);
        

        printf("Working..\n");
        sleep(1);
    

【讨论】:

知道如何获取选择库吗? 它是 POSIX 的一部分,因此它始终可以在兼容 POSIX 的系统上使用,例如 Linux。不知道你用的是什么平台。 Windows 似乎在winsock2.h 中有选择。 @Mattias:我认为 Windows select 仅适用于套接字,而不适用于终端等任意文件描述符。但我的 Windows 知识可能已经过时了。 @MattiasWallin:在 Windows 中,此代码执行但始终输入if 条件并在 scanf 处阻塞。 select.h 已替换为 winsock2.h @user3629249 是的,不仅是 -1。您可能应该使用 FD_ISSET(0, &fds) 来检查可用数据。并从 scanf 检查状态。【参考方案3】:

您可以使用fcntl 将标准输入设置为非阻塞。这使得 scanf 提前返回 EAGAIN,否则它会被阻止。

示例(没有正确的错误处理):

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main()

    int x;
    fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);

    while (1) 
        int ret = scanf("%d", &x);
        if (ret > 0)
            printf("Got %d from stdin", x);

        printf("Working..\n");
        sleep(1);
    

【讨论】:

以上是关于从控制台读取输入,无需无条件等待(非等待 scanf)的主要内容,如果未能解决你的问题,请参考以下文章

Linux下无需按下回车读取输入键值

从控制台读取数据

js 等待,满足条件才执行下去

boost asio 异步等待条件变量

无需等待输入即可输入?

如何在没有OverflowError的情况下等待键盘输入