getch()函數源碼如下:
[cpp]
- #include <termios.h>
- #include <unistd.h>
- #include <stdio.h>
- int getch(void) {
- struct termios tm, tm_old;
- int fd = STDIN_FILENO, c;
- if(tcgetattr(fd, &tm) < 0)
- return -1;
- tm_old = tm;
- cfmakeraw(&tm);
- if(tcsetattr(fd, TCSANOW, &tm) < 0)
- return -1;
- c = fgetc(stdin);
- if(tcsetattr(fd, TCSANOW, &tm_old) < 0)
- return -1;
- return c;
- }
經測試,在Linux下無法正常使用方向鍵,其余鍵能正常識別,為了解決這問題,我利用了模擬實現的kbhit函數檢測是否有多個鍵值,有的話,累加鍵值,具體如下:
[cpp]
- int set_raw(int t)
- {
- static struct termio tty ;
- struct termio tmp ;
-
- if (t) {
- ioctl(0,TCGETA,&tty) ;
- tmp = tty ;
- tmp.c_lflag &= ~(ICANON|ECHOPRT);
- tmp.c_cc[VMIN] = 1 ;
- tmp.c_cc[VTIME] = 0 ;
- ioctl(0,TCSETA,&tmp) ;
- }
- else {
- tty.c_lflag &= ~(ICANON|ECHO);
- ioctl(0,TCSETA,&tty);
- }
- return 0;
- }
- int kbhit(void)
- {
- struct termios oldt, newt;
- int ch;
- int oldf;
- set_raw(3);
- tcgetattr(STDIN_FILENO, &oldt);
- newt = oldt;
- newt.c_lflag &= ~(ICANON | ECHO);
- tcsetattr(STDIN_FILENO, TCSANOW, &newt);
- oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
- fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
- ch = getchar();
- tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
- fcntl(STDIN_FILENO, F_SETFL, oldf);
- if(ch != EOF)
- {
- ungetc(ch, stdin);
- return 1;
- }
- set_raw(0);
- return 0;
- }
-
-
-
- static int input;
-
-
- int getch(void)
- {
- struct termios tm, tm_old;
- int fd = STDIN_FILENO,c;
- input = 0;
- if(tcgetattr(fd, &tm) < 0)
- return -1;
-
- tm_old = tm;
-
- tm.c_lflag &= ~(ICANON|ECHO|ISIG);
- if(tcsetattr(fd, TCSANOW, &tm) < 0)
- return -1;
-
- int k;
- input = fgetc(stdin);
- k = input;
- if(kbhit()){ /* 如果還有下一個鍵值 */
- input += getch();
- }
- if(tcsetattr(fd,TCSANOW,&tm_old)<0) return -1;
- c = input;
- if(c == 3) exit(1); /*如果是Ctrl+C組合鍵,就強制終止程序*/
- return c;
- }
本函數的代碼僅在諾亞舟NP1500學習機裡測試通過,並不保證在其它平台上也能正常執行。