C 語言初學教材 - 第二章 將加法器擴展成四則運算器

加法器很簡單,純粹處理加法也很實用,但我們總是希望程式多點功能,直接可以處理所有加減乘除等四則運算的計算工作。有需求,程式就可以隨之推出改進的版本,想一想,該怎麼設計新的程式版本呢?



因為我們已經寫出了加法器,依序可以接受使用者輸入兩個整數,那麼我們中間多輸入一個表示加減乘除的字元,然後設計一個機制,讓程式可以判斷是加減乘除的哪個符號不就可以了嗎?依照這個想法寫出的程式如下
#include <stdio.h>

int main(void)
{
    int a, b; //宣告需要用到的變數
    char opt;
    
    printf("這個程式會依符號計算兩個整數的和、差、積、商....\n");
    printf("請輸入第一個整數: "); //提示使用者輸入的文字
    scanf("%d", &a);
    printf("請輸入運算符號: "); //提示使用者輸入的文字
    scanf("%s", &opt);
    printf("請輸入第二個整數: "); //提示使用者輸入的文字
    scanf("%d", &b);
    
    //以下會依所輸入的運算子計算並印出結果
    printf("結果如下: \n");
    switch (opt) { 
        case '+':
            printf("%d + %d = %d\n", a, b, a + b);
            break;

        case '-':
            printf("%d - %d = %d\n", a, b, a - b);
            break;

        case '*':
            printf("%d * %d = %d\n", a, b, a * b);
            break;

        case '/':
            printf("%d / %d = %d\n", a, b, a / b);
            break;

        default:
            printf("輸入錯誤!\n");
            break;
    }
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:calculator1.c
    功能:接受使用者輸入的四則運算器
    作者:張凱慶
    時間:西元2010年7月 */


我們利用了 switch-case 陳述作為分辨運算子的機制,程式的第 18 行到第 38 行便是 switch-case 陳述的部份。 switch-case 為複合陳述,用法圖解如下



switch-case 為複合陳述,大括弧後不需要以分號結尾。


switch 為關鍵字之一,其後接一個小括弧,小括弧內必須是常數,或是運算結果為常數的運算式。然後接一對大括弧,大括弧裡放多個 case 及後最後一個 default 。 case 及 default 也都是關鍵字, case 的作用就是對情況進行判斷,所謂的情況就是 case 後一個空格,然後接的常數或常數運算式,然後再接一個冒號。


如果 switch 的常數與任何一個 case 的常數相同,該 case 底下的陳述就會被執行。每個 case 最後會用一個 break 陳述結尾,這是要中斷 switch 繼續做 case 條件檢查之用。 break 亦為關鍵字之一,用於中斷迴圈或跳出 switch 陳述。 deault 可以看成是預設的 case ,假如以上的 case 都不符合,就會執行 default 底下的陳述。


如果沒有用 break 陳述, switch 陳述就會一直檢查 case 情況到最後,因此加入 break 陳述可以早一步離開 switch 。而 我們把 default 放在整個 switch 陳述的最後,也就是右大括弧之前,其實這裡可以不加 break 陳述,因為上面每個 case 都不符合才會執行 default 的部份,之所以也放 break 陳述的原因很簡單,只是讓程式碼看起來對齊一致,既然每個 case 都有 break ,那 default 也就加入 break 囉!


另外注意第 6 行,我們宣告一個字元變數 opt 來放使用者輸入的運算符號
char opt;


鍵盤支援的加減乘除運算子分別為 + 、 - 、 * 、 / ,因此使用者需要輸入相對應的符號,我們利用第 12 行的函數 scanf() 取得 使用者輸入的運算符號
scanf("%s", &opt);


這裡的轉換字符是 %s ,本來是接收字串,字元的轉換字符為 %c ,我們不是接收一個字元就可以了嗎?會用 %s 而不是 %c 的原因其實也很簡單,因為當我們按下 return 或 Enter 鍵的時候就等於我們輸入了新行字元,因此當上一個數字輸入完按下 return 或 Enter 鍵的時候,輸入緩衝區多儲存了一個新行字元,因此若是我們這裡採用 %c 的方式,會使函數 scanf() 直接從緩衝區讀取上一次按下的新行字元,而造成無法輸入運算符號的問題。


另外,我們少宣告一個 result 變數,這是因為我們呼叫 printf() 的時候,直接把運算式當作參數代入。由於運算式會計算出一個數值,因此通常可以直接用型態符合的運算式當成參數。


我們來編譯執行看看吧!



嗯,若是若是沒有輸入整數,程式會發生錯誤。我們先把這個問題擱在一旁,先來想想有沒有其他的設計方式。


問題與討論
  1. 這個四則運算器需要使用者連續輸入三次,這樣的設計方式好不好?
  2. 將程式中的 break 陳述移除,重新編譯執行,看會得到什麼樣的結果。
  3. 參數也可以用運算式,這樣呼叫函數時有什麼方便的地方?
  4. 若是在函數 scanf() 中應該輸入整數,而輸入其他字元發生錯誤,可以設計什麼樣的防範機制呢?




1 則留言:

YC 提到...

想問如果想改用陣列的方式去寫~那要怎麼改