无ncurses的非阻塞用户输入循环。
标题听起来有点尴尬,让我简要解释一下这是关于什么的。
在我的程序中,我想等待用户输入,但同时,我希望我的其他操作继续处理。我将其定义为非阻塞用户输入。我希望我的程序在循环中等待用户输入,如果接收到用户输入处理它并继续等待下一个用户输入,否则继续处理其他循环操作。
通常,人们会考虑使用ncurses库。通过使用ncurses,可以使用timeout(0)和getch()轻松执行非阻塞用户输入。引用ncurses矩阵作为参考。
如果我不想使用ncurses怎么办?有其他选择吗?有时我只是想在一个大程序中添加一个需要非阻塞的函数,我不想使用ncurses,因为它使我的打印行行为不同,或者其他原因。
多亏了##[email protected]上的程序员,我找到了一种方法。它可能看起来很凌乱,但它的工作方式是我想要的。我使用termios的函数并选择,让我们一个一个的来看函数。
01 02 03 04 05 06 07 08 09 10 11 |
|
此函数在没有超时0、tv的情况下对标准输入(stdin)执行非阻塞检查。tv_sec和电视。tv_usec都设置为零。select通常用于需要处理多个I/O的情况,或者同时进行检查。但是在本例中,我只对标准输入感兴趣,因此只有一个FD_SET(STDIN_FILENO, &fds)是触发器。有关选择参数的详细信息,请参阅手册。似乎我们只对输入感兴趣,所以我们将fd set放在第二个参数select()处,第3个参数用于输出,第4个参数用于异常。
重要部分,选择if user input is trigger后,FD_ISSET将返回非零值,否则返回0。现在我们可以这样用
1 2 3 4 5 |
|
由于终端的规范模式,您需要按enter来确认用户输入。规范模式意味着它总是等待enter来确认用户输入。如果这不是你的情况,bellow是另一个功能来迎合这一点。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
函数名可能有误导作用,函数实际上做的是关闭stdin的规范模式。首先,获取term的状态。接下来,通过将0设置为位,关闭正则表达式。ttystate的行。c_cc[VMIN]是设置要接受的用户输入的最小数量。如果将其设置为2,select将等待,直到给出2个字符,然后它将捕获作为输入。最后设置术语状态。这个函数实际上允许您打开和关闭规范模式。
好的,让我们看看它是如何工作的
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
按“q”键会导致程序退出,否则你会看到“0”的打印在屏幕上。观察到我在循环中使用的是usleep(1),在不使用usleep的情况下,程序的响应性更强,但是它使用了高CPU资源。另一方面,使用usleep(1)会减少CPU资源,也会降低程序的响应性。根据你的需要,你可以选择是否把它放进去。
我已经比较了这个应用程序和一个简单的ncurses程序,这个程序似乎使用较少的内存。无法测量CPU资源,因为ps和top都显示0.0%。
Curses sample shows as bellow:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Download the source code:
Non-blocking kbhit sample source code.(失效)