實 習 內 容 | |
實
|
繼我們練習寫過 檔案輸出入, 三位數字轉換中文輸出, 簡易計算機, 尋找完全數, 計算最大公因數 的程式之後, 這個實習中我們練習 1. 綜合運用 條件敘述, 迴圈, 函數 來模組化地設計程式 2. 撰寫一個可以完成 "分數加減乘除運算" 的程式 |
1 |
這個實習中, 我們要設計一個可以完成 "分數加減乘除運算" 的程式 操作者可以輸入兩個普通分數 (common fraction, 2/3, 7/2...), 以及運算符號, 程式會完成指定的運算並且用最簡分數列印運算的結果 執行過程如下: Enter a common fraction as two integers separated by a slash> 2/3 2/3 + 5/9 = 11/9 2/3 - 1/6 = 1/2 2/3 * 9/8 = 3/4 |
2 |
main() 函數: 這個程式 main() 函數中最主要的架構會是如下的迴圈, 包括 1. 讀取資料及運算命令, 2. 進行指定的運算並且化簡, 3. 列印執行結果: do { /* 讀取第一個分數 */ /* 讀取運算子 op */ /* 讀取第二個分數 */ switch (op) /* 判斷運算的種類 */ { case '+': /* 執行加法運算 */ break; case 接下來可以針對各個部份撰寫函數來完成指定的功能 因為這樣子分工以後 (這也就是所謂由上而下 (top-down) 的程式設計方法), 每一個函數所需要處理的工作都變得很簡單, 當然也要求你一定要讓每一個函數所處理的資料 (輸入哪些資料, 輸出哪些資料) 很明顯地運用函數的參數表示出來 (請不要使用全域變數) |
3 |
讀取分數函數 每一個分數包括三部分: 分子, /, 分母, 例如: 3 / 4 5/ 6 7 /8 9 / 10 運算元 都是合法的輸入 這個函數的定義應該類似 void scan_fraction(int *numerator, int *denominator); 函數裡面我們可以用 iret = scanf("%d %c%d", numerator, &slash, denominator); 來讀取使用者由鍵盤輸入的資料, 第一個 %d 會自動跳過所有的空格, 讀入十進位的整數分子, %c 不會跳過空格, 所以前面需要加上一個空格來要求 scanf 跳過所有空格, 接下來的 %d 可以自動跳過空格讀入十進位的整數分母 scanf() 函式如果讀到了三筆資料的話, 回傳的數值 iret 就是資料的筆數 3, 同時 slash == '/', 如果兩者有任何不正確的話就需要印出訊息提示使用者重新輸入 另外, 分母之後一直到換列字元的文字如果是對程式無意義的注釋, 需要使用一個迴圈跳過, 例如: char discard;函數寫完以後請儘快編譯, 測試執行的結果, 不要等到整個程式寫完以後才編譯, 才測試。以這個函數來說, 就可以在函數執行完回到 main 的時候印出 分子和分母來看一下, 就知道是否正確。 |
4 |
讀取運算子函數 這個函數的定義應該類似 char get_operator(void); 函數裡面包括一個迴圈, 運用 scanf 函數讀取字元, 檢查是不是可以接受的 +, -, *, /, 如果不是的話, 印出訊息提示使用者重新輸入 |
5 |
執行加法運算的函數 這個函數傳進去兩個分數, 回傳兩個分數相加的結果 (因為在 main() 中我們在執行完運算後才統一執行分數化簡的動作, 所以這個函數加起來的分數不需要化簡), 函數的定義如下: void add_fractions(int num1, int denom1, int num2, int denom2, int *num_ansp, int *denom_ansp); num1, denom1 代表傳入的第一個分數, num2, denom2 代表傳入的第二個分數, num_ansp, denom_ansp 則是為了把結果傳出函數的兩個記憶體位址 分數的加法需要通分, 計算兩個分母的乘積作為新的分母, 例如 新的分子也可以很快算出 統一把正負號放在新的分子裡面, 分母讓它維持是正數 為了盡快可以看到程式執行的結果, 測試每一部份的程式的正確性, 下一步驟裡可以先寫列印結果的函數 |
6 |
列印結果的函數: 在 main 函數裡迴圈的最後, 需要寫一個列印結果的函數, 傳入兩個分數和運算子, 再傳入化簡過的分數結果, 運用 printf 函數輸出如下的運算式: 2/3 * 9/8 = 3/4 |
7 |
執行減法運算的函數 其實這個函數應該可以不用寫, 直接呼叫前面執行加法運算的函數 add_fractions, 將第二個分數變號就可以完成了 |
8 |
執行乘法運算的函數 這個函數傳進去兩個分數, 回傳兩個分數相乘結果 (因為在 main() 中我們在執行完運算後才統一執行分數化簡的動作, 所以這個函數加起來的分數不需要化簡), 函數的定義如下: void mult_fractions(int num1, int denom1, int num2, int denom2, int *num_ansp, int *denom_ansp);乘法的動作比加減法更簡單, 基本上分子分子相乘, 分母分母相乘就快要好了, 只需要檢查一下是否為最簡分數 |
9 |
執行除法運算的函數 其實這個函數應該可以不用寫, 直接呼叫前面執行乘法運算的函數 mult_fractions, 將第二個分數分子分母互調就完成了 |
10 |
分數化簡的函數 這個函數傳進去一個分數, 回傳這個分數化簡後的結果, 函數的定義如下: void reduce_fraction(int *nump,int *denomp);函數的內部首先用上課講過的 gcd() 函數來找到分子和分母的最大公因數, 然後化簡過的分子就是原來的分子除以最大公因數, 化簡過的分母就是原來的分母除以最大公因數 |
11 |
合併測試: 編譯並且測試下列
|
12 |
線上繳交: 完成上述測試以後, 請將提示使用者的文字註解掉, (例如 Enter a common
fraction as two integers separated by a slash>) 然後在
e-Tutor 線上繳交 |