這是個暖身的作業, 所以我寫了很多的提示, 按部就班地作應該不會太困難, 不過要寫的東西蠻多的, 請提早寫, 否則一定寫不完, 作業佔的比例很高, 不要放棄掉, 萬一最後你只完成了部份, 還是建議你交過來, 唯一不需要交過來的是別人的作業。雖然這比較像一個實習題目, 挑戰性稍微少了一點, 不過還是可以練習許多必備的語法與設計, 以後的作業應該就沒有那麼多提示了。
請下載範例執行程式 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 之間, 任何時候如果數值超過這個範圍, 我們應該把這個物件標示為錯誤, 同時可能不允許這個物件提供某些服務 (例如參與某些運算)
這個成員函式需要檢查傳進來的資料是否合法 (分母不能是 0, 分數的數值在範圍內...), 並且記錄資料在物件內, (所以類別內應該要有存放分子和分母的資料成員), 如果原先自己這個物件內有任何舊的資料的話都要清除掉, 如果設定失敗的話, 應該要傳回 false, 同時分數物件應該變成是一種不合法的數字, 要求和一個不合法的數字進行運算的話也應該會產生同樣不合法的數字; 反之成功的話就傳回 true, 另外這個成員函式應該是一個 public 的界面函式
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();
這個函式會讀取 original 指標所指向分數物件內的資料, 並且拷貝在自己這個物件內, 如果 original 指標所只到的物件是不合法的數字, 拷貝過來以後自己這個物件也會變成不合法的
請注意分母不要設為 0, 你可能需要自己設定一個特定的數字作為分母。
這個函式暫時不要回傳值, 可以先設為 void。 (你自己也可以先嘗試回傳一個分數的物件, 想想看會有什麼問題? )
另外請注意在這個乘法的動作裡並不會修改傳入的參數, 請用 const 的敘述宣告來確保這樣的結果。
如果你會化簡分數的話, 應該要先把分子分母共同的因數去除以後再做乘積, 這樣比較不會發生分子或是分母溢位的狀況。 你也可以想想看萬一發生溢位的狀況, 程式有沒有辦法自己檢查出來。
如果兩個數字中有一個是不合法的數字時, 乘積也是一個不合法的數字
在這個成員函式中, 你當然可以存取這個物件的分子和分母, 但是當傳入的參數也是這個 CFraction 類別的物件時, 這個成員函式也可以直接存取傳入的分數物件的分子和分母。
例如原來物件 A 的內容是 3/5, B 的內容是 7/9
執行完以後 A 物件的內容成為 7/15
請注意在這個運算裡不論是傳入的物件或是自己這個物件的內容維持不變, 請用 const 敘述保證這 兩件 事情。
另外還需要注意你可以比較化簡過的分數, 但是不能直接用 == 來比較浮點數值的 (如果在製作這個功能的時候, 你打算直接用浮點數來比較的話,
你需要設計適當的方法, 同時繳交作業的時候必須說明你的作法。)
請特別注意如果傳入的物件根本就是自己這個物件的話, 要傳回 true 的結果。 你可以運用下列的敘述檢查傳入的物件是否等於自己:
如果兩個分數物件中有不合法的分數時, 我們定義它們是不等的。
如果分子是 0 的話, 不需要比較分母
assert(gcd(100, 65) == 5); assert(gcd(-100, 65) == 5); assert(gcd(-100, -65) == 5); assert(gcd(0, 65) == 1);想要自己寫的同學請參考下面求 gcd(1180, 482) 的說明, 函式應該不會很長:
- 12 / 1237這個函式請傳入一個螢幕輸出資料串流 ostream 的參考參數, 不需要回傳任何數值, 也不會更改物件的內容
四個位元組的整數代表分母, 四個位元組的整數代表分子如果是一個無效的分數物件, 輸出分子及分母都設為 123456789
請由鍵盤讀入一個檔案名稱, (例如 ass1_data1.dat) 這個檔案裡的資料都是以二進位的方式存放, 開啟這個檔案時應該將 nMode 設為 ios::in | ios::binary, 前四個位元組是一個整數, 代表在這個檔案裡共有幾個分數, 接下去是一連串的分數資料, 每一個分數分別有四個位元組的整數代表分母, 以及四個位元組的整數代表分子, 請注意如果分子與分母同為 123456789 則代表此為一不合法的分數, 請將這些分數讀入記憶體內成為分數物件, 並且記錄在一個 vector 物件中, 請逐一將每一個分數化簡, 然後請利用 C++ 標準函式庫中 STL 的 sort 將此物件由大到小排序, 請注意排序時不合法的分數排在最後, 將排序過後的分數在螢幕上列印出來, 請計算並列印所有分數的總和、平均值、和中間值, 最後由鍵盤讀入一個輸出的檔案名稱, 將所有的排序過後的分數資料以輸入 資料檔案相同的二進位格式存入新的檔案中。
原則上你想要增加什麼功能都是可以的, 記得在心得中寫出來, 這樣我才會注意到, 也才能夠幫你加一些分數, 現在程式還簡單, 你應該有辦法增加功能或是基於這個類別做一些好玩的應用。
回
C++ 程式設計課程
首頁
製作日期: 3/13/2005
by 丁培毅 (Pei-yih Ting)
E-mail: pyting@cs.ntou.edu.tw
TEL: 02 24622192x6615
海洋大學
工學院
資訊工程系
Lagoon