前言
本文面向 C 语言初学者,从零开始讲解程序中最常用的两类控制结构:分支语句与循环语句。
- 分支语句:
if单分支、if...else双分支、if...else if...else多分支、三目运算符以及switch分支,解决"根据条件选择执行哪段代码"的问题。 - 循环语句:
while、do while、for三种循环,以及break、continue两个循环控制关键字,解决"重复执行某段代码"的问题。
每个知识点都配有可直接编译运行的完整示例,并在代码中用中文注释逐行说明执行过程,方便边看边敲、边敲边理解。
学习目标:读完后能够独立写出带条件判断和循环的 C 程序,理解各语句的执行流程与适用场景,并能根据需求在if与switch、三种循环之间做出合理选择。
目录
- 1. 分支语句
- 1.1 if 单分支
- 1.2 if…else 双分支
- 1.3 if…else if…else 多分支
- 1.4 三目运算符
- 1.5 switch 分支
- 2. 循环语句
- 2.1 while 循环
- 2.2 do while 循环
- 2.3 for 循环
- 3. 循环控制关键字
- 3.1 break
- 3.2 continue
- 4. 总结
1. 分支语句
1.1 if 单分支
语法:
if(条件){// 条件成立时执行的代码}简单示例:
#include<stdio.h>intmain(){intage=20;// 定义变量 age 为 20if(age>=18){// 判断 age >= 18 是否成立printf("已成年\n");// 20 确实大于等于 18,条件成立,输出“已成年”}return0;}1.2 if…else 双分支
语法
if(条件){//条件成立时执行的代码}else{//条件不成立时的代码}简单示例:
#include<stdio.h>intmain(){intscore=55;// 定义变量 score 为 55if(score>=60){// 判断 score >= 60 是否成立printf("及格\n");// 55 小于 60,条件不成立,不执行这里}else{printf("不及格\n");// 条件不成立,执行 else 里的代码,输出“不及格”}return0;}1.3 if…else if…else 多分支
语法
if(条件1){//条件1成立,执行这里}elseif(条件2){//条件1不成立,条件2成立,执行这里}elseif(条件3){//条件1,2不成立,条件3成立,执行这里}else{//条件1,2,3都不成立,执行这里}简单示例:
#include<stdio.h>intmain(){intscore=85;// 定义变量 score 为 85if(score>=90){// 先判断 score >= 90,85 不小于 90,条件不成立printf("优秀\n");}elseif(score>=80){// 再判断 score >= 80,85 大于等于 80,条件成立printf("良好\n");// 执行这里的代码,输出“良好”}elseif(score>=60){printf("及格\n");}else{printf("不及格\n");}return0;}1.4 三目运算符
三目运算符是if...else的"精简版":它不执行语句,而是直接算出一个值。
语法格式
表达式1?表达式2:表达式3读法:表达式1 成立就取 表达式2,不成立就取 表达式3。其中?相当于"如果",:相当于"否则"。因为它得到的是一个值,所以可以直接赋值、直接打印,也能参与其它运算。
和 if…else 对照
// 写法一:if...else,先判断再赋值intmax;if(a>b){max=a;}else{max=b;}// 写法二:三目运算符,一行搞定,效果完全一样intmax=(a>b)?a:b;区别在于:if...else是语句,只能"做事情";三目运算符是表达式,能"算出结果",更适合"二选一取值"。
完整示例:求两个数中的较大值
#include<stdio.h>intmain(){inta=10;// 定义变量 a 为 10intb=20;// 定义变量 b 为 20// a > b 不成立,取冒号后面的 b,即 20intmax=(a>b)?a:b;// 把 20 赋给 maxprintf("较大的数是:%d\n",max);// 输出"较大的数是:20"return0;}嵌套注意事项
- 可以嵌套,但建议不超过两层,否则可读性急剧下降。
- 嵌套时结合方向是从右向左,先算最右边的三目表达式。
- 优先级很低,只比赋值运算符高,和别的运算符混用时一定要加括号。
常见错误:嵌套不加括号
#include<stdio.h>intmain(){inta=5,b=10,c=15;// 本意:求三者最大值// 实际:结合方向从右向左,等价于 a > b ? a : (b > c ? b : c)intmax=a>b?a:b>c?b:c;printf("max = %d\n",max);// 输出 15,本例碰巧正确,换组数据就可能出错return0;}这种写法可读性极差,属于"能跑但不敢维护"的代码。
正确写法:用括号明确嵌套关系
#include<stdio.h>intmain(){inta=5,b=10,c=15;// 加括号后意图清晰:先求 b、c 的较大值,再和 a 比较intmax=(a>b)?a:((b>c)?b:c);printf("max = %d\n",max);// 输出 15return0;}小结:三目运算符适合"条件简单、二选一取值"的场合;逻辑一复杂或需要嵌套,就老老实实用if...else。
1.5 switch 分支
语法
switch(整型表达式){case常量1:语句;break;case常量2:语句;break;case常量3:语句;break;default:语句;break;}解释:
1.switch()括号里只能是整形:int,char,short;不能是浮点和字符串
2.case后面必须是常量,不能写变量
3.break作用:跳出switch
完整示例:按成绩等级分支
#include<stdio.h>intmain(){intscore=85;// 定义成绩变量 score,初值为 85intlevel=score/10;// 用整除把百分制成绩换算成等级:85 / 10 = 8switch(level){// switch 括号里是整型表达式,这里为 8case10:// 100 分单独处理,与 90~99 一起归为优秀case9:// 90~99 分:level 为 9printf("等级:优秀\n");// 命中 case 9 后输出“优秀”break;// break 跳出 switch,后面的 case 不再执行case8:// 80~89 分:level 为 8,本例 85 分命中这里printf("等级:良好\n");// 输出“良好”break;// 跳出 switch,结束分支判断case7:// 70~79 分case6:// 60~69 分,与 70~79 共用同一段处理代码printf("等级:及格\n");break;// 跳出 switchdefault:// 以上 case 都不匹配时执行,即 60 分以下printf("等级:不及格\n");break;// default 放在最后时 break 可省略,写上更规范}return0;}运行结果:
等级:良好说明:case 10:后面没有语句也没有break,会直接“落”到case 9:的代码上,这是有意为之的穿透用法,用来让多个取值共用同一段处理逻辑。
错误示例:漏写 break 导致穿透(fall-through)
#include<stdio.h>intmain(){intmenu=2;// 模拟用户输入的菜单编号为 2switch(menu){case1:printf("执行功能一\n");// 漏写 break!会继续往下执行 case 2 的代码case2:printf("执行功能二\n");// 漏写 break!会继续往下执行 case 3 的代码case3:printf("执行功能三\n");break;// 直到这里才跳出 switchdefault:printf("无效的菜单编号\n");break;}return0;}运行结果(与预期只输出“执行功能二”不符):
执行功能二 执行功能三原因:switch只负责找到入口case 2,之后会顺序向下执行所有语句,直到遇到break或switch结束。漏写break就会把后面case的代码一并执行,这就是穿透。
修正写法:每个 case 处理完立即 break
#include<stdio.h>intmain(){intmenu=2;// 模拟用户输入的菜单编号为 2switch(menu){case1:printf("执行功能一\n");break;// 处理完立即跳出,避免穿透到 case 2case2:printf("执行功能二\n");break;// 处理完立即跳出,避免穿透到 case 3case3:printf("执行功能三\n");break;// 处理完立即跳出default:printf("无效的菜单编号\n");break;// 兜底处理,防止非法输入}return0;}运行结果:
执行功能二小结:break是switch的“出口”,除刻意让多个case共用代码外,每个case分支末尾都应补上break;default用于兜底,建议始终保留。
2. 循环语句
2.1 while 循环
语法
while(条件){//条件成立,进入循环}```简单示例: ```c#include<stdio.h>intmain(){inti=1;// 定义循环变量 i,初值为 1while(i<=5){// 判断 i <= 5 是否成立,成立则进入循环printf("i = %d\n",i);// 输出当前 i 的值i++;// i 自增 1,避免死循环(关键!)}printf("循环结束,i = %d\n",i);// 循环结束时 i 为 6,条件不再成立return0;}说明:while 是先判断后执行,条件一开始就不成立时,循环体一次都不会执行。
2.2 do while 循环
语法
do{循环体语句;}while(判断条件);//末尾的分号不能丢```说明:此循环和while循环有所不同,要先执行一次循环体,再判断条件 简单示例: ```c#include<stdio.h>intmain(){inti=1;// 定义循环变量 i,初值为 1do{printf("i = %d\n",i);// 先执行一次循环体,输出 i 的值i++;// i 自增 1}while(i<=5);// 再判断条件,成立则继续下一轮printf("循环结束,i = %d\n",i);// 输出 6return0;}对比示例:条件一开始就不成立时,do while 仍会执行一次。
#include<stdio.h>intmain(){inti=10;// i 初值为 10do{printf("执行了一次,i = %d\n",i);// 条件不成立也会执行一次i++;}while(i<=5);// 10 <= 5 为假,循环结束return0;}2.3 for 循环
语法
for(表达式1;表达式2;表达式3){循环体;}```表达式1:初始化; 表达式2:循环条件判断 ;表达式3:每次循环结束执行 简单示例: ```c#include<stdio.h>intmain(){// 表达式1:int i = 1 初始化;表达式2:i <= 5 循环条件;表达式3:i++ 每轮结束执行for(inti=1;i<=5;i++){printf("i = %d\n",i);// 依次输出 1 2 3 4 5}return0;}常见用法示例:求 1 到 100 的累加和。
#include<stdio.h>intmain(){intsum=0;// 定义累加变量 sum,初值为 0for(inti=1;i<=100;i++){// i 从 1 循环到 100sum+=i;// 每轮把 i 累加到 sum 上}printf("1 到 100 的和是:%d\n",sum);// 输出 5050return0;}说明:for 循环的三个表达式都可以省略,但分号不能省;省略表达式2时相当于条件恒为真,需配合 break 使用。
3. 循环控制关键字
3.1 break
作用:直接跳出整个循环,循环结束,for、while、do while 都能用。
简单示例:在 1 到 10 中查找第一个能被 7 整除的数,找到后立即跳出循环。
#include<stdio.h>intmain(){for(inti=1;i<=10;i++){// i 从 1 循环到 10if(i%7==0){// 判断 i 能否被 7 整除printf("找到第一个能被 7 整除的数:%d\n",i);// 7 满足条件,输出 7break;// 找到后立即跳出整个 for 循环,不再继续}printf("检查 i = %d,不满足\n",i);// 1~6 会执行到这里}printf("循环已结束\n");// break 之后直接执行这里return0;}说明:break 只能跳出当前所在的那一层循环;如果循环里还嵌套了 switch,break 只会跳出 switch,不会跳出外层循环。
3.2 continue
作用:跳过本次循环剩下代码,直接执行下一轮条件判断。
简单示例:输出 1 到 10 中的奇数,遇到偶数就跳过本次循环。
#include<stdio.h>intmain(){for(inti=1;i<=10;i++){// i 从 1 循环到 10if(i%2==0){// 判断 i 是否为偶数continue;// 是偶数就跳过本轮剩余代码,直接进入下一轮}printf("奇数:%d\n",i);// 只有奇数会执行到这里,输出 1 3 5 7 9}return0;}说明:continue 只是结束本次循环,循环本身不会终止;这一点与 break 有本质区别。
break 与 continue 对比:
#include<stdio.h>intmain(){printf("break 的效果:\n");for(inti=1;i<=5;i++){if(i==3){break;// i 等于 3 时整个循环结束}printf("i = %d\n",i);// 只输出 1、2}printf("continue 的效果:\n");for(inti=1;i<=5;i++){if(i==3){continue;// i 等于 3 时只跳过本轮}printf("i = %d\n",i);// 输出 1、2、4、5}return0;}4. 总结
本文围绕 C 语言的两大控制结构展开,核心要点回顾如下:
- 分支语句的选择建议
- 只有"成立就做、不成立什么都不做"时,用
if单分支。 - 只有两种互斥情况(如及格/不及格)时,用
if...else双分支。 - 存在多个区间或连续范围判断(如成绩等级)时,用
if...else if...else,注意条件从上到下依次判断,命中即跳出。 - 简单的二选一取值可以用三目运算符
条件 ? 值1 : 值2简化代码,但嵌套不宜超过两层,混用其它运算符时务必加括号。 - 判断的是离散的整型常量(如菜单编号、星期几)时,优先用
switch,结构更清晰;记得每个case后加break,并用default兜底。
- 只有"成立就做、不成立什么都不做"时,用
- 三种循环的选用原则
while:先判断后执行,循环次数不确定、由条件决定时使用,条件一开始不成立则一次都不执行。do while:先执行后判断,至少执行一次,适合"先做再问要不要继续"的场景(如输入校验、菜单循环),注意while(...)后的分号不能丢。for:次数明确的循环首选,把初始化、条件、迭代写在一行,结构紧凑、不易漏写自增导致死循环。
- 循环控制关键字
break:立即结束整个循环(只跳出当前一层),常用于"找到目标就停止"。continue:只跳过本次循环剩余代码,直接进入下一轮判断,循环本身继续。
- 实践建议:写循环时先确认三件事——初始值、终止条件、每轮如何变化;三者缺一,就容易写出死循环或差一错误(off-by-one)。