2005 Spring C++ 程式作業一:
        分數 (Fraction) 類別設計

這是個暖身的作業, 所以我寫了很多的提示, 按部就班地作應該不會太困難, 不過要寫的東西蠻多的, 請提早寫, 否則一定寫不完, 作業佔的比例很高, 不要放棄掉, 萬一最後你只完成了部份, 還是建議你交過來, 唯一不需要交過來的是別人的作業。雖然這比較像一個實習題目, 挑戰性稍微少了一點, 不過還是可以練習許多必備的語法與設計, 以後的作業應該就沒有那麼多提示了。

分數 (Fraction) 類別設計

作業目標:

    1. 練習各種流程控制: for, while, if, switch, 函式等等,
    2. 練習二進位檔案的輸入與輸出
    3. 練習基礎的類別語法
    4. 練習類別界面的設計
    5. 使用自定類別產生物件
    6. 練習 bottom-up 的程式設計方法
    7. 練習使用 vector 類別物件
    8. 練習使用 STL sort 樣板函式
    9. 請使用多個 .h, .cpp 檔案來分隔你的程式模組

請下載範例執行程式 fractionMain.exe , 資料檔案: ass1_data1.dat 或是 ass1_data2.dat 或是 ass1_data3.dat 或是 ass1_data4.dat

執行記錄顯示

執行時先要輸入 ass1_data1.dat 或是 ass1_data2.dat 或是 ass1_data3.dat 或是 ass1_data4.dat
然後輸入一個輸出檔案名稱, 程式會列印出簡化、排序過後的分數序列、總和、
平均值、與中間值
請注意: ass1_data1.dat (或是 ass1_data2.dat 或是 ass1_data3.dat 或是 ass1_data4.dat) 檔案中存放多個以二進位格式存放的分數, 直接以編輯器讀取應該是看不出什麼的, 還有 ass1_data4.dat 的總和和平均值會算不出來。

程式基本要求

在這個作業中我們希望製作一個 "分數" 的類別, "分數"一般在數學上是類似

1/2, -3/8, -5/20, 1752/396 或是 7435/343

上面這幾個分數有的還可以化簡, 讓分子和分母沒有公因數

