🛡️

身份验证

答对题目即可进入,验证你是谁

剩余尝试次数:3

条件判断 — if/else 与 switch

C语言学习教程

条件判断 — if/else 与 switch

🌟 生活中的”条件判断”

想象你早上出门前看天气:

这就是条件判断——根据不同情况做不同的事。程序也是一样,它不可能永远”一条路走到黑”。用户输入的密码对不对?分数及不及格?余额够不够付款?每一个”岔路口”都需要条件判断来决定程序走向。

一句话总结:条件判断让程序有了”选择”的能力。没有条件判断,程序只能机械地从上到下顺序执行,什么”智能”都谈不上。


📖 概念详解 — 程序从哪里开始分岔?

条件判断的本质

在 C 语言中,条件判断围绕一个核心规则展开:

0 表示”假”(false),非 0 表示”真”(true)

if (条件表达式) {
    // 条件为真(非 0)时执行这里的代码
}

C 语言没有真正的 true/false 关键字(C99 引入了 stdbool.h,但底层仍然是 0 和 1)。理解这一点至关重要,因为很多”奇怪”的 bug 都和真假判断有关。

完整流程图

                  ┌──────────────┐
                  │  程序执行到   │
                  │  if 语句前   │
                  └──────┬───────┘


                  ┌──────────────┐
                  │  计算条件     │
                  │  表达式的值   │
                  └──────┬───────┘

                    ┌────┴────┐
                    │ 是真的?  │
                    └────┬────┘
                    是 ╱   ╲ 否
                      ▼      ▼
              ┌──────────┐  ┌──────────┐
              │ 执行 if   │  │ 跳过 if  │
              │ 块内代码  │  │ 块内代码  │
              └────┬─────┘  └────┬─────┘
                   │              │
                   ▼              ▼
              ┌──────────────────────┐
              │   继续执行 if 之后    │
              │   的代码(汇合点)    │
              └──────────────────────┘

if-else if-else 流程

                    ┌──────────┐
                    │  条件 1  │
                    └────┬─────┘
                  真 ╱   ╲ 假
                     ▼     ▼
                ┌──────┐  ┌──────────┐
                │代码块1│  │  条件 2   │
                └──┬───┘  └────┬─────┘
                   │       真 ╱   ╲ 假
                   │          ▼     ▼
                   │     ┌──────┐  ┌──────────┐
                   │     │代码块2│  │  条件 3   │
                   │     └──┬───┘  └────┬─────┘
                   │        │       真 ╱   ╲ 假
                   │        │          ▼     ▼
                   │        │     ┌──────┐  ┌──────┐
                   │        │     │代码块3│  │ else  │
                   │        │     └──┬───┘  │代码块 │
                   │        │        │      └───┬───┘
                   ▼        ▼        ▼          ▼
              ┌────────────────────────────────────┐
              │   所有分支最终都到这里(汇合点)     │
              └────────────────────────────────────┘

关键点:从上到下检查,第一个为真的条件执行后,剩余分支全部跳过。 这是一个”胜利者通吃”的机制。


💻 代码示例 — 从简单到复杂

示例 1:最简单的 if(单分支)

#include <stdio.h>

int main() {
    int score = 85;

    // 只有一个分支:及格了才打印
    if (score >= 60) {
        printf("恭喜,你及格了!\n");
    }

    // 这行无论及不及格都会执行
    printf("程序结束。\n");
    return 0;
}

运行结果

恭喜,你及格了!
程序结束。

如果 score = 55

程序结束。

花括号 {} 只在代码块超过一行时必须写。但强烈建议始终写花括号,这是无数 bug 换来的教训。


示例 2:if-else(双分支)

#include <stdio.h>

int main() {
    int temperature = 38;

    if (temperature > 37) {
        printf("你发烧了,体温 %.1f°C\n", (float)temperature);
        printf("建议去看医生。\n");
    } else {
        printf("体温正常:%d°C\n", temperature);
        printf("保持健康!\n");
    }

    return 0;
}

if-else 是互斥的:要么执行 if,要么执行 else,不可能两者都执行


示例 3:if-else if-else(多分支 — 成绩等级)

#include <stdio.h>

int main() {
    int score;

    printf("请输入成绩 (0-100): ");
    scanf("%d", &score);

    // 注意条件顺序:从高到低写
    if (score >= 90 && score <= 100) {
        printf("等级:A(优秀)\n");
        printf("评语:继续保持,你很棒!\n");
    } else if (score >= 80) {
        // 能到这里说明 score < 90,所以只需判断 >= 80
        printf("等级:B(良好)\n");
        printf("评语:不错,还有进步空间。\n");
    } else if (score >= 70) {
        printf("等级:C(中等)\n");
        printf("评语:基础掌握了,继续加油。\n");
    } else if (score >= 60) {
        printf("等级:D(及格)\n");
        printf("评语:勉强过关,需要多练习。\n");
    } else if (score >= 0) {
        printf("等级:F(不及格)\n");
        printf("评语:不要灰心,找到薄弱点再攻破。\n");
    } else {
        // 小于 0 的无效输入
        printf("输入错误!成绩不能为负数。\n");
    }

    return 0;
}

