天天看点

如何在类 Unix 环境下无需等待回车即可获取来自键盘的输入?

在类 Unix 操作系统中,C++ 程序使用 stdio 或 iostream 程序库接收键盘输入时,需等待回车键按下后才能接收到输入内容。如何能在无需等待回车即可获取来自键盘的输入?

通过 termios 程序库中与终端关联的 termios 结构和 tcgetattr、tcsetattr 函数,改变终端编辑模式为非规范输入且不回显,即可实现“无需等待回车即可获取来自键盘的输入”的功能。

以下代码片段展示了此实现方案,(how_to_get_input_without_enter.cpp)

首先需要包含 termios.h 程序库(#1),该文件定义了与终端关联的 termios 结构和 tcgetattr、tcsetattr 函数。使用 tcgetattr 函数获取当前终端的属性,并保存在 termios 结构的变量中(#2)。为了能将终端属性恢复成原有值,先用原有终端属性复制出一份临时属性(#3)。改变终端编辑模式的关键,在于 termios.c_lflag 字段。将临时属性的 c_lflag 字段改变为非规范输入且不回显(#4),并设置终端属性为新值。应用结束后,将终端属性恢复成原有值(#5)。

笔者分别在 macOS Mojave(版本 10.14.6)和 Raspbian Stretch(版本 9.4)两个操作系统的原生终端内,用 87 键键盘输入 ASCII 字符集进行了验证。

编译代码成功后运行可执行文件。对于十进制 ASCII 码为 32 ~ 127 的可打印字符可直接按键输入,而对于 ASCII 码为 0 ~ 31 的控制字符按如下组合键输入,

十进制

字符

macOS Mojave 组合键

Raspbian Stretch 组合键

^@

Ctrl-@

1

^A

Ctrl-A

2

^B

Ctrl-B

3

^C

Ctrl-V Ctrl-C

(未验证)

4

^D

Ctrl-D

5

^E

Ctrl-E

6

^F

Ctrl-F

7

^G

Ctrl-G

8

^H

Ctrl-H

9

Tab, ^I

Tab, Ctrl-I

10

^J

Ctrl-J

11

^K

Ctrl-K

12

^L

Ctrl-L

13

^M

Ctrl-V Ctrl-M

14

^N

Ctrl-N

15

^O

Ctrl-V Ctrl-O

Ctrl-O

16

^P

Ctrl-P

17

^Q

Ctrl-V Ctrl-Q

18

^R

Ctrl-R

19

^S

Ctrl-V Ctrl-S

20

^T

Ctrl-T

21

^U

Ctrl-U

22

^V

Ctrl-V Ctrl-V

Ctrl-V

23

^W

Ctrl-W

24

^X

Ctrl-X

25

^Y

Ctrl-V Ctrl-Y

Ctrl-Y

26

^Z

Ctrl-V Ctrl-Z

27

ESC, ^[

Ctrl-[

ESC, Ctrl-[

28

^\

Ctrl-V Ctrl-\

29

^]

Ctrl-]

30

^^

Ctrl-^

31

^-

Ctrl--

在 Raspbian Stretch 上的测试中存在”(未验证)“的 ASCII 码,是因为该示例代码无法通过键盘输入对应的控制符。

以下是运行过程中的部分输出,

完整示例代码请参考 [github] cnblogs/15691156 。

写作过程中,笔者参考了 Linux下C++/C终端获取键盘事件/termios结构详细解释 和 LINUX 使用tcgetattr与tcsetattr函数控制终端。致 Liuqz2009 和 凡人只做一事 两位作者。

受限于作者的水平,读者如发现有任何错误或有疑问之处,请追加评论或发邮件联系 [email protected]。作者将在收到意见后的第一时间里予以回复。 本文来自博客园,作者:green-cnblogs,转载请注明原文链接:https://www.cnblogs.com/green-cnblogs/p/15691156.html 谢谢!

继续阅读