在 Linux 上實作 C++ 在 VC++ 的 getch()


這是前兩天,和網友討論的東西。主要命題就是:「要怎麼用 C++ 寫一個 console 的程式,可以取得單一按鍵的輸入?」也就是類似「按任一鍵繼續」的功能了~

Heresy 本來以為很簡單,後來才發現非常地麻煩… 首先,一般習慣在用的 scanf() 或是 cin,都必須要按下 Enter 後,才會開始處理;找了好一段時間的資料,也試了好久,才大概確定,他們應該都沒有辦法符合這個要求。

而在 Windows 上用 Visual C++ 的話,只要先 include conio.h 後,就可以直接使用 getch() 這個函式了~完整程式,也就只要下面這樣就夠了

#include <stdio.h>
#include <conio.h>
int main(void)
{
  printf("Press any key to continue...");
  int a = getch();
  printf( "%dn", a );
  return 0;
}

但是到了 Linux 一般用的 g++ 呢…第一個問題就是沒有 conio.h 這個檔案了…

不過,在 Google 找一下,就可以發現,可以發現在 curses.h 這個標頭檔裡,也有定義 getch() 這個函式(參考:The Single UNIX ® Specification,編譯時需加入 -lcurses 的參數)!

可是,問題還是沒解決。因為 curses.h 裡的 getch() 不能像 Windows 版的一樣,直接用… = =

Heresy 後來才知道,原來他要使用 curses.h 裡的功能,必須要先透過 initscr() 這個函式,來初始化一個 screen(window),才能針對這個 window 做操作。而參考的寫法,大概如下:

#include <curses.h>
int main(void)
{
  WINDOW *w = initscr();
  // cbreak();
  // nodelay(w,false);
  int c = getch();
  endwin();
  printw("%dn",c);
  return 0;
}

其中,cbreak()nodelay() 這兩個函式是被 mrak 掉了。因為像在找到《c++ g++ wait for key press???》這篇的範例,就是有加上這個 cbreak() 函式;而有加上 nodelay() 的版本,則是 Heresy 同事給的範例。但是 Heresy  自己在測試時,好像沒加也都沒差就是了…

而另外,Heresy 有位網友也提供了一種透過 POSIX 來實作 getch() 的方法(請見《implement getch() on POSIX.1 OS》);其程式如下:

#include <stdio.h>
// POSIX headers
#include <termios.h>  // for tcxxxattr, ECHO, etc ..
#include <unistd.h>    // for STDIN_FILENO
 
int getch(void);
 
int main(void)
{
    printf("Press any key to continue...");
    getch();
 
    return 0;
}
 
int getch (void)
{
    int ch;
    struct termios oldt, newt;
 
    tcgetattr(STDIN_FILENO, &oldt);
    memcpy(&newt, &oldt, sizeof(newt));
    newt.c_lflag &= ~( ECHO | ICANON | ECHOE | ECHOK |
                       ECHONL | ECHOPRT | ECHOKE | ICRNL);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
 
    return ch;
}

整個弄完後的感想,只有一個:要用 C++ 寫一個跨平台的程式,可以抓到單一按鍵的輸入還真麻煩啊…

對「在 Linux 上實作 C++ 在 VC++ 的 getch()」的想法

  1. 你好,我剛好也在找這個問題,請問你的文章可以讓我貼在我的網誌上面嗎?我會做一個連結註明出處,不知道是否可以,謝謝!

  2. 又打錯字了 orz
     
    不過 Linux 上用 g++ 寫程式還好啦~
    標準語法都還是通用的。除非要寫 UI,不然差異不會太大。

  3. 其實我也正在進軍LINUX上的C++程式耶,不過目前進度很慢,沒有領隊..XD開路吧Heresy!可以取得單一安鍵的輸入?…"安"鍵

發表留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料