在 Unix 控制台上按下后立即接收密钥

Receive the keys as soon as they are pressed on Unix console

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

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

我该怎么做?

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

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

看来你需要一种"unbuffered"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;
}

这是终端的一项功能,因此要关闭该功能,您需要重新配置该终端。在 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);