C个不阻塞键盘输入 [英] C non-blocking keyboard input

查看:598
本文介绍了C个不阻塞键盘输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试着写在C(在Linux上)的程序循环,直到用户presses的关键,但不应该要求一个关键preSS继续每个循环。

I'm trying to write a program in C (on linux) that loops until the user presses a key, but shouldn't require a keypress to continue each loop.

有没有一种简单的方法来做到这一点?我想我可能与选择()做到这一点,但似乎想了很多的工作。

Is there a simple way to do this? I figure I could possibly do it with select() but that seems like a lot of work.

另外,有没有办法赶上控制-C键preSS程序之前做清理关闭,而不是非阻塞IO?

Alternatively, is there a way to catch a control-c keypress to do cleanup before the program closes instead of non-blocking io?

推荐答案

如前所述,您可以使用的sigaction 捕获CTRL-C或选择来捕获任何标准输入。

As already stated, you can use sigaction to trap ctrl-c, or select to trap any standard input.

不过请注意,与后一种方法,你还需要设置TTY所以,它在人物-AT-A-时间,而不是线在-A-时间模式。后者是默认的 - 如果你在​​一个文本行中键入它不会发送到正在运行的程序的标准输入,直到你preSS输入

Note however that with the latter method you also need to set the TTY so that it's in character-at-a-time rather than line-at-a-time mode. The latter is the default - if you type in a line of text it doesn't get sent to the running program's stdin until you press enter.

您就需要使用 tcsetattr()功能关闭ICANON模式,大概也禁止回声了。从内存中,您还可以将终端设置回ICANON模式时,程序退出!

You'd need to use the tcsetattr() function to turn off ICANON mode, and probably also disable ECHO too. From memory, you also have to set the terminal back into ICANON mode when the program exits!

只是为了完整性,这里的一些code我刚刚敲了(注意:没有错误检查),它建立在Unix TTY并模拟了DOS < CONIO.H> 功能的kbhit()残培()

Just for completeness, here's some code I've just knocked up (nb: no error checking!) which sets up a Unix TTY and emulates the DOS <conio.h> functions kbhit() and getch():

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <termios.h>

struct termios orig_termios;

void reset_terminal_mode()
{
    tcsetattr(0, TCSANOW, &orig_termios);
}

void set_conio_terminal_mode()
{
    struct termios new_termios;

    /* take two copies - one for now, one for later */
    tcgetattr(0, &orig_termios);
    memcpy(&new_termios, &orig_termios, sizeof(new_termios));

    /* register cleanup handler, and set the new terminal mode */
    atexit(reset_terminal_mode);
    cfmakeraw(&new_termios);
    tcsetattr(0, TCSANOW, &new_termios);
}

int kbhit()
{
    struct timeval tv = { 0L, 0L };
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(0, &fds);
    return select(1, &fds, NULL, NULL, &tv);
}

int getch()
{
    int r;
    unsigned char c;
    if ((r = read(0, &c, sizeof(c))) < 0) {
        return r;
    } else {
        return c;
    }
}

int main(int argc, char *argv[])
{
    set_conio_terminal_mode();

    while (!kbhit()) {
        /* do some work */
    }
    (void)getch(); /* consume the character */
}

这篇关于C个不阻塞键盘输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