歡迎光臨
每天分享高質量文章

ncurses 入門指南 | Linux 中國

怎樣使用 curses 來繪製終端屏幕?
— Jim Hall


本文導航
編譯自 | http://www.linuxjournal.com/content/getting-started-ncurses 
 作者 | Jim Hall
 譯者 | leemeans

怎樣使用 curses 來繪製終端屏幕?

雖然圖形界面非常酷,但是不是所有的程式都需要點擊式的界面。例如,令人尊敬的 Vi 編輯器在第一個 GUI 出現之前在純文本終端運行了很久。

Vi 編輯器是一個在“文本”樣式下繪製的面向屏幕screen-oriented程式的例子。它使用了一個叫 curses 的庫。這個庫提供了一系列的編程接口來操縱終端屏幕。curses 庫產生於 BSD UNIX,但是 Linux 系統通過 ncurses 庫提供這個功能。

[要瞭解 ncurses “過去曾引起的風暴”,參見 ncurses: Portable Screen-Handling for Linux[1], September 1, 1995, by Eric S. Raymond.]

使用 curses 創建程式實際上非常簡單。在這個文章中,我展示了一個利用 curses 來在終端屏幕上繪圖的示例程式。

謝爾賓斯基三角形

簡單展示一些 curses 函式的一個方法是生成謝爾賓斯基三角形Sierpinski’s Triangle。如果你對生成謝爾賓斯基三角形的這種方法不熟悉的話,這裡是一些產生謝爾賓斯基三角形的規則:

☉ 設置定義三角形的三個點。
☉ 隨機選擇任意的一個點 (x,y)

然後:

☉ 在三角形的頂點中隨機選擇一個點。
☉ 將新的 x,y 設置為先前的 x,y 和三角頂點的中間點。
☉ 重覆(上述步驟)。

所以我按照這些指令寫了這個程式,程式使用 curses 函式來向終端屏幕繪製謝爾賓斯基三角形:

  1. /* triangle.c */

  2. #include <curses.h>

  3. #include <stdlib.h>

  4. #include "getrandom_int.h"

  5. #define ITERMAX 10000

  6. int main(void)

  7. {

  8.  long iter;

  9.  int yi, xi;

  10.  int y[3], x[3];

  11.  int index;

  12.  int maxlines, maxcols;

  13.  /* initialize curses */

  14.  initscr();

  15.  cbreak();

  16.  noecho();

  17.  clear();

  18.  /* initialize triangle */

  19.  maxlines = LINES - 1;

  20.  maxcols = COLS - 1;

  21.  y[0] = 0;

  22.  x[0] = 0;

  23.  y[1] = maxlines;

  24.  x[1] = maxcols / 2;

  25.  y[2] = 0;

  26.  x[2] = maxcols;

  27.  mvaddch(y[0], x[0], '0');

  28.  mvaddch(y[1], x[1], '1');

  29.  mvaddch(y[2], x[2], '2');

  30.  /* initialize yi,xi with random values */

  31.  yi = getrandom_int() % maxlines;

  32.  xi = getrandom_int() % maxcols;

  33.  mvaddch(yi, xi, '.');

  34.  /* iterate the triangle */

  35.  for (iter = 0; iter < ITERMAX; iter++) {

  36.      index = getrandom_int() % 3;

  37.      yi = (yi + y[index]) / 2;

  38.      xi = (xi + x[index]) / 2;

  39.      mvaddch(yi, xi, '*');

  40.      refresh();

  41.  }

  42.  /* done */

  43.  mvaddstr(maxlines, 0, "Press any key to quit");

  44.  refresh();

  45.  getch();

  46.  endwin();

  47.  exit(0);

  48. }

讓我一邊解釋一邊瀏覽這個程式。首先,getrandom_int() 函式是我對 Linux 系統呼叫 getrandom() 的包裝器。它保證傳回一個正整數(int)值。(LCTT 譯註:getrandom() 系統呼叫按照位元組傳回隨機值到一個變數中,值是隨機的,不保證正負,使用 stdlib.h 的 random() 函式可以達到同樣的效果)另外,按照上面的規則,你應該能夠辨認出初始化和迭代謝爾賓斯基三角形的代碼。除此之外,我們來看看我用來在終端上繪製三角形的 curses 函式。

大多數 curses 程式以這四條指令開頭。 initscr() 函式獲取包括大小和特征在內的終端型別,並設置終端支持的 curses 環境。cbreak() 函式禁用行緩衝並設置 curses 每次只接受一個字符。noecho() 函式告訴 curses 不要把輸入回顯到屏幕上。而 clear() 函式清空了屏幕:

  1.  initscr();

  2.  cbreak();

  3.  noecho();

  4.  clear();

之後程式設置了三個定義三角的頂點。註意這裡使用的 LINES 和 COLS,它們是由 initscr() 來設置的。這些值告訴程式在終端的行數和列數。屏幕坐標從 0 開始,所以屏幕左上角是 0 行 0 列。屏幕右下角是 LINES - 1 行,COLS - 1 列。為了便於記憶,我的程式里把這些值分別設為了變數 maxlines 和 maxcols

在屏幕上繪製文字的兩個簡單方法是 addch() 和 addstr() 函式。也可以使用相關的 mvaddch() 和 mvaddstr() 函式可以將字符放到一個特定的屏幕位置。我的程式在很多地方都用到了這些函式。首先程式繪製三個定義三角的點並標記為 '0''1' 和 '2'

  1.  mvaddch(y[0], x[0], '0');

  2.  mvaddch(y[1], x[1], '1');

  3.  mvaddch(y[2], x[2], '2');

為了繪製任意的一個初始點,程式做了類似的一個呼叫:

  1.  mvaddch(yi, xi, '.');

還有為了在謝爾賓斯基三角形遞迴中繪製連續的點:

  1.      mvaddch(yi, xi, '*');

當程式完成之後,將會在屏幕左下角(在 maxlines 行,0 列)顯示一個幫助信息:

  1.  mvaddstr(maxlines, 0, "Press any key to quit");

註意 curses 在記憶體中維護了一個版本的屏幕顯示,並且只有在你要求的時候才會更新這個屏幕,這很重要。特別是當你想要向屏幕顯示大量的文字的時候,這樣程式會有更好的性能表現。這是因為 curses 只能更新在上次更新之後改變的這部分屏幕。想要讓 curses 更新終端屏幕,請使用 refresh() 函式。

在我的示例程式中,我選擇在“繪製”每個謝爾賓斯基三角形中的連續點時更新屏幕。通過這樣做,用戶可以觀察三角形中的每次迭代。(LCTT 譯註:由於 CPU 太快,迭代過程執行就太快了,所以其實很難直接看到迭代過程)

在退出之前,我使用 getch() 函式等待用戶按下一個鍵。然後我呼叫 endwin() 函式退出 curses 環境並傳回終端程式到一般控制。

  1.  getch();

  2.  endwin();

編譯和示例輸出

現在你已經有了你的第一個 curses 示例程式,是時候編譯運行它了。記住 Linux 操作系統通過 ncurses 庫來實現 curses 功能,所以你需要在編譯的時候通過 -lncurses來鏈接——例如:

  1. $ ls

  2. getrandom_int.c  getrandom_int.h  triangle.c

  3. $ gcc -Wall -lncurses -o triangle triangle.c getrandom_int.c

(LCTT 譯註:此處命令列有問題,-lncurses 選項在我的 Ubuntu 16.04 系統 + gcc 4.9.3 環境下,必須放在命令列最後,否則找不到庫檔案,鏈接時會出現未定義的取用。)

在標準的 80x24 終端運行這個 triangle 程式並沒什麼意思。在那樣的解析度下你不能看見謝爾賓斯基三角形的很多細節。如果你運行終端視窗並設置非常小的字體大小,你可以更加容易地看到謝爾賓斯基三角形的不規則性質。在我的系統上,輸出如圖 1。

圖 1. triangle 程式的輸出

雖然迭代具有隨機性,但是每次謝爾賓斯基三角形的運行看起來都會很一致。唯一的不同是最初繪製到屏幕的一些點的位置不同。在這個例子中,你可以看到三角形開始的一個小圓點,在點 1 附近。看起來程式接下來選擇了點 2,然後你可以看到在圓點和“2”之間的星號。並且看起來程式隨機選擇了點 2 作為下一個隨機數,因為你可以看到在第一個星號和“2”之間的星號。從這裡開始,就不能繼續分辨三角形是怎樣被畫出來的了,因為所有的連續點都屬於三角形區域。

開始學習 ncurses

這個程式是一個怎樣使用 curses 函式繪製字符到屏幕的簡單例子。按照你的程式的需要,你可以通過 curses 做得更多。在下一篇文章中,我將會展示怎樣使用 curses 讓用戶和屏幕交互。如果你對於學習 curses 有興趣,我建議你去讀位於 Linux 文件計劃Linux Documentation Project[2]的 Pradeep Padala 寫的 NCURSES Programming HOWTO[3]

關於作者

Jim Hall 是一個自由及開源軟體的倡議者,他最有名的工作是 FreeDOS 計劃,也同樣致力於開源軟體的可用性。Jim 是在明尼蘇達州的拉姆齊縣的首席信息官。


via: http://www.linuxjournal.com/content/getting-started-ncurses

作者:Jim Hall[5] 譯者:leemeans 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

LCTT 譯者

leemeans ? ?
共計翻譯:3 篇
貢獻時間:10 天


推薦文章

< 左右滑動查看相關文章 >

點擊圖片、輸入文章 ID 或識別二維碼直達

赞(0)

分享創造快樂

© 2021 知識星球   网站地图