對於一個分數的物件來說, 必須提供一些基本的功能, 例如: 加法, 減法, 乘法, 除法, 相等, 大於, 化簡, 轉為浮點數, 讀檔/寫檔 (序列化), 列印 等等, 請製作一個 "分數" 的類別來處理這樣的資料, 為了練習製作物件狀態檢查的功能, 我們額外限制每一個分數物件的數值在 10000 到 -10000 之間, 任何時候如果數值超過這個範圍, 我們應該把這個物件標示為錯誤, 同時可能不允許這個物件提供某些服務 (例如參與某些運算)

  1. 首先利用 Visual Studio 工具製作一個 CFraction 的類別

  2. 請撰寫一個設定分數物件內容的成員函式:

    這個成員函式需要檢查傳進來的資料是否合法 (分母不能是 0, 分數的數值在範圍內...), 並且記錄資料在物件內, (所以類別內應該要有存放分子和分母的資料成員), 如果原先自己這個物件內有任何舊的資料的話都要清除掉, 如果設定失敗的話, 應該要傳回 false, 同時分數物件應該變成是一種不合法的數字, 要求和一個不合法的數字進行運算的話也應該會產生同樣不合法的數字; 反之成功的話就傳回 true, 另外這個成員函式應該是一個 public 的界面函式

  3. 請撰寫一個 static 的 CFraction 成員函式 unitTest(), 在這個函式中運用 assert() 替下面所有逐步增加的功能都撰寫單元測試的程式碼, 每寫完一個功能就進行部份的測試, 在持續不斷地修改程式與不斷地新增程式功能的過程中, 你可以逐步的測試所有增加的功能, 並且確保增加新的功能時, 已經測試過的功能都維持正確, 請參考實習 1-2 以及 3-2 , 例如針對上面 setValue() 功能的測試可以包括下列:
    	void CFraction::unitTest()
    	{
    	    CFraction f1;
    	    assert(f1.setValue(1245, -1230));
    	    assert(!f1.setValue(1234, 0));
    	    assert(!f1.setValue(10001, 1));
    	    assert(!f1.setValue(10001, -1));
    	}
    在製作這個 CFraction 類別的過程中,主程式裡可以如下呼叫單元測試的函式:
    	CFraction::unitTest();

  4. 請再撰寫一個拷貝分數物件內容的成員函式:

    這個函式會讀取 original 指標所指向分數物件內的資料, 並且拷貝在自己這個物件內, 如果 original 指標所只到的物件是不合法的數字, 拷貝過來以後自己這個物件也會變成不合法的

  5. 請撰寫一個將資料設為 0 的函式:

    請注意分母不要設為 0, 你可能需要自己設定一個特定的數字作為分母。

  6. 接下來要替這個分數類別 CFraction 寫下面的成員函式, 這是這種類型的物件所需要提供給其它類型物件的服務:

     

  7. 請替這個類別寫一個成員函式以分數的形式在螢幕上列印出來, 例如:
        - 12 / 1237
    這個函式請傳入一個螢幕輸出資料串流 ostream 的參考參數, 不需要回傳任何數值, 也不會更改物件的內容

  8. 請替這個類別寫一個成員函式, 傳入一個檔案串流 ofstream 物件的參考, 將物件內容以二進位格式寫入檔案串流中, 每一個物件在檔案串流中的格式如下:
        四個位元組的整數代表分母,
        四個位元組的整數代表分子
    如果是一個無效的分數物件, 輸出分子及分母都設為 123456789

  9. 請替這個類別寫一個成員函式, 傳入一個檔案串流 ifstream 物件的參考, 將檔案內容 (如上一步驟的格式) 讀進分數物件內, 請注意讀入的資料應該要覆蓋原來物件內的資料

  10. 主程式: (請參考範例執行程式執行記錄)
        請由鍵盤讀入一個檔案名稱, (例如 ass1_data1.dat)
        這個檔案裡的資料都是以二進位的方式存放,
        開啟這個檔案時應該將 nMode 設為 ios::in | ios::binary,
        前四個位元組是一個整數,
        代表在這個檔案裡共有幾個分數,
        接下去是一連串的分數資料,
        每一個分數分別有四個位元組的整數代表分母, 
        以及四個位元組的整數代表分子,
        請注意如果分子與分母同為 123456789 則代表此為一不合法的分數,
        請將這些分數讀入記憶體內成為分數物件, 
        並且記錄在一個 vector 物件中,
        請逐一將每一個分數化簡,
        然後請利用 C++ 標準函式庫中 STL 的 sort 將此物件由大到小排序,
        請注意排序時不合法的分數排在最後,
        將排序過後的分數在螢幕上列印出來, 
        請計算並列印所有分數的總和、平均值、和中間值,
        最後由鍵盤讀入一個輸出的檔案名稱,
        將所有的排序過後的分數資料以輸入
        資料檔案相同的二進位格式存入新的檔案中。
    

  11. 測試檔案: ass1_data1.dat, ass1_data2.dat, ass1_data3.datass1_data4.dat (請注意這四個檔案內的資料都是二進位格式, 所以你用編輯器打開來看都是看不懂的東西, 每一個檔案裡都依序存放多個分數物件)

其他注意事項:

  1. 撰寫程式的時候由於你還不是很熟悉 C++ 的語法, 最好是寫一點點就編譯一下, 才不會一直等到寫完了以後發現錯誤很多, 不知道怎樣開始修改。

  2. 請注意變數的命名和函式的命名不可太短, 要有意義

  3. 各個函式的功能盡量不要重複, 可以盡量用已經設計好的功能來組合成新的功能, 例如: 減法的功能應該可以用加法的功能來完成, 這樣子可以減少程式維護的困難

  4. 你開始測試這個程式的時候,會發現在做加減乘除的時候很容易就發生溢位的狀況,比較好的作法應該是不斷地測試是否溢位 (正數乘正數得到超過四個位元組整數可以表示的數字..), 如果偷懶一點的話至少你需要不斷地化簡 (不過這樣還是非常危險的), 其實在 C 程式中要偵測整數的溢位有點困難, 需要用所謂的 inline assembly 來直接使用 x86 組合語言偵測溢位, 這個作業所製作的分數類別其實應該配合一個可以表達任意範圍的整數的類別來運作, 才不會遇見這種需要偵測溢位的情形。

進一步增加程式的功能

原則上你想要增加什麼功能都是可以的, 記得在心得中寫出來, 這樣我才會注意到, 也才能夠幫你加一些分數, 現在程式還簡單, 你應該有辦法增加功能或是基於這個類別做一些好玩的應用。

C++ 程式設計課程 首頁

製作日期: 3/13/2005 by 丁培毅 (Pei-yih Ting)
E-mail: [email protected] TEL: 02 24622192x6615
海洋大學 工學院 資訊工程系 Lagoon