天天看點

《編寫高品質代碼:改善c程式代碼的125個建議》——建議23:正确地使用switch語句

本節書摘來自華章計算機《編寫高品質代碼:改善c程式代碼的125個建議》一書中的第3章,建議23,作者:馬 偉 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

相對于if語句而言,switch語句可以更友善地應用于多個分支的控制流程。c89指明,一個switch語句最少可以支援257個case語句,而c99則要求至少支援1023個case語句。然而,在實際開發環境中,為了程式的可讀性與執行效率,應該盡量減少switch語句中的case語句。

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

建議23-1:不要忘記在case 語句的結尾添加break語句

在switch語句中,每個case 語句的結尾不要忘記添加break語句,否則将導緻多個分支重疊。當然,除非有意使多個分支重疊,這樣可以免去break語句。下面我們來看一個實際示例,如代碼清單3-2所示。

在代碼清單3-2中,在print_week函數中通過switch語句實作根據數字輸出星期名稱的功能。執行代碼清單3-2,程式将輸出“wednesday”。

現在,如果将case 1~case 4的break語句去掉,如代碼清單3-3所示,程式會輸出什麼結果呢?

代碼清單3-3 switch去掉break示例

在代碼清單3-3中,由于case 1~case 4缺少break語句,是以将導緻多個分支重疊,其運作結果如圖3-2所示。

《編寫高品質代碼:改善c程式代碼的125個建議》——建議23:正确地使用switch語句

圖3-2 代碼清單3-3的運作結果

建議23-2:不要忘記在switch語句的結尾添加default語句

在switch語句中,default 語句主要用于檢查預設情況,或者處理錯誤情況,如下面的示例代碼所示:

如果在switch語句中去掉default 語句,那麼switch語句将失去對預設情況與錯誤情況的處理能力。是以,奉勸大家不要偷懶,老老實實把每一種情況都用case 語句來完成,而把真正對預設情況的處理交給default 語句來完成。即使程式真的不需要default 處理,也應該保留此語句:

這樣做并非畫蛇添足,可以避免令人誤以為你忘記了default處理。

建議23-3:不要為了使用case 語句而刻意構造一個變量

在實際程式設計應用中,switch中的case 語句應該隻用于處理簡單的、容易分類的資料。如果資料并不簡單,卻為了使用case 語句而刻意構造一個變量,那麼這種變量很容易令我們得不償失。是以應該嚴格避免這種變量,并使用if/else if/else結構來處理這類程式,如下面的示例代碼所示:

在上面的程式中,字元變量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/else結構來處理這類程式,如下面的示例代碼所示:

建議23-4:盡量将長的switch語句轉換為嵌套的switch語句

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

例如,下面的代碼把發生頻率相對較低的情況放置于預設的case語句内。

在上面的代碼中,假設case 6與case 7不經常發生,是以将它們放置到嵌套switch語句的最内層。從表面看,雖然這樣損失了程式的一定可讀性,但當case語句很多,并且确實有些case語句發生的頻率比較低時,這種解決方案還是可取的。

繼續閱讀