重点讲解

  1. 条件从上到下”逐级过滤”。到了 else if (score >= 80) 时,已经确定 score < 90,所以不需要写成 score >= 80 && score < 90
  2. 条件顺序很重要——如果先写 >= 60,后面的条件永远不会匹配!
  3. else 是”兜底”分支,所有不满足前面条件的情况都会掉到这里。

示例 4:嵌套 if(多条件组合 — 网吧入场判断)

#include <stdio.h>

int main() {
    int age;
    int hasIdCard;      // 1 = 有身份证, 0 = 没有
    int isVip;          // 1 = 会员, 0 = 非会员

    printf("请输入年龄: ");
    scanf("%d", &age);
    printf("有身份证吗?(1=有, 0=没有): ");
    scanf("%d", &hasIdCard);
    printf("是会员吗?(1=是, 0=不是): ");
    scanf("%d", &isVip);

    if (age >= 18) {
        // 成年人:检查身份证
        if (hasIdCard) {
            printf("✅ 允许进入。\n");
            // 进一步检查是否会员
            if (isVip) {
                printf("   尊贵会员,请上二楼包厢。\n");
            } else {
                printf("   普通用户,请在一楼大厅。\n");
            }
        } else {
            printf("❌ 请出示身份证。\n");
        }
    } else {
        // 未成年人
        printf("❌ 未满18岁,禁止进入网吧。\n");
        printf("   请在监护人陪同下使用电脑。\n");
    }

    return 0;
}

嵌套 if 要点


示例 5:三元运算符(一行写完的 if-else)

#include <stdio.h>

int main() {
    int a = 10, b = 20;

    // 常规写法
    int max;
    if (a > b) {
        max = a;
    } else {
        max = b;
    }
    printf("(常规) 较大值是: %d\n", max);

    // 三元运算符写法:条件 ? 真时的值 : 假时的值
    int max2 = (a > b) ? a : b;
    printf("(三元) 较大值是: %d\n", max2);

    // 三元运算符也可以嵌套(但不建议太复杂)
    int c = 30;
    int max3 = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
    printf("三者中最大是: %d\n", max3);

    // 实战用法:奇偶判断
    int num = 7;
    printf("%d%s\n", num, (num % 2 == 0) ? "偶数" : "奇数");

    return 0;
}

使用建议:三元运算符适合简单的”二选一赋值”,不要把大段逻辑塞进去,否则代码将非常难读。


示例 6:switch-case(多值精确匹配 — 简易计算器)

#include <stdio.h>

int main() {
    char operator;
    double num1, num2, result;

    printf("简易计算器\n");
    printf("请输入算式 (如: 5 + 3): ");
    scanf("%lf %c %lf", &num1, &operator, &num2);

    switch (operator) {
        case '+':
            result = num1 + num2;
            printf("%.2f + %.2f = %.2f\n", num1, num2, result);
            break;

        case '-':
            result = num1 - num2;
            printf("%.2f - %.2f = %.2f\n", num1, num2, result);
            break;

        case '*':
        case 'x':
        case 'X':
            // 三种输入方式都当作乘法(* 或 x 或 X)
            result = num1 * num2;
            printf("%.2f × %.2f = %.2f\n", num1, num2, result);
            break;

        case '/':
            if (num2 != 0) {
                result = num1 / num2;
                printf("%.2f / %.2f = %.2f\n", num1, num2, result);
            } else {
                printf("错误:除数不能为 0!\n");
            }
            break;

        default:
            printf("不支持的运算符:%c\n", operator);
            printf("支持的运算符:+ - * /\n");
    }

    return 0;
}

switch 要点

多个 case 合并case '*': case 'x': case 'X': 三个标签共享同一段代码,一个 break 统一跳出。


⚠️ 常见错误 — 这些都是血泪教训

错误 1:if 后面多了分号(空语句陷阱)

错误写法正确写法
if (x > 0); ← 分号结束了 if!if (x > 0)
printf("正数\n"); ← 永远执行 printf("正数\n");
// ❌ 错误演示
int x = -5;
if (x > 0);                    // 分号 = 空语句,if 什么都不做
    printf("x 是正数\n");      // 这行跟 if 没关系,永远执行!

// 输出:x 是正数(明明 x = -5!)

// ✅ 正确写法
int x = -5;
if (x > 0)                     // 没有分号
    printf("x 是正数\n");      // 只有 x > 0 时才执行

// 输出:(无输出,正确!)

原理:在 C 语言中,单独一个分号 ; 是一条合法语句(空语句,什么也不做)。if (x > 0); 的意思是”如果 x > 0,执行空语句”,然后 printf(...) 跟 if 毫无关系。这可能是 C 语言中最隐蔽的 bug 之一。


错误 2:赋值 = 和比较 == 混淆

错误写法正确写法
if (x = 5) ← 赋值,不是比较if (x == 5) ← 这才是比较
// ❌ 错误演示
int x = 3;
if (x = 5) {                   // 把 5 赋给 x,然后判断 x(5 非 0 = 真)
    printf("相等\n");          // 永远会打印!
}
printf("x = %d\n", x);         // x 变成了 5!
// 输出:相等
//       x = 5

// ✅ 正确写法
int x = 3;
if (x == 5) {                  // 判断 x 是否等于 5
    printf("相等\n");          // 不执行,因为 3 != 5
}
printf("x = %d\n", x);         // x 还是 3
// 输出:x = 3

防御技巧:将常量写在左边 — if (5 == x)。如果误写成 if (5 = x),编译器会报错(因为不能给常量赋值),帮你提前发现 bug。


错误 3:字符串不能用 == 比较

错误写法正确写法
if (name == "Tom")if (strcmp(name, "Tom") == 0)
#include <stdio.h>
#include <string.h>

int main() {
    char name[20];
    printf("请输入名字: ");
    scanf("%s", name);

    // ❌ 错误:比较的是内存地址,不是内容
    if (name == "Tom") {
        printf("错误的比较方式\n");
    }

    // ✅ 正确:使用 strcmp 函数
    if (strcmp(name, "Tom") == 0) {
        printf("Hello, Tom!\n");
    } else {
        printf("你不是 Tom\n");
    }

    return 0;
}

原理:C 语言中,数组名(如 name)代表数组首地址。name == "Tom" 比较的是两个地址是否相同,而不是字符串内容是否相等。必须用 <string.h> 中的 strcmp() 函数。


错误 4:switch 忘记 break(穿透 bug)

// ❌ 错误演示
int day = 1;
switch (day) {
    case 1:
        printf("Monday\n");     // 没有 break!
    case 2:
        printf("Tuesday\n");    // 也会执行!
    case 3:
        printf("Wednesday\n");  // 也会执行!
}
// 输出:Monday
//       Tuesday
//       Wednesday
// 竟然输出了三行!

// ✅ 正确写法
int day = 1;
switch (day) {
    case 1:
        printf("Monday\n");
        break;                  // 必须有 break
    case 2:
        printf("Tuesday\n");
        break;
    case 3:
        printf("Wednesday\n");
        break;
}
// 输出:Monday (仅一行)

什么时候可以不写 break? 当你确实需要多个 case 共享同一段代码时(比如上面的计算器中 case '*': case 'x': case 'X':)。


错误 5:复合条件没有用括号

// ❌ 不好读,容易出错
if (age >= 18 && hasIdCard || isVip)  // 运算符优先级是什么?
    printf("允许进入\n");

// ✅ 用括号明确逻辑
if ((age >= 18 && hasIdCard) || isVip)
    printf("允许进入\n");

优先级&& 优先于 ||,但不要依赖记忆——加括号,让意图一目了然


💡 练习建议

  1. 从纸上开始:在写代码前,用笔画出流程图。搞清楚”先判断什么、再判断什么”,代码自然水到渠成。
  2. 测试边界值:写完成绩判断程序后,分别输入 -1、0、59、60、89、90、100、101 测试,确保每个边界都正确。
  3. 故意犯错:故意在 if 后加分号,或忘记 break,或把 == 写成 =,看看程序会怎么”歪”。理解 bug 比写出正确代码更有价值。
  4. 改写练习:把一个 if-else 改成 switch(如果可以的话),再改回来。体会两种结构各自适合什么场景。
  5. 多条件拆解:复杂条件不要写一行。拆成多个 if,用变量存中间结果,代码可读性会大幅提升。

📝 要点速查

要点说明
if (条件) { }条件为真(非 0)时执行,为假(0)时跳过
else与最近的 if 配对,条件不成立时执行
else if链式多分支,从上到下匹配,命中后跳过后续
switch(v)适合判断一个整数变量的多个具体值
break在 switch 中阻止”穿透”
defaultswitch 的”兜底”分支(可选但建议写)
三元 ? :简单二选一的简写,不要嵌套过深
= vs ==赋值 vs 比较,C 语言头号陷阱
strcmp()字符串比较必须用函数,不能用 ==

🔗 相关主题