如何在C语言中处理Linux控制台中按下的键?

mat*_*boy 14 c linux keyboard

我正在使用Linux控制台,我想做一个输出随机字符的程序,直到按下ESC.我怎样才能制作这样的键盘处理程序?

jsc*_*ier 20

默认情况下,终端设备的线路规则通常在规范模式下工作.在此模式下,终端驱动程序不会向用户空间显示缓冲区,直到看到换行符(Enter按下键).

您可以通过使用tcsetattr()操作termios结构将终端设置为原始(非规范)模式.清除ECHOICANON标志分别禁用在键入字符时回显字符,并使读取请求直接从输入队列中得到满足.设定的值VTIME,并VMIN以中零c_cc阵列使读请求(fgetc())返回立即而不是块; 有效地轮询stdin.如果流中没有字符,fgetc()则将返回调用EOF.

#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <time.h>

int getkey() {
    int character;
    struct termios orig_term_attr;
    struct termios new_term_attr;

    /* set the terminal to raw mode */
    tcgetattr(fileno(stdin), &orig_term_attr);
    memcpy(&new_term_attr, &orig_term_attr, sizeof(struct termios));
    new_term_attr.c_lflag &= ~(ECHO|ICANON);
    new_term_attr.c_cc[VTIME] = 0;
    new_term_attr.c_cc[VMIN] = 0;
    tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);

    /* read a character from the stdin stream without blocking */
    /*   returns EOF (-1) if no character is available */
    character = fgetc(stdin);

    /* restore the original terminal attributes */
    tcsetattr(fileno(stdin), TCSANOW, &orig_term_attr);

    return character;
}

int main()
{
    int key;

    /* initialize the random number generator */
    srand(time(NULL));

    for (;;) {
        key = getkey();
        /* terminate loop on ESC (0x1B) or Ctrl-D (0x04) on STDIN */
        if (key == 0x1B || key == 0x04) {
            break;
        }
        else {
            /* print random ASCII character between 0x20 - 0x7F */
            key = (rand() % 0x7F);
            printf("%c", ((key < 0x20) ? (key + 0x20) : key));
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

注意:为简单起见,此代码省略了错误检查.


jim*_*ara 5

更改一键按下的 tty 设置:

int getch(void) {
      int c=0;

      struct termios org_opts, new_opts;
      int res=0;
          //-----  store old settings -----------
      res=tcgetattr(STDIN_FILENO, &org_opts);
      assert(res==0);
          //---- set new terminal parms --------
      memcpy(&new_opts, &org_opts, sizeof(new_opts));
      new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
      tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
      c=getchar();
          //------  restore old settings ---------
      res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);
      assert(res==0);
      return(c);
}
Run Code Online (Sandbox Code Playgroud)


And*_*ovs 4

也许来自 Curses 库的getch() ?另外,您需要使用 notimeout() 告诉 getch() 不要等待下一次按键。

  • 注意:ncurses 中的 getch() 需要初始化适当的 ncurses“屏幕”,否则它将无法工作。 (4认同)
  • 您还必须初始化该库 - 这是@ShinTakezou 所说的变体。 (2认同)