switch語句用法注意事項,如何正確使用switch語句

2020-07-16 10:04:19
相對於 if 語句而言,switch 語句可以更方便地應用於多個分支的控制流程。C89 指明,一個 switch 語句最少可以支援 257 個 case 語句,而 C99 則要求至少支援 1023 個 case 語句。然而,在實際開發環境中,為了程式的可讀性與執行效率,應該盡量減少 switch 語句中的 case 語句。

除此之外,switch 語句與 if 語句不同的是,switch 語句只能夠測試是否相等,因此,case 語句後面只能是整型或字元型的常數或常數表示式;而在 if 語句中還能夠測試關係與邏輯表示式。

不要忘記在 case 語句的結尾新增 break 語句

在 switch 語句中,每個 case 語句的結尾不要忘記新增 break 語句,否則將導致多個分支重疊。當然,除非有意使多個分支重疊,這樣可以免去 break 語句。下面我們來看一個實際範例。
#include <stdio.h>
void print_week(unsigned int day);
void print_week(unsigned int day)
{
    switch(day)
    {
        case 1:
            printf("Mondayn");
            break;
        case 2:
            printf("Tuesdayn");
            break;
        case 3:
            printf("Wednesdayn");
            break;
        case 4:
            printf("Thursdayn");
            break;
        case 5:
            printf("Fridayn");
            break;
        case 6:
            printf("Saturdayn");
            break;
        case 7:
            printf("Sundayn");
            break;
        default:
            printf("errorn");
            break;
    }
}
int main (void)
{
    print_week(3);
    return 0;
}
該程式中,在 print_week 函數中通過 switch 語句實現根據數位輸出星期名稱的功能。執行程式碼,程式將輸出“Wednesday”。

現在,如果將 case 1~case 4 的 break 語句去掉,如下程式碼所示,程式會輸出什麼結果呢?
#include <stdio.h>
void print_week(unsigned int day);
void print_week(unsigned int day)
{
    switch(day)
    {
        case 1:
            printf("Mondayn");
        case 2:
            printf("Tuesdayn");
        case 3:
            printf("Wednesdayn");
        case 4:
            printf("Thursdayn");
        case 5:
            printf("Fridayn");
            break;
        case 6:
            printf("Saturdayn");
            break;
        case 7:
            printf("Sundayn");
            break;
        default:
            printf("errorn");
            break;
    }
}
int main (void)
{
    print_week(3);
    return 0;
}
執行結果為:
Wednesday
Thursday
Friday

不要忘記在 switch 語句的結尾新增 default 語句

在 switch 語句中,default 語句主要用於檢查預設情況,或者處理錯誤情況,如下面的範例程式碼所示:
default:
    printf("errorn");
    break;
如果在 switch 語句中去掉 default 語句,那麼 switch 語句將失去對預設情況與錯誤情況的處理能力。所以,奉勸大家不要偷懶,老老實實把每一種情況都用 case 語句來完成,而把真正對預設情況的處理交給 default 語句來完成。即使程式真的不需要 default 處理,也應該保留此語句:
default:
    break;
這樣做並非畫蛇添足,可以避免令人誤以為你忘記了 default 處理。

不要為了使用 case 語句而刻意構造一個變數

在實際程式設計應用中,switch 中的 case 語句應該只用於處理簡單的、容易分類的資料。如果資料並不簡單,卻為了使用 case 語句而刻意構造一個變數,那麼這種變數很容易令我們得不償失。因此應該嚴格避免這種變數,並使用 if/else 結構來處理這類程式,如下面的範例程式碼所示:
char ch = c[0];
switch (ch)
{
    case 'a':
        f1();
        break;
    case 'b':
        f2();
        break;
    case 'c':
        f3();
        break;
    default:
        break;
}
在上面的程式中,字元變數 ch 的值是取字元陣列 c[] 的第一個字元,與 case 語句中的常數值逐一進行比較。很顯然,這種方法存在一個嚴重的問題。

例如,如果字元陣列 c[] 中儲存的是“ab”字串,那麼 c[0] 會取第一個字元“a”與 case 語句進行匹配,因此會匹配到第一個 case 語句,並呼叫 f1() 函數。然而,如果字元陣列 c[] 中儲存的是其他以字元 a 開頭的字串(比如“abc”“abcd”“abcde”等),因為 c[0] 始終會取第一個字元的關係,因此它們同樣會匹配第一個 case 語句而呼叫 f1() 函數。其他的 case 語句同理。很顯然,這並不是我們想要的結果。

由此可見,當為了使用 case 語句而刻意構造一個變數時,真正的資料可能不會按照我們所希望的方式對映到 case 語句。因此,我們應該嚴格避免為了使用 case 語句而刻意構造一個變數,並使用 if/else 結構來處理這類程式,如下面的範例程式碼所示:
if(0 == strcmp("ab",c))
{
    f1();
}
else if(0 == strcmp("bc",c))
{
    f2();
}
else if(0 == strcmp("cd",c))
{
    f3();
}
else
{
}

盡量將長的 switch 語句轉換為巢狀的 switch 語句

有時候,當一個 switch 語句中包括很多個 case 語句時,為了減少比較的次數,可以把這類長 switch 語句轉為巢狀 switch 語句,即把發生頻率高的 case 語句放在一個 switch 語句中,作為巢狀 switch 語句的最外層;把發生頻率相對低的 case 語句放在另一個 switch 語句中,放置於巢狀 switch 語句的內層。

例如,下面的程式碼把發生頻率相對較低的情況放置於預設的 case 語句內。
void print_week(unsigned int day)
{
    switch(day)
    {
        case 1:
            printf("Mondayn");
            break;
        case 2:
            printf("Tuesdayn");
            break;
        case 3:
            printf("Wednesdayn");
            break;
        case 4:
            printf("Thursdayn");
            break;
        case 5:
            printf("Fridayn");
            break;
        default:
            switch(day)
            {
                case 6:
                    printf("Saturdayn");
                    break;
                case 7:
                    printf("Sundayn");
                    break;
                default:
                    printf("errorn");
                    break;
            }
    }
}
在上面的程式碼中,假設 case 6 與 case 7 不經常發生,因此將它們放置到巢狀 switch 語句的最內層。從表面看,雖然這樣損失了程式的一定可讀性,但當 case 語句很多,並且確實有些 case 語句發生的頻率比較低時,這種解決方案還是可取的。