【问题标题】:Implementing a KeyPress Event in C在 C 中实现 KeyPress 事件
【发布时间】:2014-01-13 12:21:21
【问题描述】:

我有一个像下面这样的无限循环,在这个循环中,我想不断地检查键盘以查看是否按下了转义键 (ESC)。如果它被按下,那么循环应该被打破。我如何在 C 中做到这一点? (我正在使用 gcc,并且也可以访问 pthread,以防必须通过线程完成)

 while(1){
        //do something
        //check for the ESC key
 }

【问题讨论】:

  • 试试while((ch = getchar()) != ESC_ASCCI_CODE)
  • 在您不断做其他事情的同时不断检查键盘?
  • @ᴍarounᴍaroun 谢谢,但是使用这种方法,每次循环停止以获取字符。我不想停下来检查键盘。
  • @SzG 我实际上需要一个按键事件。看来我需要一个中断处理程序。
  • 这是什么系统? Linux?请更新标签。

标签: c multithreading keypress


【解决方案1】:

这在很大程度上取决于系统。在 Unix/Linux 系统中,默认的终端处理程序会收集行,并且仅在有完整行可用时才通知程序(在 Enter 被击中之后)。如果您想要立即击键,则需要将终端进入非规范模式:

#include <termios.h>

struct termios info;
tcgetattr(0, &info);          /* get current terminal attirbutes; 0 is the file descriptor for stdin */
info.c_lflag &= ~ICANON;      /* disable canonical mode */
info.c_cc[VMIN] = 1;          /* wait until at least one keystroke available */
info.c_cc[VTIME] = 0;         /* no timeout */
tcsetattr(0, TCSANOW, &info); /* set immediately */

完成此操作后,您可以使用从标准输入读取的任何调用,它们将返回键而无需等待行尾。您还可以设置c_cc[VMIN] = 0 使其在您从标准输入读取时根本不等待击键。

但是,如果您正在使用与 stdio FILE 相关的调用(getchar 等)来读取 stdin,则设置 VMIN = 0 将使其认为您在没有可用键时已达到 EOF,因此您必须调用clearerr 之后碰巧尝试读取更多字符。您可以使用如下循环:

int ch;
while((ch = getchar()) != 27 /* ascii ESC */) {
    if (ch < 0) {
        if (ferror(stdin)) { /* there was an error... */ }
        clearerr(stdin);
        /* do other stuff */
    } else {
        /* some key OTHER than ESC was hit, do something about it? */
    }
}

完成后,您可能需要确保将终端设置回规范模式,以免其他程序(例如您的 shell)混淆:

tcgetattr(0, &info);
info.c_lflag |= ICANON;
tcsetattr(0, TCSANOW, &info);

您还可以使用 tcsetattr 执行其他操作——有关详细信息,请参阅手册页。设置一个替代的 EOL 字符可能足以满足您的目的。

【讨论】:

    【解决方案2】:

    如果你正在做的主要工作可以放在这个主循环中,你可以在非阻塞模式下使用 STDIN。您仍然对正常进行行缓冲的终端有问题。您也应该将终端设置为原始模式。

    使用 Ctrl-C(中断)怎么样?

    非阻塞意味着read() 系统调用总是立即返回,即使文件中没有新字节。在 Linux/Unix 上,您可以通过这种方式使 STDIN 成为非阻塞:

    #include <unistd.h>
    #include <fcntl.h>
    fcntl(0, F_SETFL, O_NONBLOCK); /* 0 is the stdin file decriptor */
    

    【讨论】:

    • 谢谢!事实上,我想使用 Ctrl-C 之类的东西,但使用 ESC 之类的另一个键。您能详细解释一下非阻塞模式下的 STDIN 吗?
    【解决方案3】:

    这就是你想要的:

    #include <stdio.h>
    #include <conio.h>
    
    void main() {
    
       int c;
    
       while((c = getch()) != EOF )
          if(c == 27)   break;
    /* 27 is the ASCII code for Esc */
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      相关资源
      最近更新 更多