首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言核心筆記(六):選擇結構深度解析——if、switch 與巢狀分支實戰

     編輯:關於C

選擇結構概覽

C 語言提供兩大分支機制:if 系列(條件靈活、支援任意表達式)與 switch(整數/字元等值匹配、跳轉表優化)。掌握其語法細節、巢狀規則與典型應用模式,是寫出清晰邏輯的關鍵。

1. if 語句:從單分支到多路選擇

1.1 單條件單分支

if (表達式) {
    語句序列;
}
// 後續程式碼

表達式非 0 → 執行大括號內語句;為 0 → 直接跳過。大括號可省略(單語句),但**強烈建議保留**以防維護時誤增行導致邏輯錯誤。

範例:及格判斷

double score;
scanf("%lf", &score);
if (score >= 60)
    printf("Pass!\n");
printf("Program over.\n"); // 無論及格與否都執行

1.2 單條件雙分支

if (表達式) {
    語句A;
} else {
    語句B;
}

非 0 執行 A,為 0 執行 B,二者必居其一。

範例:及格/不及格

if (score >= 60)
    printf("Pass!\n");
else
    printf("Fail!\n");

2. 巢狀 if 與 else-if 階梯

2.1 兩種常見格式


// 格式一:標準 else-if 階梯(推薦)
if (expr1) { ... }
else if (expr2) { ... }
else if (expr3) { ... }
else { ... }

// 格式二:省略大括號的緊湊寫法(單語句時可用)
if (expr1) stmt1;
else if (expr2) stmt2;
else stmt3;

2.2 實戰:判斷整數位數


int a; scanf("%d", &a);
int abs_a = abs(a); // 需 #include 

if (abs_a < 10)       printf("%d is 1 digit\n", a);
else if (abs_a < 100) printf("%d is 2 digits\n", a);
else if (abs_a < 1000) printf("%d is 3 digits\n", a);
else if (abs_a < 10000) printf("%d is 4 digits\n", a);
else if (abs_a < 32767) printf("%d is 5 digits\n", a);
else                  printf("Number too large\n");

條件**互斥且有序**,自上而下首次匹配即執行,效率與可讀性俱佳。

2.3 經典陷阱:dangling else


if (a > 0)
    if (b > 0) printf("A");
else printf("B"); // else 配對給最近的 if (b>0)!

規則:`else` 永遠與**最近的未配對 `if`** 綁定。務必用大括號明確界定作用域:


if (a > 0) {
    if (b > 0) printf("A");
} else {
    printf("B"); // 明確屬於外層 if
}

3. switch 分支:整數/字元的高效匹配

3.1 語法結構


switch (表達式) {
    case 常量表達式1: 語句; break;
    case 常量表達式2: 語句; break;
    ...
    default: 語句; // 可選
}
  • 表達式結果必為**整型或字元型**(隱式轉換)。
  • `case` 標籤必須為**編譯期常量**(不可為變數)。
  • `break` 缺失會導致**貫穿**,繼續執行下一 `case`。

3.2 執行流程

  1. 計算 switch 表達式值
  2. 自上而下比對 `case` 常量
  3. 匹配 → 進入該 `case` 後語句
  4. 遇 `break` → 跳出 switch;無 `break` → 繼續往下執行
  5. 全不匹配 → 執行 `default`(若有)

3.3 實戰:分數等級轉換


int score; scanf("%d", &score);
switch (score / 10) { // 整數除法自動截斷
    case 10:
    case 9:  printf("Grade A\n"); break;
    case 8:  printf("Grade B\n"); break;
    case 7:  printf("Grade C\n"); break;
    case 6:  printf("Grade D\n"); break;
    default: printf("Grade E\n");
}

利用**多 case 共用代碼**(`case 10: case 9:`)簡化區間判斷。

3.4 switch 巢狀與 break 作用域


switch (n1) {
    case 1:
        switch (n2) { // 內層 switch
            case 11: ...; break; // 僅跳出內層
        }
        break; // 外層需自行 break
    case 2: ...;
}

`break` **僅跳出它所在的最內層 switch/迴圈**。

4. 綜合實戰案例

4.1 判斷閏年


int year; scanf("%d", &year);
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    printf("Leap year\n");
else
    printf("Common year\n");

邏輯:能被 4 整除且非整百年,或能被 400 整除。

4.2 計算某年某月某日是當年第幾天


int y, m, d, sum = 0;
scanf("%d%d%d", &y, &m, &d);

switch (m) { // 累加前 m-1 月天數
    case 12: sum += 30;
    case 11: sum += 31;
    case 10: sum += 30;
    case 9:  sum += 31;
    case 8:  sum += 31;
    case 7:  sum += 30;
    case 6:  sum += 31;
    case 5:  sum += 30;
    case 4:  sum += 31;
    case 3:  sum += 28;
    case 2:  sum += 31;
    case 1:  break; // 無需加
}
sum += d; // 加上當月天數

// 閏年且月份>2,補一天
if ((y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) && m > 2)
    sum++;

printf("Day of year: %d\n", sum);

技巧:`switch` **故意省略 `break` 實現累加**(貫穿特性),從 12 月倒序加到輸入月份前一月,代碼極度緊湊。

5. if-else vs switch 選擇指南

場景推薦理由
區間判斷、浮點比較、複雜邏輯表達式if-elseswitch 僅支援整數常量等值匹配
多固定值匹配(選單、狀態碼、字元指令)switch編譯器優化為跳轉表,O(1) 查找;碼可讀性高
少量分支(2-3 條)if-else無顯著效能差異,if 更靈活
需範圍判斷但值為整數if-else 或 switch+技巧如分數等級可用 switch(score/10)

6. 常見錯誤與避坑清單

  • ❌ `if (a = 5)` 賦值而非比較 → 改用 `if (5 == a)` 習慣(編譯器會報錯)
  • ❌ `switch` 表達式用 `float`/`double`/`string` → 僅限整數類型
  • ❌ `case` 使用變數或區間 → 必須為常量
  • ❌ 忘記 `break` 導致非預期貫穿 → 若故意貫穿需加註解 `/* fall through */`
  • ❌ 巢狀 `if` 缺少大括號導致 `else` 配對錯誤 → 永遠加大括號

總結

選擇結構是程式決策的核心。if-else 以靈活著稱,處理範圍、複雜條件;switch 以高效著稱,處理離散值匹配。實戰中常混合使用:外層 `switch` 分發命令類型,內層 `if` 處理參數驗證。養成「加大括號、防貫穿、查類型」三部曲,能消除 90% 分支相關 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved