1. 程式人生 > >8. C 語言 -- 分支結構: switch 和 break 語句

8. C 語言 -- 分支結構: switch 和 break 語句

本部落格主要內容為 “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】 學習筆記,文章的主題內容均來自該課程,在這裡僅作學習交流。在文章中可能出現一些錯誤或者不準確的地方,如發現請積極指出,十分感謝。
也歡迎大家一起討論交流,如果你覺得這篇文章對你有所幫助,記得評論、點贊哦 ~(。・∀・)ノ゙

1. switch 和 break 語句

  處理多分支結構,可以考慮使用語法更簡便的 switch 語句,如下所示

…… // 其它語句
switch (表示式)
{
    case 常量表達式1: 語句或程式塊
    case 常量表達式2: 語句或程式塊
    ……
    case
常量表達式n:語句或程式塊 default: 語句或程式塊 } …… // 其它語句

這裡每個 case 後邊的常量是匹配 switch 後邊表示式的值,case 後邊必須跟一個常量值,而不能是一個範圍,如果所有的 case 均沒有匹配的,那麼執行 default 的內容,default 是可選的,如果沒有 default,並且所有的 case 均不匹配,那麼 switch 語句不執行任何動作。它與 if else 相比的好處在於它更簡潔,會少些很多的大括號。

  但是直接像上面那麼書寫程式是容易出現問題的,因為switch 語句中的 case 和 default 事實上都是“標籤”,用來標誌一個位置而已。當 switch 跳到某個位置之後,就會一直往下執行,比如說它滿足了 case 常量表達式1

的要求之後會自動執行剩下的所有的語句和程式塊,而無需判斷是否滿足前面所對應的 case 。所以如果只希執行某一個 case 後面的語句和程式塊,還需要配合一個 break 語句,讓程式碼在適當的位置跳出 switch,即如下所示

…… // 其它語句
switch (表示式)
{
    case 常量表達式1: 語句或程式塊1;  break;
    case 常量表達式2: 語句或程式塊2;  break;
    ……
    case 常量表達式n:語句或程式塊n;  break;
    default: 語句或程式塊n+1;  break; 
}
…… // 其它語句

1.1 舉例說明

  下面的例子實現了一個功能,輸入成績的評定結果(A,B,C)中的一個,返回其所對應的分數區間

#include <stdio.h>

int main()
{
	char ch;

	printf("請輸入成績:");
	scanf("%c", &ch);

	switch (ch){
		case 'A': printf("你的成績在90分以上!\n"); break;
		case 'B': printf("你的成績在80~90分之間!\n"); break;
		case 'C':printf("你的成績在60分以下!\n"); break;
		default: printf("請輸入有效的成績評級!\n"); break;
	}

	return 0;
}

如果我們假定我們輸出的是 B,程式輸出的結果為

請輸入成績:B
你的成績在8090分之間!

2. 分支結構的巢狀

  如下圖所示,在一個 if 語句中包含另一個 if 語句,我們就稱之為 if 語句的巢狀,也叫分支結構的巢狀。

  比如說我們嘗試編寫下面的流程圖的程式

其中流程圖所代表的含義很簡單,首先判斷輸入的兩個數 a b 是否相等,相等輸出 a = b;否則判斷 a 是否大於 b,如果大於 b 的話輸出 a > b,否則輸出 a < b,具體程式如下

#include <stdio.h>

int main()
{
	int a, b;

	printf("請輸入兩個數:");
	scanf("%d %d", &a, &b);

	if (a != b){
		if (a > b){
			printf("%d > %d\n", a, b);
		}
		else{
			printf("%d < %d\n", a, b);
		}
	}
	else{
		printf("%d = %d\n", a, b);
	}

	return 0;
}

3. 懸掛else

  在 C 語言中,else 始終與距離他最近的 if 相對應,考慮如下的程式碼

……
if (x == 0)
    if (y == 0)
        error();
else
    z = x + y;
……

這段程式碼中程式設計者的本意是應該有兩種主要情況,x 等於 0 以及 x 不等於 0。對於 x 等於 0 的情形,除非 y 也等於 0(此時呼叫 error 函式),否則程式不作任何處理;對於 x 不等於 0 的情形,程式將 x 與 y 之和賦值給 z。

  然而,這段程式碼實際上所做的卻與程式設計者的意圖相去甚遠。原因在於 C 語言中有這樣的規則,else 始終與同一對括號內最近的未匹配的 if 結合。如果我們按照上面這段程式實際上被執行的邏輯來調整程式碼縮排,大致是這個樣子:

……
if (x == 0)
    if (y == 0)
        error();
    else
        z = x + y;
……

也就是說,如果 x 不等於 0,程式將不會做任何處理。如果要得到原來的例子中由程式碼縮排體現的程式設計者本意的結果,應該這樣寫:

……
if (x == 0)
{
    if (y == 0)
    {
        error();
    }
}
else
{
    z = x + y;
}
……

現在,else 與第一個 if 結合,即使它離第二個 if 更近也是如此,因為此時第二個 if 已經被括號“封裝”起來了。所以在編寫多層迴圈巢狀的程式碼的時候,建議使用 {} 將對應的部分括起來,尤其是使用習慣了python 的同學,千萬不要根據縮排來判斷 else 與那部分相對應。

4. 等於號帶來的問題

  在 C 語言中使用等號(=)作為賦值運算,使用連續兩個等號(==)作為比較運算。一般而言,賦值運算相對於比較運算出現得更頻繁,因此字元較少的 = 就被賦予了更常用的含義——賦值操作。此外,在 C 語言中賦值符號被作為一種操作符對待,因而重複進行賦值操作(如 a = b = c)可以很容易地書寫,並且賦值操作還可以被嵌入到更大的表示式中。

  但是,這種使用上的便利性可能導致一個潛在的問題:當程式設計師本意是在作比較運算時,卻可能無意中誤寫成賦值運算。比如下例,該語句本意似乎是要檢查 x 是否等於 y :

if (x = y)
    break;

而實際上是將 y 的值賦給了 x ,然後檢查該值是否為零。這樣的判斷距離我們原始想要的相差甚遠。

  雖然判斷兩個變數是否相等只能靠程式設計師本身來注意,但是判斷一個變數是否與一個常數值相等卻可以有一個叫好的防範方法。比如說我們需要判斷變數 a 的值是否等於 1,可以採用如下的寫法

if (1 == a)
{
    prinft("Yes\n");
}

如果沒有寫成判斷之是否相等,而是寫成了賦值符號,那麼一定會報錯的,因為一個常量是沒有辦法被賦值的。

參考

[1] “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】P12

歡迎大家關注我的知乎號(左側)和經常投稿的微信公眾號(右側)
在這裡插入圖片描述