在類 Unix 作業系統中,C++ 程式使用 stdio 或 iostream 程式庫接收鍵盤輸入時,需等待Enter鍵按下後才能接收到輸入内容。如何能在無需等待回車即可擷取來自鍵盤的輸入?
通過 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 謝謝!