
類別 (class) 為 C++ 開發軟體 (software) 的要角,因為類別用來設計物件,軟體的實際運作則是藉由物件與物件的互動。我們接下來進入實際開發軟體的階段,最後會發展出一個 GUI 軟體
我們打算發展的一個替英文句子編密碼的軟體,主要功能是做小寫字母的替換,例如 "There is no spoon." 可能變成以下任一個
Tcnan hf gl fqllg.
Tczmz dn ij nkjji.
Tgfsf pb ir barri.
Tdcpc my fo yxoof.
首先,我們要發展 Encrypt 類別,主要功能是建立一個英文小寫字母的對換表格,藉由這個表格,我們可以將英文句子中的小寫英文字母進行對換,最終開發圖形使用者介面 (graphical user interface) 的 EncryptWindow 類別。
GUI 的外觀如下圖

我們的 GUI 設計會採用第三方程式庫 (third party library) Qt ,然後利用 Qt Creator 的 IDE 寫程式,並利用 Qt Creator 附的 Designer 設計 GUI , Qt 為跨平台的程式庫,同樣 Qt Creator 也是跨平台的整合開發環境,因此在各平台的使用都大致相同。
有兩個可供輸入的文字欄位 (text field) ,其中一個我們作為輸出的顯示訊息之用,另有三個標籤 (label) ,顯示文字的提示訊息,七個按鈕 (button) ,提供「新建」、「開啟」、「儲存」 Encrypt 物件,與「編碼」、「解碼」所輸入的英文句子,「清除」所有輸入欄位,以及「拷貝」輸出結果等的功能。
現在我們先來看看所有功能的核心,也就是 Encrypt 類別,我們的目的是,建立一個小寫英文字母的轉換表格,然後編碼、解碼都可直接依據這個表格。我們打算用下面的數學公式建立表格
m = y % n
r = m + diff
這裡的概念是利用字元的 ASCII 編碼順序,假設 x 為字元的原始編碼, ASCII 編碼中 'a' 為 97 ,然後將 x 乘上變數 (variable) a , 再加上變數 b ,假設兩者均是 0 到 9 的隨機整數,這樣便得到 y 的值。
然後將 y 除以 n 取得餘數 m , n 為所要轉換的字元數量,英文小寫字母共有 26 個,所以這裡 n 等於 26 ,因此 m 等於 0 到 25 之間的整數值。最後將 m 加上 diff , diff 也就是編碼系統的差值,由於 ASCII 中 'a' 為 97 ,所以這裡 diff 要以 97 代入。
因此,餘數 0 的字元會替換成 'a' ,餘數 1 的字元會被替換成 'b' ,餘數 2 的字元會被替換成 'c' ,餘下 23 個字元類推。這樣的計算需要進行 n 次,也就是 26 次,我們最後得到一組餘數與相對應字元的表格,這就是我們需要的表格了。
重複 n 次,我們需要一個迴圈 (loop) ,由於重複次數確定,因此 for 迴圈 (for loop) 很適合,那我們要用什麼東西來儲存這個表格呢?標準程式庫 (standard library) 中有許多的資料結構 (data structure) ,可以依資料特性有效率的處理資料,這裡,我們利用字串 (string) 就可以了。
字串為字元陣列 (character array) 的物件 (object) ,因此字串裡是由字元 (character) 當成元素 (element) ,也保有陣列 (array) 的特性,例如利用從 0 開始的索引值存取每個字元,這也完全符合我們計算餘數從 0 開始的需求。
因此,我們要替 Encrypt 宣告一個字串型態的的資料成員 (data member) , code_array 為二十六個英文小寫字母的密碼對照表格
private:
    // 密碼表字串
    string code_array;
        因此就需要存取函數 (accessor) 與修改函數 (mutator) ,也就是 get_code_array() 與 set_code_array() ,另外加上建構函數 (constructor) 跟編碼、解碼用的 ToEncode() 、 ToDecode() 兩個成員函數 (member function) ,我們先寫一個發展中的 encrypt01.h ,如下
// 從標準程式庫中引入 string
#include <string>
// 使用 std 中的 string 名稱
using std::string;
// 宣告 Encrypt 類別
class Encrypt {
public:
    // 宣告建構函數
    Encrypt();
    // 宣告 setter 與 getter 成員函數
    void set_code_array();
    string get_code_array();
    // 宣告編碼、解碼的成員函數
    string ToEncode(string);
    string ToDecode(string);
    
private:
    // 密碼表字串
    string code_array;
};
/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:encrypt01.h
   功能:Encrypt 類別的發展中版本
   作者:張凱慶 */
        注意這裡,原本我們的範例使用 using 的地方都是連帶 namespace
using namespace std;
  這裡改成指定的名稱
// 使用 std 中的 string 名稱
using std::string;
        兩者實際的差別不大,因為編譯器編譯時會將程式作最佳化,因此編譯完成的執行檔只會放進必要的東西,而我們改成指定名稱的寫法,主要的原因是讓我們自己清楚用到標準程式庫中的哪些東西,所以看範例開頭 using 的部份就一目瞭然了。
我們看看宣告在 public 的成員函數
public:
    // 宣告建構函數
    Encrypt();
    // 宣告 setter 與 getter 成員函數
    void set_code_array();
    string get_code_array();
    // 宣告編碼、解碼的成員函數
    string ToEncode(string);
    string ToDecode(string);
        標頭檔 (header file) 宣告 (declare) 成員函數時,參數列 (parameter list) 只需要宣告型態 (type) 即可,實作檔再補上實際的參數 (parameter) 名稱即可。
這裡我們看到的是未來發展 Encrypt 的規格,編碼由 ToEncode() 負責,解碼則是 ToDecode() ,我們在這裡先宣告函數原型,後續單元再陸續實作。
下面我們先來實作 set_code_array() ,把數學公式寫成程式碼,實際建立 code_array 囉!
相關教學影片
| 中英文術語對照 | |
|---|---|
| 類別 | class | 
| 軟體 | software | 
| 圖形使用者介面 | graphical user interface | 
| 第三方程式庫 | third party library | 
| 文字欄位 | text field | 
| 標籤 | label | 
| 按鈕 | button | 
| 變數 | variable | 
| 迴圈 | loop | 
| for 迴圈 | for loop | 
| 標準程式庫 | standard library | 
| 資料結構 | data structure | 
| 字串 | string | 
| 字元陣列 | character array | 
| 物件 | object | 
| 字元 | character | 
| 元素 | element | 
| 陣列 | array | 
| 資料成員 | data member | 
| 存取函數 | accessor | 
| 修改函數 | mutator | 
| 成員函數 | member function | 
| 建構函數 | constructor | 
| 標頭檔 | header file | 
| 宣告 | declare | 
| 參數列 | parameter list | 
| 型態 | type | 
| 參數 | parameter | 
| 重點整理 | 
|---|
| 1. Encrypt 類別的主類功能是轉換句子中的英文小寫字母,最後作為 GUI 軟體的核心部分。 | 
| 2. Encrypt 類別以數學公式建立英文字母的轉換表格,用字串當成員變數儲存表格。 | 
| 3. ASCII 中, 'a' 的整數值為 97 。 | 
| 4. 標準程式庫中有許多有用的資料結構,字串即是一例,字串是由字元所組成的物件,保有字元陣列的特性。 | 
| 5. 程式的發展通常是逐步來的,標頭檔則作為程式的規格。 | 
| 問題與討論 | 
|---|
| 1. 為什麼 Encrypt 類別是要當作 GUI 軟體的核心?不能讓 Encrypt 類別直接成為大展神威的 GUI 軟體嗎? | 
| 2. 除了數學公式外,有其他的方式可以建立轉換表格嗎? | 
| 3. 為什麼程式的發展要逐步來?不能一次到位嗎? | 
| 4. 陣列是什麼樣的資料結構?對於儲存資料有什麼方便性? | 
| 練習 | 
|---|
| 1. 陣列的宣告是型態後加上識別字與中括弧,例如宣告大小為 10 的整數陣列像是 int a[10]; ,這時 a 就是屬於整數陣列的變數,存取與設定陣列元素則用中括弧加索引值,例如 a[0] 取得或設定第一個元素, a[6] 取得或設定第 7 個元素。寫一個程式 exercise1401.cpp ,設定一個具有 10 元素的整數陣列,隨意設定 10 個元素的初值。 | 
| 2. 寫一個程式 exercise1402.cpp ,裡頭用迴圈建立一個儲存英文字母表的字元陣列。 | 
| 3. 猜數字遊戲是一種猜測四位不重複數字的小遊戲,依猜測答案給 A 及 B 的數量, A 為對的數字及位置, B 為對的數字錯的位置,寫一個程式 exercise1403.cpp ,自訂答案 answer 值,然後印出 answer 。 | 
