getch()函數依賴於頭文件 conio.h .會在windows平台下從控制台無回顯地取一個字符,並且返回讀取到的字符。
然而,我在實際用這個函數才發現getch()這個函數並不簡單。
getch函數從控制台讀取單個字符而不回顯,函數不能去讀取CTRL+C,當讀取一個功能鍵或方向鍵,函數必須調用兩次(這就說明可以用這個函數去監控功能鍵和方向鍵),第一次調用返回0或0xe0,第二次返回實際的鍵代碼
例如:
#include <stdio.h>
#include <conio.h>
int main()
{
while (true)
{
int tmp = _getch();
printf(" ……\n"); //測試每鍵入一次,打印幾次
}
return 0;
}
在這個簡單的小程序中,我測試了幾個鍵盤的按鍵。
- 在a~z的英文字母、數字鍵、以及Tab、space、ESC、Backspace、Enter等幾個常用鍵上,printf()只會打印一次,也就是說,getch()會立即返回真實的鍵碼值,並且被tmp變量接收。
- 在鍵盤上輸入上下左右的方向鍵,F1~F9、Delete等功能鍵時,printf()會打印兩次。
為了探究getch()的真相,我改寫了以上函數。
int main()
{
while (true)
{
int tmp = _getch();
int tmp2 = _getch();
printf(" tmp=%d\n tmp2=%d\n",tmp,tmp2);
}
return 0;
}
在鍵盤上依次輸入上下左右得到如下鍵值:
- 上 tmp=224 tmp2=72
- 下 tmp=224 tmp2=80
- 左 tmp=224 tmp2=75
- 右 tmp=224 tmp2=77
上下左右方向鍵,getch()第一次返回 224(0xe0),第二次返回真實鍵值
在鍵盤上依次輸入F1~F10、F11、F12、Delete得到如下鍵值:
- F1 tmp=0 tmp2=59
- F2 tmp=0 tmp2=60
- F3 tmp=0 tmp2=61
- F10 tmp=0 tmp2=68
F1~F10,getch()第一次返回 0 ,第二次返回該鍵的真實鍵值(59~68)
- F11 tmp=224 tmp2=133
- F12 tmp=224 tmp2=134
- Delete tmp=224 tmp2=83
那么問題就來了,getch()一會返回一個值,一會返回兩個值,究竟要怎樣寫才不會出錯呢?
我這里提供一種方法,僅供參考
#include <conio.h>
int main()
{
char tmp; //讀取鍵值,或過濾功能鍵的第一個返回值
char tmp2; //接受功能鍵
while (true)
{
tmp = _getch();
if (tmp == 0 || tmp == -32)//表示讀取的是功能鍵或者方向鍵,丟掉第一個返回值,讀取第二個返回值
{
switch (tmp2 = _getch()) //接収功能鍵返回值
{
case 72://上
printf("This is ↑\n");
break;
case 59://F1
printf("This is F1\n");
break;
default:
break;
}
}
else //普通按鍵,如字母、數字、space,Esc等按鍵
{
switch (tmp)
{
case 32://空格
printf("This is Space\n");
break;
case 27://Esc
printf("This is Esc\n");
break;
default:
break;
}
}
}
return 0;
}
注意1:在以上代碼中 tmp 為char類型,可接受的值為 -128~127之間,所以原本 0xe0的返回值(10進制為224) 會被轉換為 -32。
轉換原理為 超出char范圍的(即127以后的數字),把差值從 char類型的另一側極限值重新開始計算(即-128往后排)
例如:224——> 超出97(224-127)——> -128+97-1=-32
解決辦法:
- 可以把tmp定義 unsigned char類型
- 通過計算、或者測試,得到可用的鍵值。
注意2:用getch()函數時,編譯器可能會給出如下錯誤
嚴重性 代碼 說明 項目 文件 行 禁止顯示狀態
錯誤 C4996 'getch': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _getch. See online help for details.
解決辦法:把getch()換成編譯器要求的_getch()函數即可