類別 (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 。 |