【问题标题】:Receive the keys as soon as they are pressed on Unix console在 Unix 控制台上按下后立即接收键
【发布时间】:2018-05-17 15:01:04
【问题描述】:

我正在 Linux 上开发一个 C++ 程序以将其用作 ROS 节点(有关 ROS 的更多信息)。

Unix 控制台会缓冲整行文本,直到用户按下 Enter 键,但我需要在用户按下键后立即接收击键。

我该怎么做?

我对编写可移植代码不感兴趣。这只是我大学课程的一项活动。

顺便说一句,我运行的是 Ubuntu 16.04.4 LTS,shell 是 bash。

【问题讨论】:

  • 如果您不想像 termios 示例那样手动修改终端设置,我会查看您系统上可能已经存在的 curses 库,它提供了getch()

标签: c++ linux terminal ros


【解决方案1】:

看来你需要一种“无缓冲”getchar

你应该试试termios,例如:

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

int main()
{
    struct termios old_tio, new_tio;
    unsigned char c;

    /* get the terminal settings for stdin */
    tcgetattr(STDIN_FILENO,&old_tio);

    /* we want to keep the old setting to restore them a the end */
    new_tio=old_tio;

    /* disable canonical mode (buffered i/o) and local echo */
    new_tio.c_lflag &=(~ICANON & ~ECHO);

    /* set the new settings immediately */
    tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);

    do {
         c=getchar();
         printf("%d ",c);
    } while(c!='q');

    /* restore the former settings */
    tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);

    return 0;
}

【讨论】:

    【解决方案2】:

    这是终端的一项功能,因此要关闭该功能,您需要重新配置该终端。在 C++ 中是这样的:

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

    在任何初始化函数中:

    struct termios original_termios, unbuffered_termios;
    
    tcgetattr(STDIN_FILENO, &original_termios);
    unbuffered_termios = original_termios;
    unbuffered_termios.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &unbuffered_termios);
    

    之后,您可以使用任何标准方法从文件 stdin 中读取单个字节(例如 fread()getch())。请记住,某些键在按下时会发送超过一个字节(例如光标键)。

    处理完你的东西后,你应该恢复原来的设置,否则即使你的程序终止了,终端也可能表现得很奇怪:

    tcsetattr(STDIN_FILENO, TCSANOW, &original_termios);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-10
      • 1970-01-01
      • 2021-12-16
      • 2013-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多