C++ 入門指南 4.01

單元 15 - 實作 set_code_array()

-unit15-

set_code_array() 的工作就是建立密碼表,我們需要的密碼表就是一個攪亂順序的英文字母表

setCode()

012345678910111213141516171819202122232425
qzirajsbktcludmvenwfoxgpyh

先來溫習一下用來編碼的數學公式

y = a * x + b
m = y % n
r = m + diff

ab 預定是 09 之間的隨機整數,要取得隨機整數的話,標準程式庫 (standard library) 有程式可用,倒是現在先不用急著一次到位,我們先把 a 設定成 3b 設定成 5 測試看看好了,如此 set_code_array() 的實作如下

// 設定 code_array 的 setter 成員函數
void Encrypt::set_code_array() {
    // 設定 a 、 b 值
    int a = 3;
    int b = 5;

    // 利用公式建立密碼表字串
    int x, y, m;
    char c = 'a';
    string s;
    int i;
    for (i = 0; i < 26; i++) {
        x = c;
        y = x * a + b;
        m = y % 26;
        s += m + 97;
        c++;
    }

    // 將建立好的密碼表直接設定給成員變數
    code_array = s;
}

因為英文字母表的小寫字母共有 26 個,因此公式用迴圈 (loop) 跑了 26

for (i = 0; i < 26; i++) {
    x = c;
    y = x * a + b;
    m = y % 26;
    s += m + 97;
    c++;
}

我們多用了除了公式外的兩個變數 (variable) cs ,變數 c 為起始字元 (character) ,初值設定成英文字母表的第一個字母 'a's 則是宣告為字串 (string) ,這裡並沒有直接拿變數 c 進行計算,而是把變數 c 的值指派 (assign) 給整數型態的 x

    x = c;

會這樣做的原因很簡單,因為需要一個變數表示目前處理的字元,而字元型態的變數可以如同整數 (integer) 型態進行加減乘除,因此迴圈的最後利用遞增將變數 c 轉移到下一個字元,例如迴圈從 'a' 開始,第二個處理的字元為 'b' ,第三個為 'c' ,以此類推

    c++;

由於 C++ 的字元型態其實就是範圍較小的整數,因此也可以直接將迴圈的控制變數 i 設定為 97 ,讓 i 依次遞增到 97 + 26 為止。

迴圈跑完,最後就是把 s 設定給 code_array

// 將建立好的密碼表直接設定給成員變數
code_array = s;

建構函數 Encrypt() 就是呼叫 set_code_array() 設定 code_array ,另外 get_code_array() 也就是回傳 code_array ,目前的實作版本如下

// 引入 Encrypt 類別的標頭檔
#include "encrypt01.h"

// Encrypt 的建構函數
Encrypt::Encrypt() {
    // 呼叫 setter 設定 code_array
    set_code_array();
}

// 設定 code_array 的 setter 成員函數
void Encrypt::set_code_array() {
    // 設定 a 、 b 值
    int a = 3;
    int b = 5;

    // 利用公式建立密碼表字串
    int x, y, m;
    char c = 'a';
    string s;
    int i;
    for (i = 0; i < 26; i++) {
        x = c;
        y = x * a + b;
        m = y % 26;
        s += m + 97;
        c++;
    }

    // 將建立好的密碼表直接設定給成員變數
    code_array = s;
}

// 回傳密碼表字串的 getter 成員函數
string Encrypt::get_code_array() {
    return code_array;
}

/* 程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:encrypt01.cxx
   功能:實作發展中版本的 Encrypt 類別
   作者:張凱慶 */

我們用另外一個程式 (program) 來測試目前的版本吧!因為 ToEncode()ToDecode() 都還沒實作,所以就印出密碼表來看看就好了

// 引入標準程式庫中的 iostream
#include <iostream>
// 引入 Encrypt 類別的標頭檔
#include "encrypt01.h"

// 使用 std 中的兩個名稱
using std::cout; // 標準輸出串流的物件
using std::endl; // 新行符號,等於 '\n'

