C++ 入門指南 V2.00 - 單元 16 - 繼續測試




軟體生命週期 (software life cycle) 分成三大階段,開發 (development) 、使用 (use) 、修改 (modification) ,接下來便是使用、修改的無限循環



開發階段,自然免不了對需求的分析 (analysis) ,然後設計 (design) 、建置 (implement) ,接著進行測試 (testing) ,其實這順序沒有絕對,「設計」與「建置」可能只是先做個簡單版本,「測試」與「使用」說到底都是實際執行後觀察結果,「修改」等於以之前的基礎再次「設計」與重新「建置」。


我們打算開發的 Encrypt 類別 (class) 的需求已經很清楚,也就是產生一個英文小寫字母的對照字串 (string) ,我們用 code_array 儲存這個字串,然後以 set_code_array() 建立這個字串。


上個單元中,我們將 a 設定為 3b 設定為 5 ,順利的跑出一個英文小寫字母的對照字串,現在我們希望把 ab 設定成 09 之間的隨機整數,這該怎麼做呢?簡單講,就是要有個產生隨機整數的方式,還好標準程式庫 (standard library) 中已經有相關程式供我們直接使用,因此我們不需要自己重頭開發。


標準程式庫中 cstdlibrand() 可產生 0RAND_MAX 的擬隨機整數,加一個「擬」的意思是這個數字是模擬出來的,並不算是數學上真正的隨機,不過就我們的需求來講就夠用了,而 RAND_MAX 的數值在 64 位元的 GCC 為 2147483647


除了 rand() 外,還需要同在 cstdlibsrand() 初始化取得擬隨機數的種子,另外要用 ctimetime() 取得現在時間當作 srand() 的參數,因此原本的實作檔修改如下


001 // 引入標準程式庫中的 cstdlib 及 ctime
002 #include <cstdlib> // srand(), rand()
003 #include <ctime>   // time()
004
005 // 引入 Encrypt 類別的標頭檔 
006 #include "encrypt01.h"
007
008 // Encrypt 的建構函數 
009 Encrypt::Encrypt() {
010    // 呼叫 setter 設定 code_array
011    set_code_array();    
012 }
013
014 // 設定 code_array 的 setter 成員函數
015 void Encrypt::set_code_array() {
016    // 初始化擬隨機數產生器 
017    srand(time(0));
018
019    // 取得 a 、 b 值 
020    int a = rand() % 10;
021    int b = rand() % 10;
022
023    // 利用公式建立密碼表字串     
024    int x, y, m;
025    char c = 'a';
026    string s;
027    int i;
028    for (i = 0; i < 26; i++) {
029       x = c; 
030       y = x * a + b;
031       m = y % 26;
032       s += m + 97; 
033       c++; 
034    }
035
036    // 將建立好的密碼表直接設定給成員變數
037    code_array = s; 
038 }
039
040 // 回傳密碼表字串的 getter 成員函數     
041 string Encrypt::get_code_array() {
042    return code_array;
043 }
044
045 /* encrypt02.cpp 
046    Kaiching Chang 
047    2014-5 */

程式開頭先引入 cstdlibctime


001 // 引入標準程式庫中的 cstdlib 及 ctime
002 #include <cstdlib> // srand(), rand()
003 #include <ctime>   // time()

然後在 set_code_array 中初始化擬隨機數產生器


016 // 初始化擬隨機數產生器 
017 srand(time(0));

接者利用 rand() 取得 ab


019 // 取得 a 、 b 值 
020 int a = rand() % 10;
021 int b = rand() % 10;

那就來編譯測試看看囉



看起來還不錯,再多測試幾次看看



居然有一行都是 'g' ,有些是我們要的密碼表沒錯,有一些則不是,那表示我們所用的數學公式有問題,接下來要先修正數學公式。


中英文術語對照


軟體生命週期 software life cycle
開發 development
使用 use
修改 modification
分析 analysis
設計 design
建置 implement
測試 testing
類別 class
字串 string
標準程式庫 standard library

重點整理


  1. 軟體的生命週期分成開發、使用、修改三大階段。
  2. 開發階段就是對需求分析,然後設計、建置、測試等等。
  3. 標準程式庫中 cstdlibrand() 回傳 0RAND_MAX 的擬隨機整數,並需要以 srand() 初始化取得擬隨機數的種子。
  4. 設計、建置完軟體的初始版本就進行測試,如果有問題,就重新檢視設計, Encrypt 的數學公式有問題,因此要研究問題出在哪,再回頭修改程式。

問題與討論


  1. 軟體的生命週期分成哪些階段?
  2. 設計軟體的時候,該不該重視使用者的體驗經驗?
  3. 想一想, Encrypt 的數學公式問題可能發生在哪裡?該如何修正呢?

練習


  1. 承接上一個單元的猜數字遊戲,將新程式寫在 exercise1601.cpp 中,把測試答案與猜測陣列的部份寫在 EqualTest() 裡,結果回傳布林值。
  2. 承上題,設計一個函數 ABCounter() 計算 AB 值,用另一個 ab_array[] 陣列紀錄 AB 值,若使用者沒用猜對就印出AB 值,將新程式寫在 exercise1602.cpp 中。
  3. 承上題,加入迴圈直到使用者猜對答案為止,將新程式寫在 exercise1603.cpp 中。

the end

沒有留言: