【问题标题】: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);