// 程式執行的 main() 函數
int main() {
    // 印出空白一行
    cout << endl;

    // 建立 Encrypt 物件
    Encrypt encryptor;
    // 印出密碼表字串
    cout << encryptor.get_code_array() << endl << endl;

    return 0;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:encrypt_demo01.cxx
   功能:實作發展中版本 Encrypt 類別的測試程式
   作者:張凱慶 */

編譯執行,結果如下

-encrypt_demo01-

結果如預期,一個英文小寫字母恰恰好對應到另外一個英文小寫字母,這樣我們的公式就 ok 了嗎?a 等於 3b 等於 5 是沒問題的,可是我們希望 ab 可以是 09 之間的任意整數,這樣就有 100 種組合說,所以我們接下來要繼續測試,看看是不是每一種組合都 ok 囉!

中英文術語對照
指派assign
字元character
整數integer
迴圈loop
程式program
標準程式庫standard library
字串string
變數variable
重點整理
1. 實作 set_code_array() 是先將公式中的 a 設成 3b 設成 5 ,然後用迴圈利用兩個控制變數 ic 逐一計算每個字元。
2. 字元型態就是範圍較小的整數,因此可直接進行算術運算。
3. 計算完的整數直接與字串進行運算,加號在字串類別重載過,因此可把轉換成字元的整數附加到字串的最後。
問題與討論
1. 為什麼不把建立對換表格直接寫在建構函數裡就好了?
2. 為什麼字串變數用 += 可以把字元附加到字串物件的最後?
練習
1. 字元陣列的最後一個元素如果是 '\0' 就可以跟字串進行比較,寫一個程式 exercise1501.cxx ,宣告相同內容的字元陣列及字串,例如 "hello" ,在字元陣列的結尾加上 '\0' ,然後利用比較相等運算子 == 測試兩者內容是否相等,如果相等就印出 "equal" ,不相等印出 "not equal"參考程式碼
2. 陣列識別字就是指標,寫一個程式 exercise1502.cxx ,宣告建立一個整數陣列,然後將整數陣列的識別字指派給整數指標變數,利用這個指標變數印出陣列的所有元素值。 參考程式碼
3. 標準程式庫中的 array 是物件形式的陣列,可以利用角括弧宣告陣列的型態及元素個數,例如 array<int, 5> 是含有五個元素的整數陣列,寫一個程式 exercise1503.cxx ,分別宣告整數陣列 int a1[]array<int, 5> a2 ,利用字面常數指派陣列內容,然後逐次比較兩個陣列, array 可用 at() 取得索引值的內容,如果比較結果相同就印出元素值,不相同就印出 "n"參考程式碼
4. 標準程式庫中的 array 同樣可以用中括弧及索引值存取與修改元素內容,另外 empty() 可判斷是否為空陣列, size() 回傳陣列元素總數,寫一個程式 exercise1504.cxx ,先利用字面常數設定陣列內容,再利用中括弧及索引值修改任意兩個元素內容,然後判斷陣列是否為空,如果不為空就印出全部的元素。 參考程式碼
5. 標準程式庫中的 array 還有其他好用的成員函數,寫一個程式 exercise1505.cxx ,宣告建立一個整數陣列,然後利用 front() 印出第一個元素, back() 印出最後一個元素。 參考程式碼
6. 基本內建型態利用小括弧,例如 (char) 97 ,就可以把整數 97 轉換成字元 'a' ,另外也可用關鍵字 static_cast 加上角括弧轉換成角括弧中指定的型態, static_cast 會在編譯期間做型態是否相容的檢查,寫一個程式 exercise1506.cxx ,宣告 int 變數 a97 ,然後利用 (char)static_cast<char> 轉換變出 a 為字元,並且印出轉換後的結果。 參考程式碼
7. 承上題,同樣的方式可以用在 int 轉換成 short ,但是 short 的範圍較小,因此如果 int 型態的變數數值超出 short 的範圍就會發生溢位,寫一個程式 exercise1507.cxx ,宣告 int 變數 a32768 ,然後印出轉換成 short 的結果。 參考程式碼
8. 承上題,同樣在 long 轉換成 int 也會有溢位問題,寫一個程式 exercise1508.cxx ,宣告 long 變數 a2147483648 ,然後印出轉換成 int 的結果。 參考程式碼
9. 承上題,同樣的方式可以用在浮點數轉換成整數,例如 float 轉換成 int ,寫一個程式 exercise1509.cxx ,宣告 float 變數 a10.51 ,然後印出轉換成 int 的結果。 參考程式碼
10. 承上題,如果是字串要轉換成整數或浮點數,例如 "99.99" 轉換成 intfloat ,需要用到標準程式庫中 stringstoi()stof() ,寫一個程式 exercise1510.cxx ,宣告 string 變數 a"99.99" ,然後印出轉換成 intfloat 的結果。 參考程式碼

相關教學影片

上一頁 單元 14 - Encrypt 類別
回 C++ 入門指南 4.01 目錄
下一頁 單元 15 - 實作 set_code_array()
回 C++ 教材
回程式語言教材首頁