這是我們對輸入第一個整數進行過的測試,現在我們拿四則運算器的例子重新進行測試,分別輸入 o+o 、 o+9 、 9o9 、 9+o
嗯,前三者都讓 switch 顯示 default 的「輸入錯誤!」,雖然我們希望 switch 的運作是跟輸運運算符號直接相關,不過輸入第一個整數(運算元)時,也導致 switch 選擇 default ,這樣的運作方式倒是可以接受,當成輸入第一個整數的錯誤防範機制。
但是第四個測試卻出現了很奇怪的整數,而且程式能繼續計算,結果還會計算列印出來,這自然不會是我們想要的運作方式,我們總是希望輸入型態不符的話,程式能直接顯示「輸入錯誤!」。類似這樣的錯誤被稱為語意錯誤,就是程式能順利執行,但是結果非預期。
語意錯誤跟語法錯誤都是很常發生的錯誤,後者無法順利編譯,同時編譯器會提供錯誤訊息,然而前者,也就是語意錯誤卻能順利編譯,程式能成功執行,但是會得到非預期的結果。通常語意錯誤需要對程式進行反覆測試,例如在與使用者互動的程式中,利用各種不同的輸入來查看執行結果是否正確。
那我們該如何修正這個錯誤呢?由於函數 scanf() 會回傳一個整數,表示所輸入的型態相符的輸入值。例如要輸入兩個整數,若使用者正確輸入兩個整數, scanf() 就回傳 2 ,同樣的,我們的例子要求輸入一個整數、一個字元及另一個整數,若是依順序輸入型態相符的參數, scanf() 就會回傳整數 3 。
因此我們宣告另一個變數 t 來接收 scanf() 的回傳值,若回傳值不等於 3 ,就把運算符號改為非預期的字元 '!' 。修正後的版本如下
#include <stdio.h> int main(void) { int a, b, t; //宣告需要用到的變數 char opt; printf("這個程式會依符號計算兩個整數的和、差、積、商....\n"); printf("請輸入計算式,如 2+2: "); //提示使用者輸入的文字 t = scanf("%d %c %d", &a, &opt, &b); //如果使用者輸入的除數為 0 ,將除數改為 1 if (opt == '/' && b == 0) { b = 1; } //如果使用者輸入非整數,便將 opt 改成不合法的運算符號 if (t != 3) { opt = '!'; } //以下會依運算子計算並印出結果 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/ 檔名:calculator4.c 功能:接受使用者輸入的四則運算器 作者:張凱慶 時間:西元2010年7月 */
程式改變就是多宣告變數 t ,第 11 行變數 t 接受函數 scanf() 的參數
t = scanf("%d %c %d", &a, &opt, &b);
然後第 19 行到第 21 行,檢查 t 是否不等於 3 ,若真就將 opt 設為 '!'
//如果使用者輸入非整數,便將 opt 改成不合法的運算符號 if (t != 3) { opt = '!'; }
重新編譯來測試看看吧!
嗯,目前看來,的確解決了輸入型態不符的錯誤。
問題與討論
- 為什麼要對程式進行不同輸入值的測試?
- 除了這個例子所提的語意錯誤,還有可能有怎樣的語意錯誤呢?
- 還有沒有其他防範機制呢?
- 如果都改成輸入字元,需要數字再把字元轉換成整數,這樣的作法好不好?
沒有留言:
張貼留言