C 语言分支与循环语句完全指南:从入门到实战 学 C 语言的时候最让人头秃的往往不是指针和内存——而是程序到底在按什么顺序执行。一行一行往下走还是跳来跳去还是反复转圈答案是全靠控制流语句。C 语言的执行顺序由两大类语句决定1.分支语句Branch根据条件选择走哪条路——if、else、switch2.循环语句Loop让代码反复执行——while、do-while、for这篇文章把这两类语句讲透语法结构是什么、执行流程长什么样、什么时候用哪个、有哪些坑要避。一、整体概览C 语言控制流家族先看一张总图建立全局印象flowchart TD A[控制流语句] -- B[分支语句] A -- C[循环语句] B -- B1[if / else if / else] B -- B2[switch / case] C -- C1[while] C -- C2[do-while] C -- C3[for]图 1C 语言控制流语句总览——左侧为分支语句族右侧为循环语句族从图中可以看到分支语句负责做选择循环语句负责重复做。两者经常配合使用比如在循环里用if判断是否跳出是编写任何有逻辑的程序的基础。二、分支语句让程序学会做判断2.1 if / else if / else —— 最常用的条件分支if是 C 语言中最基本的分支语句。它的逻辑很简单如果条件成立就执行某段代码否则执行另一段或什么都不做。基本语法if (条件表达式) { /* 条件为真时执行的代码 */ } else if (另一个条件) { /* 上一个条件为假、这个条件为真时执行 */ } else { /* 所有条件都为假时执行 */ }关键规则条件表达式必须是标量类型整数、字符、指针结果为0表示假非0表示真花括号{}如果只有一条语句可以省略但强烈建议永远不省避免悬挂 else 等 bugelse 总是与最近的未匹配的 if 配对——这是经典面试题执行流程如下flowchart TD S[开始] -- C1{条件1} C1 --|真| A1[执行代码块1] C1 --|假| C2{条件2} C2 --|真| A2[执行代码块2] C2 --|假| C3{条件3} C3 --|真| A3[执行代码块3] C3 --|假| E[执行else代码块] A1 -- End[结束] A2 -- End A3 -- End E -- End图 2if-else-if 阶梯式条件判断的完整执行流程。程序从上到下依次检查每个条件遇到第一个为真的就进入对应分支之后的所有 else-if 和 else 都被跳过一个实际例子——成绩等级判定int score 85; if (score 90) { printf(优秀\n); } else if (score 80) { printf(良好\n); /* score85 走这里 */ } else if (score 60) { printf(及格\n); } else { printf(不及格\n); }2.2 switch-case —— 多路分支的利器当你需要根据一个变量的值从很多选项中选一个时写一长串if-else if既难看又低效。这时就该switch出场了。switch (整型表达式) { case 常量1: 语句组1; break; /* 别忘了*/ case 常量2: 语句组2; break; /* ... 更多 case ... */ default: 默认语句组; /* 所有 case 都不匹配时执行 */ }核心要点表达式必须是整数类型int、char、枚举不能用浮点数或字符串case 后面的值必须是编译期常量不能是变量break的作用是跳出 switch——漏写会导致穿透fall-through继续执行下一个 case 的代码flowchart TD S[计算表达式] -- C1{匹配case1?} C1 --|是| A1[执行语句组1] -- B1{有break?} B1 --|有| End[结束] B1 --|无| A2[执行语句组2] C1 --|否| C2{匹配case2?} C2 --|是| A2 -- B2{有break?} B2 --|有| End B2 --|无| A3[继续穿透...] C2 --|否| More{匹配更多case...} More --|不匹配| Default[执行default] -- End图 3switch-case 多分支选择语句的执行流程。计算表达式的值后跳转到匹配的 case 标签break 负责跳出缺少 break 会穿透到下一个 case穿透fall-through有时是有意为之的技巧int day 5; switch (day) { case 1: case 2: case 3: case 4: case 5: printf(工作日\n); break; case 6: case 7: printf(周末\n); break; }但更多时候它是 bug 的来源。建议每个 case 都写 break除非你明确需要穿透行为。三、循环语句让代码重复干活3.1 while 循环 —— 先判断后执行while是最简单的循环只要条件为真就反复执行循环体。while (条件表达式) { /* 循环体条件为真时重复执行 */ }flowchart TD S[开始] -- C{条件为真?} C --|是| B[执行循环体] -- C C --|否| E[结束]图 4while 循环的执行流程。每次迭代都先检查条件条件为真才进入循环体条件为假立即退出注意它的特点条件一开始就是假的 → 循环体一次都不执行。这和do-while形成鲜明对比。典型用法——计数循环int i 0; while (i 5) { printf(i %d\n, i); i; /* 别忘了更新循环变量否则死循环 */ } /* 输出i 0, 1, 2, 3, 4 */3.2 do-while 循环 —— 先执行后判断do-while和while几乎一样只有一个关键区别它至少执行一次循环体然后再去判断条件。do { /* 循环体至少执行一次 */ } while (条件表达式); /* 注意末尾的分号*/flowchart TD subgraph while循环 W1[开始] -- W2{条件?} W2 --|真| W3[执行循环体] -- W2 W2 --|假| W4[结束] end subgraph do-while循环 D1[开始] -- D2[执行循环体] D2 -- D3{条件?} D3 --|真| D2 D3 --|假| D4[结束] end图 5do-while 与 while 的对比。左while 先判断再执行可能 0 次右do-while 先执行再判断至少 1 次。这是两者唯一但本质的区别什么时候用 do-while菜单循环先显示菜单再问用户要不要继续输入校验先读取输入再判断是否合法不合法就重新输入int choice; do { printf( 主菜单 \n); printf(1. 新建文件\n); printf(2. 打开文件\n); printf(3. 退出\n); printf(请选择); scanf(%d, choice); } while (choice 1 || choice 3); /* 输入不合法就重新显示菜单 */3.3 for 循环 —— 最强大的循环for循环把初始化、条件判断、更新三件事写在同一行是 C 语言中使用频率最高的循环。for (初始化表达式; 条件表达式; 更新表达式) { /* 循环体 */ }flowchart TD Init[初始化表达式] -- Cond{条件表达式} Cond --|真| Body[执行循环体] Body -- Update[更新表达式] Update -- Cond Cond --|假| End[结束]图 6for 循环的四部分结构解剖。①初始化只执行一次 → ②判断条件 → ③执行循环体 → ④执行更新表达式 → 回到②。三个表达式都可以省略分号不能省等价的 while 写法/* for 版本 */ for (int i 0; i 10; i) { printf(%d , i); } /* 等价 while 版本 */ int i 0; /* 对应初始化 */ while (i 10) { /* 对应条件 */ printf(%d , i); i; /* 对应更新 */ }for的灵活之处在于三个表达式都可以省略省略全部三个→for(;;) 无限循环需要break退出省略条件 条件永远为真 无限循环省略初始化 变量在外部已经定义好常见模式速查模式写法用途计数循环for(i0; in; i)遍历固定次数倒序循环for(in-1; i0; i--)反向遍历步进循环for(i0; in; i2)每次步进 2无限循环for(;;)事件监听/服务器四、控制语句break 与 continue在循环内部我们常常需要改变正常的执行流程。两个关键字承担了这个职责4.1 break —— 立即跳出break的作用是立即终止当前所在的循环或 switch跳到后面的代码继续执行。flowchart TD subgraph break B1[循环执行中] -- B2{break?} B2 --|是| B3[跳出循环] B2 --|否| B4[继续执行] end subgraph continue C1[循环执行中] -- C2{continue?} C2 --|是| C3[跳过本次剩余代码] C3 -- C4[回到条件判断] C2 --|否| C5[继续执行] end图 7break 与 continue 在循环中的行为对比。左break 直接跳出整个循环后续代码不再执行右continue 只跳过本次迭代的剩余部分回到条件判断准备下一轮/* 找到第一个能被 7 整除的数就停止 */ for (int i 1; i 100; i) { if (i % 7 0) { printf(找到%d\n, i); /* 输出 7 */ break; /* 立刻退出循环 */ } } /* 循环结束后从这里继续 */4.2 continue —— 跳过本轮continue不退出循环它只是跳过本次迭代中剩下的代码直接回到循环的条件判断处准备下一轮。/* 打印 1~10 中所有奇数 */ for (int i 1; i 10; i) { if (i % 2 0) { continue; /* 偶数跳过不打印 */ } printf(%d , i); /* 只有奇数能到这里 */ } /* 输出1 3 5 7 9 */记忆口诀break 是我不干了continue 是这次不算下次再来。五、嵌套循环外层走一步内层跑一圈当一个循环的循环体里又包含另一个循环时就叫嵌套循环nested loop。这是打印九九乘法表、矩阵运算、图案输出等场景的核心技术。flowchart TD Outer[外层循环开始] -- OuterCond{外层条件} OuterCond --|真| Inner[内层循环开始] Inner -- InnerCond{内层条件} InnerCond --|真| InnerBody[执行内层循环体] InnerBody -- InnerUpdate[内层更新] -- InnerCond InnerCond --|假| OuterUpdate[外层更新] -- OuterCond OuterCond --|假| End[结束]图 8嵌套循环的执行顺序。外层每推进一轮内层都要从头到尾完整执行一遍。总执行次数 外层迭代次数 × 内层迭代次数经典案例——九九乘法表for (int i 1; i 9; i) { /* 外层行 1~9 */ for (int j 1; j i; j) { /* 内层列 1~i */ printf(%dx%d%-4d, j, i, i * j); } printf(\n); /* 每行结束后换行 */ }输出1x11 1x22 2x24 1x33 2x36 3x39 ...共 9 行第 n 行有 n 个式子嵌套循环的性能注意点双层嵌套的时间复杂度通常是O(n²)数据量大时要警惕能用单层循环解决的问题不要用嵌套比如把二维数组展平成一维break只跳出最近的一层循环不会同时跳出所有层六、实战练习综合运用下面是一个结合了分支、循环和控制语句的完整示例——猜数字游戏#include stdio.h #include stdlib.h #include time.h int main() { srand((unsigned int)time(NULL)); int secret rand() % 100 1; /* 1~100 的随机数 */ int guess, count 0; printf( 猜数字游戏 \n); printf(我想了一个 1~100 之间的数字你来猜\n\n); do { printf(请输入你的猜测1~100); scanf(%d, guess); count; if (guess 1 || guess 100) { printf(范围不对请输入 1~100 之间的数。\n\n); continue; /* 跳过重新输入 */ } if (guess secret) { printf(太大了再试试。\n\n); } else if (guess secret) { printf(太小了再试试。\n\n); } else { printf(\n恭喜你猜对了答案就是 %d\n, secret); printf(你一共猜了 %d 次。\n, count); break; /* 猜对了退出循环 */ } if (count 10) { printf(你已经猜了 10 次游戏结束。\n); printf(正确答案是 %d\n, secret); break; } } while (1); /* 无限循环靠 break 退出 */ return 0; }这个小程序用到了本文讲到的所有知识点do-while保证至少运行一次if / else if / else多路分支判断大小关系continue跳过非法输入break两种退出方式猜对 / 超过次数rand()%生成随机数七、总结与注意事项语句类型核心特点典型场景if / else分支先判断后执行可嵌套条件判断、范围检查switch / case分支整数值多路跳转菜单选择、状态机while循环先判断后执行可能 0 次不确定次数的循环do-while循环先执行后判断至少 1 次菜单循环、输入校验for循环三合一初始/条件/更新固定次数遍历break控制跳出整个循环/switch找到目标后退出continue控制跳过本次剩余代码过滤不需要的数据新手最容易犯的错if (x 5)—— 赋值号写成比较号应该永远为真switch里忘记写break—— 导致意外的穿透do-while忘记末尾分号 —— 编译错误循环体内忘记更新循环变量 —— 死循环for循环的三个表达式之间用逗号而不是分号 —— 语法错误掌握了分支和循环你就掌握了 C 语言程序的骨架。接下来可以挑战更复杂的组合应用用嵌套循环打印各种图案、用switch实现简单计算器、用break 标签实现多层跳出。多写代码、多画流程图这些概念很快就会变成你的肌肉记忆。