• 為了應付程式可能遇到的各種狀況,C 提供了 if 條件判斷陳述。
  • 情況、情境、狀態或條件的陳述,在程式執行時,該陳述只有 正確 錯誤 成立 不成立 等非常明確的「正面或負面」兩種狀況。
  • 可能的運算結果只能有「true (真)」、「false (假)」這兩種布林值( Boolean Value)
  • 布林代數 Boolean algebra

    布林代數(Boolean algebra),具有 真 (true) 與**偽 (false) **兩種值,可用來表示是非對錯的概念。
    在程式語言中,程式流程控制的語法,例如 if for while 等,所使用的條件陳述都需要用布林代數來描述。而有趣的是, C 與 C++因為語言特性和發展時機的不同,對於該怎麼實現布林代數的想法也有所不同。

    C89 中的布林型態

  • 雖然布林代數對於 流程控制 至為重要,但在 C89 中並沒有替布林代數設計一個專有的資料型態。在 C89 中,布林代數是隱約地在多個不同的型態、不同的運算與不同的語法中實現。
  • C89 替所有內建的資料型態做了統一規定: 非 0 為真、0 為偽
  • 此外,C89 對於關係運算子與邏輯 運算子的運算結果也做了規定。
  • 當運算結果為 時會算出 int 型態的 1,當運算結果為 時會算出 int 型態的 0。
  • 這造成在 C89 容易覺得布林代數就是用 int 型態來表示。
  • 不過這是個誤解,下一頁我們來看看例子。
  • 上面的程式碼,因為 C89 的規定,所以都會被判定為 false。不會印出任何結果。

  • 0.1 直接作為布林值判定時,因為非 0 所以為真。但如果將其值轉型成 int 型態,因為值變為 0 所以判定為非。由此可知 int 型態不能完全表達布林代數的結果。
  • C89 沒有替布林代數設計專用的資料型態還造成了其他問題。例如之前提到的,因為關係與邏輯運算子的運算結果是以 int 的 1 與 0 來表示 ,因而產生了一些結果不直觀的程式碼。
  • 開始,型別名字為 _Bool
  • 另外,C99 為了讓 C 和 C++ 更相容,增加了一個標頭檔案 stdbool.h 。裡面定義了 bool true false ,讓我們可以像C++ 一樣的定義布林型別。
  • _Bool 型別不需要引用其他庫函式,直接就可以使用。而 bool 型別,則需要 #include <stdbool.h>

    switch statement

  • switch 是 C 語言提供的另一種條件判斷方式,本身只能比較 數值 或是 字元
  • 但是,使用得當的話,或許會比 if 判斷式還要來得有效率。
  • Syntax:
  • switch (expression)
        case constant1:
          statements1;
          break;
        case constant2:
          statements2
          break;
        default: 
          default statements;
    

    首先,會先看看 switch 括號裡的 expression,取得 expression 的數值(或字元)之後,會一一與 case 設定的數字(或字元)比較,若符合,就會執行以下之 statement,直到遇到 breaks 後離開 switch 區塊(block)。若都沒有符合得數值(或字元),就會執行 default 裡的 statementsdefault 可省略。

    switch statement flow chart

    範例一:BMI 計算

    使用者輸入身高、體重,計算 BMI 值。
    若 BMI 小於 18.5,顯示***過輕***。
    若 BMI 介於 18.5 到 24 之間,顯示***體重正常***。
    大於 24,則顯示***過胖***。

    #include <stdio.h>
    #include <stdlib.h>
    int main()
        float bmi, w, h; // declare in floating type
        printf("Enter your weight(kg) and height(cm):\n");
        scanf("%f %f", &w, &h);
        bmi = w / ((h/100)*(h/100));
        printf("BMI = %f\n\n", bmi);
        if(bmi<=18.5){
            printf("Underweight.\n");
        }else if(bmi>18.5 && bmi <= 24){
            printf("Normal!\n");
        }else{
            printf("Overweight!\n");
        system("PAUSE");
        return 0;
    

    範例二:生肖

    已知 2021 年為牛年,設計一程式,從今年推算輸入年分之生肖為何?

    #include <stdio.h>
    #include <stdlib.h>
    int main()
        int year;
        printf("Please input a year: ");
        scanf("%d", &year);
        int this_year = 2021 % 12; // 2021 % 12 為牛年
        switch((year%12)-this_year){
            case 0:
                printf("%d 年為牛年", year);
                break;
            case 1:
                printf("%d 年為虎年", year);
                break;
            case 2:
                printf("%d 年為兔年", year);
                break;
            case 3:
                printf("%d 年為龍年", year);
                break;
            case 4:
                printf("%d 年為蛇年", year);
                break;
            case 5:
                printf("%d 年為馬年", year);
                break;
            case 6:
                printf("%d 年為羊年", year);
                break;
            case -5:
                printf("%d 年為猴年", year);
                break;
            case -4:
                printf("%d 年為雞年", year);
                break;
            case -3:
                printf("%d 年為狗年", year);
                break;
            case -2:
                printf("%d 年為豬年", year);
                break;
            case -1:
                printf("%d 年為鼠年", year);
                break;
        printf("\n\n");
        system("PAUSE");
        return 0;
    

    範例三:計算折扣

    某百貨正在舉行周年慶。顧客購物金額折扣如下:

  • 1,000(含) 以上:打 9 折
  • 5,000(含) 以上:打 8 折
  • 8,000(含) 以上:打 65 折
  • 10,000(含) 以上:打 3 折
  • 請設計一程式,使用者輸入購物金額,並在螢幕顯示出

  • 可享的折扣
  • 折扣後的金額
  • 總共省下多少錢
  • #include <stdio.h>
    #include <stdlib.h>
    int main()
        int price, account;
        printf("Enter a price: ");
        scanf("%d", &price);
        if(price >= 10000){
            account = price * 30 / 100;
            printf("打 3 折\n");
        }else if(price >= 8000){
            account = price * 0.65;
            printf("打 65 折\n");
        }else if(price >= 5000){
            account = price * 0.8;
            printf("打 8 折\n");
        }else if(price >= 1000){
            account = price * 0.9;
            printf("打 9 折\n");
        }else{
            account = price;
            printf("沒有折扣\n");
        printf("折扣後的金額為 %d\n", account);
        printf("總共省下 %d\n\n", price-account);
        system("PAUSE");
        return 0;
    

    迴圈敘述句 Loop Statement

  • 在程式裡,迴圈(loop)是用來重複執行同一個區塊(block)。
  • 會在某一個特別設定的條件下跳出迴圈。
  • 在 C語言裡,總共有三種不同的迴圈敘述句,分別為: for loop (前測式)
  • while loop (前測式) do…while loop (後測式)
  • 之後,我們會分別介紹這三種不同的 statement。
  • for loop flow chart

    for loop 步驟:

  • 執行 initialization statement,而且只會執行一次,此步驟為設定變數初值。
  • 執行 test expression,判定變數是否為真。
  • 如果為真 True,程式會進入迴圈裡的 statement,之後會執行 update statement,更新參數。
  • 開始重複第二步驟。直到判定為否 False。
  • 判定為否,則會跳出迴圈區塊,執行迴圈外的 statement。
  • for(initialization_Statement; test_Expression; update_State){
        // statements inside the body of loop
    

    while loop flow chart

    while loop 執行步驟:

  • 執行 test expression,判定變數是否為真。
  • 如果判定為否,則跳過迴圈裡的 statement,直接結束迴圈。
  • 如果為真,執行迴圈裡的 statement。
  • 執行完畢,跳回第一步,直到判定變數為否。
  • while(test_Expression){
        // the body of loop
    

    do...while loop flow chart

    兩種不同 while 迴圈

  • 這兩種 while loop 差別在於前測式與後測式迴圈:
  • 前測式迴圈:先測試迴圈變數是否符合迴圈終止條件。
  • 後測式迴圈:先執行迴圈本體一次,再測試迴圈變數是否符合終止條件。
  • 兩者的差異在於 do…while 後測式迴圈至少執行一次。
  • 要使用哪一種結構是看程式功能需求,如:帳號密碼登入功能至少要讓使用者輸入一次帳號密碼,再確認帳號密碼是否正確,就可以使用後測式迴圈結構。
  • 怎麼表示是非對錯 ? 在 C 與 C++ 中布林 (Boolean) 型態的演進 (二) : C++98 switch 條件判斷

    範例四:總和計算

    請設計一程式,使用者輸入一正整數,並顯示 1 + 2 + … + N 的總和。
    如:輸入 9 ,結果為 1~9 的總和。

    #include <stdio.h>
    #include <stdlib.h>
    int main()
        int n, sum=0;
        printf("Enter a number: ");
        scanf("%d", &n);
        for(int i=1; i <= n; i++){
            sum += i;
        printf("Summary of 1 ~ %d = %d\n\n", n, sum);
        system("PAUSE");
        return 0;
    

    範例五:猜大小

    猜大小遊戲(high or low),由電腦想定一個數字(1-1000),人來猜電腦想定的數。每人每次猜一個數,電腦則會回答:<答對> <太大> <太小>。
    答對後在螢幕顯示猜了幾次才猜到正確答案。

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    void main()
        int answer, n, count = 0;
        srand( time(NULL) ); // 設定亂數種子
        answer = (rand() % 1000) + 1; // 比較常寫成這種模式 (rand()%(max-min+1))+min
        /**while 寫法**/
        /*while(1){ // while(1) 代表無限迴圈,但是切記,一定要設停止迴圈的機制
            printf("Enter your Answer: ");
            scanf("%d", &n);
            count++;
            if(n == answer){
                printf("CONGRA!\n\n");
                break;  // 跳出迴圈,也就是停止無限迴圈的機制
            }else if(n < answer){
                printf("Higher\n\n");
            }else{
                printf("Lower\n\n");
        /**do while 寫法**/
            printf("Enter your answer: ");
            scanf("%d", &n);
            count++;
            if(n < answer){
                printf("Higher\n\n");
            }else if(n > answer){
                printf("Lower\n\n");
            }else{
                printf("Congra!\n\n");
        }while(n != answer);
        printf("第 %d 次猜到結果\n", count);
    

    補充:產生亂數

    C 語言的 stdlib.h 函式庫裡提供了 rand() 函式來產生亂數。
    不過因為 rand() 函式是由它上一個數值來產出下一個亂數,如果不做任何設定,初值系統都預設為 0。
    因此這個時候我們可以用 srand() 函式來改變一開始的亂數值(一樣定義在 stdlib.h),srand() 需要一個參數作為 seed(種子)。
    通常我們會已目前的時間當作亂數種子,使用 time() 函式,而 time() 定義在 time.h 函式庫裡。

    可以參考以下範例

    #include <stdio.h>
    #include <stdlib.h> //亂數相關函數
    #include <time.h>
    void main() // 把 main function 改成 void 就可以省掉最後的 return 0
        /** 第一種亂數範例 **/
        // 先設定亂數種子
        srand( time(NULL) ); //srand定義在stdlib裡,用現在時間當作亂數種子
        // 產生亂數
        int x = rand();
        printf("產生亂數 (基本)\n");
        printf("x= %d\n", x);
        /* 這個範例產生的亂數是一個整數,值介於 0~RAND_MAX 之間
        不同系統定義的 RAND_MAX 有不同大小 */
        printf("======\n");
        system("PAUSE");
        printf("\n");
        // show RAND_MAX
        printf("RAND_MAX = %d\n", RAND_MAX); // RAND_MAX 32767
        /* This is completely useless to us. */
        printf("======\n");
        system("PAUSE");
        printf("\n");
        /** 第二種亂數範例 - 特定範圍整數亂數 **/
        // 指定亂數範圍
        int min = 1;
        int max = 100;
        // 產生 [min, max] 的整數亂數, min <= x <= max
        int y = rand() % (max - min + 1) + min;
        printf("產生特定範圍整數亂數,範圍:[%d,%d]\n", min, max);
        printf("y = %d\n", y);
        printf("======\n");
        system("PAUSE");
        printf("\n");
        /** 第三種亂數範例 - [0,1) 浮點數亂數, 0 <= x < 1 **/
        double z = (double) rand() / (RAND_MAX + 1.0);
        printf("產生 [0,1) 範圍浮點數亂數\n");
        printf("z = %f\n", z);
        printf("======\n");
        system("PAUSE");
        printf("\n");
        /** 第四種亂數範例 - [min,max) 浮點數亂數, min <= x < max **/
        double min_float = 3.6;
        double max_float = 8.7;
        double w = (max_float-min_float) * rand() / (RAND_MAX + 1.0) + min;
        printf("產生特定範圍浮點數亂數,範圍:[%.2f,%.2f)\n", min_float, max_float);
        printf("w = %f\n", w);
        printf("======\n");
        system("PAUSE");
        printf("\n");
    
    產生亂數 (基本)
    x= 26378
    ======
    請按任意鍵繼續 . . .
    RAND_MAX = 32767
    ======
    請按任意鍵繼續 . . .
    產生特定範圍整數亂數,範圍:[1,100]
    y = 84
    ======
    請按任意鍵繼續 . . .
    產生 [0,1) 範圍浮點數亂數
    z = 0.412872
    ======
    請按任意鍵繼續 . . .
    產生特定範圍浮點數亂數,範圍:[3.60,8.70)
    w = 1.801700
    ======
    請按任意鍵繼續 . . .
    Process returned 10 (0xA)   execution time : 4.756 s
    Press any key to continue.
    

    範例六:作圖

    請設計一程式,由使用者輸入一整數,螢幕顯示如下:

    Input
    Output
    Input
    Output
    *****
    #include <stdio.h>
    #include <stdlib.h>
    void main()
        int i, j, num;
        scanf("%d", &num);
        printf("\n");
        for(i = 0; i < num; i++){
            for(j = 0; j <= i; j++){
                printf("*");
            printf("\n");