歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下的getch()函數的改進版

Linux下的getch()函數的改進版

日期:2017/3/1 10:38:10   编辑:Linux編程
getch()函數源碼如下:

[cpp]
  1. #include <termios.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. int getch(void) {
  5. struct termios tm, tm_old;
  6. int fd = STDIN_FILENO, c;
  7. if(tcgetattr(fd, &tm) < 0)
  8. return -1;
  9. tm_old = tm;
  10. cfmakeraw(&tm);
  11. if(tcsetattr(fd, TCSANOW, &tm) < 0)
  12. return -1;
  13. c = fgetc(stdin);
  14. if(tcsetattr(fd, TCSANOW, &tm_old) < 0)
  15. return -1;
  16. return c;
  17. }

經測試,在Linux下無法正常使用方向鍵,其余鍵能正常識別,為了解決這問題,我利用了模擬實現的kbhit函數檢測是否有多個鍵值,有的話,累加鍵值,具體如下:

[cpp]
  1. int set_raw(int t)
  2. {
  3. static struct termio tty ;
  4. struct termio tmp ;
  5. if (t) {
  6. ioctl(0,TCGETA,&tty) ;
  7. tmp = tty ;
  8. tmp.c_lflag &= ~(ICANON|ECHOPRT);
  9. tmp.c_cc[VMIN] = 1 ;
  10. tmp.c_cc[VTIME] = 0 ;
  11. ioctl(0,TCSETA,&tmp) ;
  12. }
  13. else {
  14. tty.c_lflag &= ~(ICANON|ECHO);
  15. ioctl(0,TCSETA,&tty);
  16. }
  17. return 0;
  18. }
  19. int kbhit(void)
  20. {
  21. struct termios oldt, newt;
  22. int ch;
  23. int oldf;
  24. set_raw(3);
  25. tcgetattr(STDIN_FILENO, &oldt);
  26. newt = oldt;
  27. newt.c_lflag &= ~(ICANON | ECHO);
  28. tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  29. oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  30. fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
  31. ch = getchar();
  32. tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  33. fcntl(STDIN_FILENO, F_SETFL, oldf);
  34. if(ch != EOF)
  35. {
  36. ungetc(ch, stdin);
  37. return 1;
  38. }
  39. set_raw(0);
  40. return 0;
  41. }
  42. static int input;
  43. int getch(void)
  44. {
  45. struct termios tm, tm_old;
  46. int fd = STDIN_FILENO,c;
  47. input = 0;
  48. if(tcgetattr(fd, &tm) < 0)
  49. return -1;
  50. tm_old = tm;
  51. tm.c_lflag &= ~(ICANON|ECHO|ISIG);
  52. if(tcsetattr(fd, TCSANOW, &tm) < 0)
  53. return -1;
  54. int k;
  55. input = fgetc(stdin);
  56. k = input;
  57. if(kbhit()){ /* 如果還有下一個鍵值 */
  58. input += getch();
  59. }
  60. if(tcsetattr(fd,TCSANOW,&tm_old)<0) return -1;
  61. c = input;
  62. if(c == 3) exit(1); /*如果是Ctrl+C組合鍵,就強制終止程序*/
  63. return c;
  64. }

本函數的代碼僅在諾亞舟NP1500學習機裡測試通過,並不保證在其它平台上也能正常執行。

Copyright © Linux教程網 All Rights Reserved