• 0
  • 1
  • 0
  • C 语言流程控制与循环结构 —— 课堂笔记整理

  • 小言心
  • 2,738
  • 2026-06-04 22:43
  • 本文梳理了C语言中条件判断(if-else)、多分支选择(switch)以及循环结构(for、while、do-while)的核心语法、典型应用和常见陷阱,适合作为复习资料或技术存档。

    一、条件判断:if-else 结构

    1.1 基本语法

    if (条件表达式) {
        // 条件为真(非0)时执行
    } else {
        // 条件为假(0)时执行
    }
    • 条件表达式可以是任何能产生整型值的表达式,0 表示假,非 0 表示真。
    • 如果代码块只有一条语句,大括号 {} 可以省略,但为可读性和避免“悬挂 else”问题,始终建议保留大括号。

    1.2 多分支结构:if - else if - else

    if (条件1) {
        // ...
    } else if (条件2) {
        // ...
    } else {
        // 以上条件均不成立时执行
    }
    • 程序从上到下依次判断条件,一旦某个条件成立,执行对应代码块后直接跳出整个 if-else 链,不再继续判断后续条件。
    • else 分支是可选的,但常用来捕获所有未匹配的情况(可作为“兜底”分支)。

    1.3 关键示例与易错点

    示例1:逻辑运算符优先级(电影选择问题)

    判断条件:若两人同一排(row 相同),且座位号相邻(差值为 1 或 -1),则“开心看电影”,否则“玩手机”。

    int rowA = 10, rowB = 10;
    int numberA = 5, numberB = 6;
    
    // 错误写法(优先级陷阱)
    if (rowA == rowB && numberA - numberB == 1 || numberA - numberB == -1) {
        printf("我会很开心的看电影");
    } else {
        printf("我会高兴的玩手机");
    }
    • 由于 && 优先级高于 ||,错误写法会被解析为:(rowA == rowB && numberA - numberB == 1) || (numberA - numberB == -1)这导致当差值等于 -1 时,即使 rowA 不等于 rowB 也会进入 if 分支,逻辑完全错误。
    • 正确做法:用括号明确组合关系。
    if (rowA == rowB && (numberA - numberB == 1 || numberA - numberB == -1)) {
        printf("我会很开心的看电影");
    } else {
        printf("我会高兴的玩手机");
    }
    要点:在混合使用 && 和 || 时,务必加括号清晰表达逻辑意图,不要依赖默认优先级。

    示例2:多区间判断与边界处理(VIP等级)

    根据充值金额划分 VIP 等级,区间应当连续、无重叠,并且要正确处理非法值(如负数)。

    int amount;
    printf("请输入你要充值的金额:");
    scanf("%d", &amount);
    
    if (amount >= 1 && amount <= 99) {
        printf("尊贵的VIP1");
    } else if (amount >= 100 && amount <= 499) {
        printf("尊贵的VIP2");
    } else if (amount >= 500 && amount <= 999) {
        printf("尊贵的VIP3");
    } else if (amount >= 1000 && amount <= 1999) {
        printf("尊贵的VIP4");
    } else if (amount >= 2000 && amount <= 5000) {
        printf("尊贵的VIP5");
    } else if (amount <= 0) {
        printf("豹子头零充");
    } else {
        printf("顶级VIP");
    }

    必须注意的细节:

    • >= 和 <= 的书写顺序:=> 是非法运算符,必须写成 >=
    • 区间务必连续且互斥,例如第一个区间 1~99,第二个从 100 开始,避免遗漏或重叠。
    • 先判断正常区间,最后用 else if 或 else 捕获异常值(如 ≤0 或 >5000),使程序对所有输入都有明确反馈。

    二、多分支选择:switch 语句

    2.1 适用场景

    • 离散等值判断:分支条件是几个有限的具体的整数值或字符,而非范围或复杂表达式
    • 分支数较多(如 5 个以上)时,switch 可能比多层 if-else 结构更清晰;部分编译器会为密集的 case 生成跳转表,提高执行效率
    • 若判断条件涉及区间、逻辑组合,则必须使用 if-else。

    2.2 语法格式与要求

    switch (整型表达式) {
        case 整型常量1:
            // 语句
            break;
        case 整型常量2:
            // 语句
            break;
        ...
        default:
            // 所有 case 都不匹配时执行
            break;
    }
    • switch 后的表达式结果必须是整数类型(包括 char),不能是浮点数或字符串。
    • case 后面必须跟整型常量表达式(如 1、'a'),不能是变量。
    • default 分支可以放在任意位置(甚至可以省略),但习惯上放在最后。

    2.3 case 穿透现象

    如果某个 case 后没有 break,程序不会自动跳出 switch,而是继续执行下一个 case 中的代码,直到遇到 break 或整个 switch 结束。这一特性可有意用于多个 case 共享同一段逻辑。

    int week = 3;
    switch (week) {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            printf("工作日\n");
            break;
        case 6:
        case 7:
            printf("周末\n");
            break;
        default:
            printf("无效星期\n");
            break;
    }
    • 当 week 为 1~5 时,都会执行 printf("工作日") 并跳出。
    • 若误删某个 break(例如 case 5 后面没有 break),就会发生预期外的穿透,导致逻辑错误。因此穿透应当是有意为之,且应加注释说明。

    2.4 典型应用示例

    基础用法:减肥计划菜单

    int option;
    printf("请输入你的减肥计划编号:");
    scanf("%d", &option);
    
    switch (option) {
        case 1: printf("跑步");   break;
        case 2: printf("游泳");   break;
        case 3: printf("漫步");   break;
        case 4: printf("动感单车"); break;
        case 5: printf("拳击");   break;
        case 6: printf("打太极");  break;
        case 7: printf("好好吃一顿"); break;
        default: printf("输入数据错误"); break;
    }

    利用穿透合并分支:电话服务菜单

    int choice;
    printf("请输入数字选择服务:");
    scanf("%d", &choice);
    
    switch (choice) {
        case 1: printf("机票查询"); break;
        case 2: printf("机票预定"); break;
        case 3: printf("机票改签"); break;
        case 4:
        default: printf("退出服务"); break;
    }
    • 此处 case 4 后没有 break,直接贯穿到 default,因此输入 4 或其他未定义选项都会输出“退出服务”。
    • 这种设计常用于“多种情况执行相同操作”或“将非法输入合并到默认出口”。


    三、循环结构

    3.1 for 循环

    语法格式:

    for (初始化; 条件表达式; 更新) {
        // 循环体
    }

    执行顺序:
    初始化(只执行一次)→ 条件判断 →(若为真)循环体 → 更新 → 条件判断 …… 直到条件为假。

    典型示例

    // 累加 1~5
    int sum = 0;
    for (int i = 1; i <= 5; i++) {
        sum += i;
    }
    printf("%d\n", sum);   // 输出 15
    
    // 输出 1~5 再逆序输出 5~1
    for (int i = 1; i <= 5; i++) printf("%d ", i);
    printf("\n");
    for (int i = 5; i >= 1; i--) printf("%d ", i);
    printf("\n");
    
    // 1~100 之间的偶数和
    sum = 0;
    for (int i = 1; i <= 100; i++) {
        if (i % 2 == 0) {
            sum += i;
        }
    }
    printf("%d\n", sum);   // 2550
    
    // 输入两个数,统计区间内既能被 6 又能被 8 整除的数的个数
    int a, b, count = 0;
    printf("输入两个整数表示范围:");
    scanf("%d %d", &a, &b);
    int min = (a < b) ? a : b;
    int max = (a > b) ? a : b;
    for (int i = min; i <= max; i++) {
        if (i % 6 == 0 && i % 8 == 0) {
            count++;
        }
    }
    printf("个数:%d\n", count);
    // 注:既能被6又能被8整除即为24的倍数,可用 i % 24 == 0 简化
    • 循环变量 i 定义在 for 的初始化部分(C99 起支持),其作用域仅限于循环内部。一旦程序结束内容变量i会被直接销毁
    • 区间统计示例中,先用条件表达式确定 min 和 max,保证了无论输入顺序如何都能正确处理。

    3.2 while 循环

    语法格式:

    while (条件表达式) {
        // 循环体
    }
    • 先判断条件,条件为真才执行循环体,否则一次都不执行。
    • 循环变量的更新通常放在循环体内部,需要开发者自行保证条件能最终变为假,否则会造成死循环。

    示例:用 while 实现 1~5 的累加

    int i = 1, sum = 0;
    while (i <= 5) {
        sum += i;
        i++;
    }
    printf("%d\n", sum);

    3.3 for 与 while 的对比与选择

    比较维度for 循环while 循环
    适用场景循环次数确定(或可计算)时循环次数不确定,依赖某个条件动态变化
    结构特点初始化、条件、更新集中在一行,紧凑初始化在循环前,更新在循环体内,三者分散
    可读性计数循环一目了然条件驱动的循环意图更明显
    典型用例遍历数组、固定次数累加、定长处理等待用户输入特定值、读取文件到 EOF、游戏主循环等
    相互转换任何 for 都可用 while 改写任何 while 也可用 for 改写

    选择建议:

    • 当循环有明确的起点、终点和步长时,优先使用 for(如 for(i=0; i<n; i++))。
    • 当终止条件是某个复杂状态或外部事件时比如:需要一直读取某个文件的内容,如果你用for来实现就必须直到开始与结束的范围,那么一个文件当中这么多字节我们不可能一个一个去读吧,这是while就能体现出它的优势了:
    while(1){ //条件表达式为1表示一直成立
    //循环体
    //在循环体内实现你读取的逻辑,此时while就会一直执行读取工作,直到结果为假才得以结束
    }

    3.4 do-while 循环(补充)

    do {
        // 循环体
    } while (条件);
    • 特点:无论条件真假,循环体至少执行一次。适合菜单至少显示一次、先执行再询问的场景。
    • while 和 for 都是先判断后执行,do-while 是先执行后判断。

    四、总结与避坑指南

    1. 优先级与括号:&& 优先级高于 ||,混合使用时必须用括号明确逻辑,避免优先级误解导致隐蔽 bug。
    2. 区间完整性:编写 if-else if 链时,确保区间不重叠、不遗漏,并考虑非法输入的处理路径(用 else 兜底)。
    3. switch 的限制与穿透:表达式和 case 值仅限整数或字符;case 后必须是常量;遗漏 break 会导致穿透,除非有意利用穿透特性,否则必须补全 break。
    4. 循环变量的作用域:C99 起,for 内定义的变量仅循环内可见,更安全;while 的变量需提前定义,注意避免在循环外部意外访问或误用。
    5. 避免无限循环:for(;;) 和 while(1) 是刻意死循环,需在循环体内使用 break、return 或 exit 正确退出,切勿写出因条件永不更新而导致的意外死循环。
    6. 始终使用大括号:即使循环体或分支体只有一条语句,也建议用 {} 括起来,避免悬挂 else 或未来修改代码时引入错误。
    7. 边界条件测试:对于区间判断,务必测试边界值(如最小值、最大值、刚好超出范围的值),确保条件逻辑完全符合预期。

    评论

  • 0
    /1000
    最热
  • 最新

    确认跳转

    您即将离开当前页面,访问外部链接。请注意核对网址,保护隐私安全。

    https://example.com

    言心安全助手 · 建议确认来源可信

    • 目录
    • 0
    • 1
    • 0
    登录后参与评论