1032 Midterm 複數運算式 (Complex Expression)

2015/04/23

C++ 實習期中考: 複數運算式 (Complex Expression) 類別設計

時間: 150分鐘 (請於 12:05 前上傳)

在這個測試裡, 期待你練習的東西包括:

1. 撰寫封裝完整的類別 (包括建構元, 解構元, 拷貝建構元, 供其它物件操作的界面函式), 例如 Complex, Expression, OperandStack 等等

2. 希望你練習多個物件之間的合作

3. 基本的 Postfix Expression Evaluation

我們有一個輸入檔案 test1.dat, 內容如下:

(1.1 + 2.2 i)
(3   + 4.5 i)
*
(-5.1 + 6 i)
/
(0 - 3 i)
+
(-2 + 1.5 i)
(1 + 1 i)
*
-

這代表一個後序 (postfix) 的複數運算式, 請實作一個程式讀取這個資料檔案, 輸出如下:

(1.1 + 2.2 i) * (3 + 4.5 i) / (-5.1 + 6 i) + (0 - 3 i) - (-2 + 1.5 i) * (1 + 1 i
) = (5.16038 - 2.81132 i)


A second copy of the expression:
(1.1 + 2.2 i) * (3 + 4.5 i) / (-5.1 + 6 i) + (0 - 3 i) - (-2 + 1.5 i) * (1 + 1 i
) = (5.16038 - 2.81132 i)

上面的輸入資料中, 每一列可以是一個複數, 或是 +, -, *, / 四個運算子, 每一個複數用 (a + b i) 或是 (a - b i) 的形式表示, a, b 可以是正負整數或是實數, 為了簡化處理程序, a 如果是 0 並不會省略, b 如果是 0 或是 1 也不會省略寫成 0 i 或是 i

為了降低一點列印時處理上的複雜度, 資料檔案中的後序運算式都是由沒有小括號的中序運算式轉寫出來的, 也就是說運算符號執行的先後順序完全是由運算符號的優先順序和結合律來決定的,
舉個例子來說, 檔案裡不會出現類似下面的後序運算式

(1.1 + 2.2 i)
(3 + 4.5 i) 
+
(-5.1 + 6 i) 
/

輸出時首先輸出 中序 (infix) 的複數運算式, 然後印出運算式計算的結果, 由於上面的簡化, 中序的複數運算式不需要任何小括號, 同樣地為了簡化處理程序, 輸出時以 (a + b i) 或是 (a - b i) 表示複數, 如果 a 是 0 或是 b 是 0 或是 b 是 1 時, 都直接印出不做簡化, 所以會印 0 + 2 i 而不是 2 i, 會印 2 + 1 i 而不是 2 + i, 會印 0 + 3 i 而不是 3 i

上面的範例輸出裡 A second copy .... 後面的東西其實沒有強制要求, 是因為要求你寫 copy ctror, 總是要運用一下, 確定功能是沒有問題的, 所以複製了運算式的物件一次, 重新算出運算的數值並且列印出來

在撰寫物件化的程式時其實你需要自己規劃下面的步驟, 當然這些步驟也不是唯一的, 有機會的話自己需要多練習一下

實習 3-1 中製作了 Complex 類別, 請先下載你所繳交的作業, 那個時候還沒有講到建構元, 所以我們實作一個 setValues(double real, double imaginary) 的成員設定物件的數值, 請先用一個兩個參數的建構元取代

請實作 ostream &operator<<(ostream &os, Complex &x); 全域函式

請實作 istream &operator>>(istream &is, Complex &x); 全域函式

這個問題可以分成兩部分來看, 如果純粹只是要計算出 後序運算式的運算結果, 你可以先實作一個 Complex 的堆疊類別, 然後實作下面的演算法 , 最後列印出結果

後序運算式計算: 使用一個堆疊來協助存放運算式中的複數
1) 一列一列讀入運算式,當讀到運算元時,將運算元放入堆疊中
2) 當讀到運算符號 +,-,*,/ 時,由堆疊最上面取出兩個運算元,進行運算後再放入堆疊
3) 當運算式讀完時,堆疊最上面就是計算的結果

可以用下面的方法來得到題目所要求 印出中序的運算式 的功能:

  1. 請設計一個 Expression 類別來記錄這個運算式的樹狀架構
  2. 請寫一個建構元, 用和上面計算後序運算式一模一樣的演算法, 在讀取檔案串流的過程中建構一個如下圖的樹狀結構, 在這個步驟裡你也需要定義一個節點的結構, 每個節點可以用來存放運算符號或是複數運算元, 順便替這個結構製作建構元函式, 另外也需要再製作一個堆疊, 用來存放節點的指標
  3. 請寫一個界面 printInfix 用 中序巡訪 很快地列印出中序的運算式 (如果你想要列印出所有可能的後序運算式, 你可以運用類似前序巡訪的演算法, 一開始印出左邊小括號, 用遞迴去列印左邊運算式, 印出運算符號, 用遞迴去列印右邊運算式, 最後印出右邊小括號)
  4. 請寫一個 evaluate 的界面函式來計算運算式的值
  5. 由於這個類別的物件中有配置複雜的資料結構, 請替 Expression 類別撰寫解構元函式
  6. 請替 Expression 類別寫一個 copy ctor (上面範例執行結果中 A second copy of the expression 就是測試 copy ctor 的運作的輸出結果)
  7. assignment operator 就不實作了, 但是為了安全起見, 請用簡單的存取權限來防止別人誤用

藍字部份是中間過程的計算結果, 萬一你需要 debug 時, 有這些結果可以核對會比較方便

不論你做到什麼階段, 請將你的 project (只需保留 .cpp, .h, .sln 以及 .vcxproj 檔案即可; 刪除掉 .suo, .sdf, .filters, .users, debug\ 資料匣, 以及 ipch\ 資料匣下的所有內容) 以 zip/rar/7zip 程式將整個資料匣壓縮起來, 選擇 Labtest2上傳

C++ 物件導向程式設計課程 首頁

製作日期: 04/23/2015 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon