流程控制条件语句

在C语言中,程序默认按照代码书写顺序从上到下依次执行。但实际应用中,我们常常需要根据条件的不同执行不同的代码块,这就是条件语句的作用。 条件语句是流程控制的重要组成部分,主要包括if语句、if-else语句、else-if阶梯以及switch语句。 掌握这些结构,可以让你的程序具备决策能力。

🔹 if 语句

if语句是最简单的条件判断结构,当条件为真(非0)时执行指定代码块,否则跳过。

语法:

if (条件表达式) {
    // 条件为真时执行的语句
}

如果代码块只有一条语句,花括号可以省略,但建议始终加上,以避免混淆。

📝 示例:判断成绩是否及格

#include <stdio.h>

int main() {
    int score;
    printf("请输入成绩: ");
    scanf("%d", &score);

    if (score >= 60) {
        printf("恭喜,及格了!\n");
    }

    return 0;
}
注意: C语言中任何非零值都被视为“真”,零被视为“假”。所以条件可以是 if (a) 等价于 if (a != 0)

🔹 if-else 语句

if-else在条件为真时执行一个分支,为假时执行另一个分支。

if (条件) {
    // 条件为真时执行
} else {
    // 条件为假时执行
}

📝 示例:判断奇偶性

#include <stdio.h>

int main() {
    int num;
    printf("请输入一个整数: ");
    scanf("%d", &num);

    if (num % 2 == 0) {
        printf("%d 是偶数\n", num);
    } else {
        printf("%d 是奇数\n", num);
    }
    return 0;
}

🔹 else-if 多分支结构

当有多个互斥的条件需要判断时,可以使用if-else if-else阶梯结构。

if (条件1) {
    // 条件1为真
} else if (条件2) {
    // 条件1为假且条件2为真
} else if (条件3) {
    // 前面条件都为假且条件3为真
} else {
    // 所有条件都为假
}

📝 示例:成绩等级评定

#include <stdio.h>

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

    if (score >= 90) {
        printf("等级: A\n");
    } else if (score >= 80) {
        printf("等级: B\n");
    } else if (score >= 70) {
        printf("等级: C\n");
    } else if (score >= 60) {
        printf("等级: D\n");
    } else {
        printf("等级: F\n");
    }
    return 0;
}
注意:else-if结构中,条件是从上到下依次判断的,一旦某个条件满足,后续的else ifelse都不会再执行。

🔹 嵌套 if 语句

ifelse的代码块中可以再包含if语句,用于处理更复杂的逻辑。

📝 示例:判断闰年

#include <stdio.h>

int main() {
    int year;
    printf("请输入年份: ");
    scanf("%d", &year);

    if (year % 4 == 0) {
        if (year % 100 == 0) {
            if (year % 400 == 0) {
                printf("%d 是闰年\n", year);
            } else {
                printf("%d 不是闰年\n", year);
            }
        } else {
            printf("%d 是闰年\n", year);
        }
    } else {
        printf("%d 不是闰年\n", year);
    }
    return 0;
}

以上逻辑可以用逻辑运算符简化为:

if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
    printf("%d 是闰年\n", year);
} else {
    printf("%d 不是闰年\n", year);
}

🔹 switch 语句

switch语句用于基于整数或字符表达式的值进行多分支选择,当分支较多且判断条件为等值比较时,比if-else结构更清晰。

switch (表达式) {
    case 常量1:
        // 当表达式 == 常量1时执行
        break;
    case 常量2:
        // 当表达式 == 常量2时执行
        break;
    // ...可以有多个case
    default:
        // 所有case都不匹配时执行
        break;
}
重要规则:
  • 表达式必须是整型(int, char, enum等)或能转换为整型的类型。
  • case后的常量必须互不相同。
  • break用于跳出switch,如果省略会“穿透”到下一个case
  • default可选,通常放在最后。

📝 示例:简单计算器(switch实现)

#include <stdio.h>

int main() {
    char op;
    double a, b;
    printf("请输入表达式 (如 3.5 + 2.1): ");
    scanf("%lf %c %lf", &a, &op, &b);

    switch (op) {
        case '+':
            printf("%.2f + %.2f = %.2f\n", a, b, a + b);
            break;
        case '-':
            printf("%.2f - %.2f = %.2f\n", a, b, a - b);
            break;
        case '*':
            printf("%.2f * %.2f = %.2f\n", a, b, a * b);
            break;
        case '/':
            if (b != 0)
                printf("%.2f / %.2f = %.2f\n", a, b, a / b);
            else
                printf("除数不能为0!\n");
            break;
        default:
            printf("无效运算符\n");
    }
    return 0;
}

📝 示例:利用case穿透实现统计

#include <stdio.h>

int main() {
    char grade;
    printf("请输入成绩等级(A/B/C/D/F): ");
    scanf("%c", &grade);

    switch (grade) {
        case 'A':
            printf("优秀\n");
            break;
        case 'B':
            printf("良好\n");
            break;
        case 'C':
            printf("中等\n");
            break;
        case 'D':
            printf("及格\n");
            break;
        case 'F':
            printf("不及格\n");
            break;
        default:
            printf("无效等级\n");
    }

    // 利用穿透:月份天数
    int month;
    printf("请输入月份(1-12): ");
    scanf("%d", &month);
    int days;
    switch (month) {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            days = 31;
            break;
        case 4: case 6: case 9: case 11:
            days = 30;
            break;
        case 2:
            days = 28;  // 暂不考虑闰年
            break;
        default:
            days = 0;
            printf("无效月份\n");
    }
    if (days != 0)
        printf("%d月有%d天\n", month, days);

    return 0;
}

💡 如何选择 if 还是 switch?

  • 当条件是基于范围判断时(如成绩等级),使用if-else
  • 当条件是等值判断且分支较多时(如菜单选择),使用switch使代码更清晰。
  • switch只能处理整型常量,无法处理浮点数或复杂条件。
  • 现代编译器对switch可能优化为跳转表,效率略高,但一般不需要过度关注。

📋 综合示例:简易猜拳游戏

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int player, computer;
    srand(time(0));  // 随机数种子
    computer = rand() % 3;  // 0:石头 1:剪刀 2:布

    printf("猜拳游戏: 0-石头, 1-剪刀, 2-布\n");
    printf("请出拳: ");
    scanf("%d", &player);

    if (player < 0 || player > 2) {
        printf("无效输入!\n");
        return 1;
    }

    printf("电脑出拳: ");
    switch (computer) {
        case 0: printf("石头\n"); break;
        case 1: printf("剪刀\n"); break;
        case 2: printf("布\n"); break;
    }

    if (player == computer) {
        printf("平局!\n");
    } else if ((player == 0 && computer == 1) ||
               (player == 1 && computer == 2) ||
               (player == 2 && computer == 0)) {
        printf("你赢了!\n");
    } else {
        printf("你输了!\n");
    }

    return 0;
}

⚠️ 常见错误与注意事项

  • 条件表达式中使用赋值号if (x = 5) 而不是 if (x == 5),前者会将5赋给x,然后判断条件为真(非零),导致逻辑错误。编译器通常会警告,但不会报错。
  • 花括号缺失导致作用域错误:在if后不加花括号,只有紧随的一条语句属于条件,容易出错。
  • switch中忘记break:导致“穿透”,可能执行多个case的代码,除非故意为之。
  • switch的default位置:default可以放在任何位置,但通常放在最后。如果放在前面且不加break,也会穿透。
  • 浮点数作为switch表达式:不允许,因为浮点数不能精确比较相等。
  • else的匹配else总是与最近的if配对,使用花括号可以避免歧义。

条件语句让程序具备了决策能力,是构建复杂逻辑的基础。熟练掌握if-elseswitch后,下一章我们将学习循环语句(for、while、do-while),让程序能够重复执行某些操作。