分支和循环
目录
2. 关键注意:while 循环中用 continue 易死循环
3. 禁忌:禁止滥用 goto(比如跳转至循环中间),否则代码逻辑混乱,调试起来头大!
✨ 引言:
如果说数据类型是 C 语言的 “砖瓦”,那分支与循环就是 “钢筋骨架”—— 它们让程序摆脱 “从上到下傻执行” 的死板,能像人一样 “做选择”(比如判断成年与否)、“重复做事”(比如打印 1~100)。
一、先搞懂:结构化程序设计是什么?
C 语言是 “结构化编程语言”,核心就 3 种基础结构,所有复杂程序(比如游戏、APP)都能靠它们组合出来:
- 🚶 顺序结构:代码从上到下依次执行(默认逻辑,比如先定义变量再打印);
- 🚦 选择结构:根据条件选不同路径(if/switch,像 “岔路口选路”);
- 🔄 循环结构:满足条件就重复执行(while/for/do while,像 “反复做家务”)。
简单说:掌握这 3 种结构,你就能让程序 “有逻辑、会思考”!
二、if 语句:程序的 “岔路口”(二选一 / 多选一)
if 语句是最常用的选择结构,核心是 “满足条件走 A 路,不满足走 B 路”,语法简单但陷阱超多,新手重点记 “大括号 + 悬空 else”!
1. 3 种核心语法(直接抄代码用)
(1)单分支 if:满足条件才做事
// 场景:输入整数,判断是否为奇数
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
// 表达式非0为真,0为假
if (num % 2 == 1)
{ // 大括号必加!避免后续加代码出错
printf("奇数\n");
}
return 0;
}
(2)双分支 if-else:二选一
// 场景:输入年龄,判断成年/未成年
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18)
printf("成年\n"); // 单条语句可省大括号(但不推荐)
else
printf("未成年\n");
return 0;
}
(3)多分支 if-else if-else:多选一
// 场景:根据年龄划分人群
int main()
{
int age = 0;
scanf("%d", &age);
if (age < 18)
printf("少年\n");
else if (age <= 44)
printf("青年\n");
else if (age <= 59)
printf("中老年\n");
else if (age <= 89)
printf("老年\n");
else
printf("老寿星\n"); // 所有条件不满足时执行
return 0;
}
2. 新手必避的 2 个致命陷阱(红标警告!)
(1)大括号不能漏!
// 错误示例:else只控制紧跟的1条语句
int main()
{
int age = 18;
if (age >= 18)
printf("成年\n");
printf("可以谈恋爱了\n"); // 不管age多少,都会执行(无大括号)
else
printf("未成年\n");
return 0;
}
// 正确示例:用大括号包裹多条语句(推荐所有情况都加)
int main()
{
int age = 18;
if (age >= 18)
{
printf("成年\n");
printf("可以谈恋爱了\n"); // 仅if成立时执行
}
else
{
printf("未成年\n");
printf("不能谈恋爱\n");
}
return 0;
}
(2)悬空 else:else 只跟最近的 if 匹配
// 易错代码(缩进误导人)
int main()
{
int a = 0, b = 2;
if (a == 1)
if (b == 2)
printf("hehe\n");
else // 实际跟if(b==2)匹配,不是if(a==1)
printf("haha\n");
return 0;
}
// 输出:无(a==1为假,整个嵌套if都不执行)
// 正确写法:加大括号明确匹配关系
int main()
{
int a = 0, b = 2;
if (a == 1)
{
if (b == 2)
printf("hehe\n");
}
else // 明确跟if(a==1)匹配
printf("haha\n");
return 0;
}
// 输出:haha
三、支撑分支循环的 4 类核心运算符(必掌握)
分支循环的 “条件判断” 全靠这些运算符,重点记逻辑运算符的 “短路特性”,能少踩很多坑!
1. 关系运算符:比较大小 / 相等(6 个)
- 运算符:
>、<、>=、<=、==(等于)、!=(不等于); - 结果:真(非 0,通常是 1)或假(0);
- ❌ 易错点:
- 别把
==(判断相等)写成=(赋值)!比如if(a=3)是赋值,永远为真; - 别连续比较!比如
18 <= age <= 40是错的(先算18<=age得 0/1,再跟 40 比),正确写法:age >= 18 && age <= 40。
- 别把
2. 逻辑运算符:组合条件(3 个)
!(逻辑取反):真变假,假变真(比如!0=1,!5=0);&&(逻辑与):全真为真,一假为假(比如3>2 && 2>1为真);||(逻辑或):一真为真,全假为假(比如3>2 || 2>3为真);- ✨ 核心特性:短路求值(关键优化,也是陷阱)!
// 示例1:&&短路(左边为假,右边不执行)
int main()
{
int a = 0, b = 2;
if (a == 1 && ++b) // a==1为假,++b不执行
printf("b=%d\n", b);
printf("b=%d\n", b); // 输出:2(b没变化)
return 0;
}
// 示例2:||短路(左边为真,右边不执行)
int main()
{
int a = 2, b = 2;
if (a == 2 || ++b) // a==2为真,++b不执行
printf("b=%d\n", b);
printf("b=%d\n", b); // 输出:2(b没变化)
}
3. 条件运算符:简化 if-else(三目运算符)
- 语法:
exp1 ? exp2 : exp3(exp1 为真,结果是 exp2;否则是 exp3); - 作用:简化 “二选一赋值”,代码更简洁!
// 场景:a>5则b=3,否则b=-3
int main()
{
int a = 0, b = 0;
scanf("%d", &a);
b = (a > 5 ? 3 : -3); // 等价于if-else,一行搞定
printf("b=%d\n", b);
return 0;
}
// 练习:求a和b的最大值
int main()
{
int a = 0, b = 0;
scanf("%d %d", &a, &b);
int max = (a > b ? a : b);
printf("最大值:%d\n", max);
return 0;
}
4. 逗号表达式:顺序求值(取最后结果)
- 语法:
exp1, exp2, ..., expn(从左到右执行,结果是最后一个表达式); - 适用场景:简化多条赋值语句。
int main()
{
int a = 0, b = 4, c = 0;
c = (a = 3, b = a * 4, c = a + b); // 执行顺序:a=3→b=12→c=15
printf("c=%d\n", c); // 输出:15(最后一个表达式的结果)
return 0;
}
四、switch 语句:多分支的 “快捷菜单”
当分支条件是 “整型常量匹配”(比如按数字选功能),用 switch 比 if-else 更简洁,像餐厅点餐一样直接选编号!
1. 基本语法(直接套用)
switch(整型表达式)
{
case 常量1: 语句1; break;
case 常量2: 语句2; break;
...
default: 语句n; break; // 无匹配时执行
}
2. 3 个核心规则(记牢不踩坑)
- switch 后的表达式必须是整型(int、char 等),case 后必须是整型常量(不能是变量,比如
case a错误); break是 “退出开关”:执行完 case 后必须加 break,否则会 “穿透”(继续执行下一个 case);default可放任意位置,建议放最后,处理异常输入(比如输入 1~7 外的数字)。
3. 实战示例(2 个常用场景)
(1)输入 1~7,打印星期几
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1: printf("星期一\n"); break;
case 2: printf("星期二\n"); break;
case 3: printf("星期三\n"); break;
case 4: printf("星期四\n"); break;
case 5: printf("星期五\n"); break;
case 6: printf("星期六\n"); break;
case 7: printf("星期日\n"); break;
default: printf("输入错误!请输1~7\n"); break;
}
return 0;
}
(2)合理利用 case 穿透(简化代码)
// 场景:判断工作日/休息日
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1: case 2: case 3: case 4: case 5:
printf("工作日\n"); break; // 1~5共用同一逻辑
case 6: case 7:
printf("休息日\n"); break; // 6~7共用同一逻辑
default: printf("输入错误!\n"); break;
}
return 0;
}
4. switch 与 if-else 怎么选?
| 场景 | 推荐用 | 原因 |
|---|---|---|
| 整型常量匹配(如 1~7) | switch | 代码简洁,执行效率高 |
| 范围判断(如 age>18) | if-else if | 灵活,能处理连续范围 |
五、三大循环语句:让程序 “重复做事”(核心重点)
循环用于 “满足条件时重复执行某段代码”,C 语言有 3 种循环,核心是 “初始化、判断、调整” 三要素,少一个就会出问题!
1. while 循环:最基础的 “重复框架”
(1)语法(三要素分散)
初始化表达式;
while(判断表达式) // 条件为真则执行
{
循环体语句;
调整表达式; // 改变条件,避免死循环
}
(2)示例:打印 1~10
int main()
{
int i = 1; // 初始化:循环起点
while (i <= 10) // 判断:循环终止条件
{
printf("%d ", i); // 循环体:要重复做的事
i++; // 调整:i递增,逐步接近终止条件
}
return 0;
}
// 输出:1 2 3 4 5 6 7 8 9 10
(3)实战:逆序打印整数的每一位
// 输入1234,输出4 3 2 1
int main()
{
int n = 0;
scanf("%d", &n);
while (n != 0) // n为0时循环终止
{
printf("%d ", n % 10); // 取最后一位
n = n / 10; // 去掉最后一位
}
return 0;
}
2. for 循环:最常用的 “高效循环”
(1)语法(三要素集中,推荐首选)
for(初始化; 判断; 调整)
{
循环体语句;
}
(2)优势:三要素集中在一行,易维护、不易漏
// 示例:打印1~10(对比while更简洁)
int main()
{
for (int i = 1; i <= 10; i++) // 初始化、判断、调整一目了然
{
printf("%d ", i);
}
return 0;
}
(3)实战:计算 1~100 中 3 的倍数之和
// 方法1:遍历所有数,判断是否是3的倍数
int main()
{
int sum = 0;
for (int i = 1; i <= 100; i++)
{
if (i % 3 == 0)
sum += i; // sum = sum + i
}
printf("和为:%d\n", sum); // 输出:1683
return 0;
}
// 方法2:直接遍历3的倍数(更高效)
int main()
{
int sum = 0;
for (int i = 3; i <= 100; i += 3) // 步长3,跳过非3的倍数
{
sum += i;
}
printf("和为:%d\n", sum);
return 0;
}
3. do while 循环:“先执行后判断” 的循环
(1)语法(循环体至少执行 1 次)
do
{
循环体语句;
} while(判断表达式); // 分号不能漏!
(2)核心特点:不管条件是否成立,先执行 1 次
// 示例:打印1~10
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
(3)实战:计算整数的位数(含 0)
// 输入0→输出1;输入123→输出3
int main()
{
int n = 0, count = 0;
scanf("%d", &n);
do
{
count++; // 先计数,再去掉最后一位
n = n / 10;
} while (n != 0); // 0的情况:循环执行1次,count=1
printf("位数:%d\n", count);
return 0;
}
4. 三大循环对比(选对场景不纠结)
| 循环类型 | 核心特点 | 适用场景 |
|---|---|---|
| while | 先判断后执行,三要素分散 | 循环次数不确定(如用户输入终止) |
| for | 先判断后执行,三要素集中 | 循环次数确定(如遍历 1~100) |
| do while | 先执行后判断,至少 1 次 | 必须先执行 1 次(如计数位数、菜单) |
六、break 与 continue:循环的 “控制开关”
这两个关键字是循环的 “刹车和换挡”,作用完全不同,新手容易搞混,用表格 + 示例讲透!
1. 核心区别(一张表看懂)
| 关键字 | 作用 | 示例(for 循环打印 1~10) | 输出结果 |
|---|---|---|---|
| break | 直接终止循环,永久退出 | if(i==5) break; | 1 2 3 4 |
| continue | 跳过本次循环,继续下一次 | if(i==5) continue; | 1 2 3 4 6 7 8 9 10 |
2. 关键注意:while 循环中用 continue 易死循环
// 错误示例:i=5时continue,跳过i++,陷入死循环
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
continue; // 跳过i++,i永远=5
printf("%d ", i);
i++;
}
return 0;
}
// 正确示例:先调整i,再判断continue
int main()
{
int i = 1;
while (i <= 10)
{
i++; // 先递增
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
// 输出:2 3 4 6 7 8 9 10 11
七、goto 语句:循环的 “紧急出口”(谨慎使用)
goto 语句用于 “无条件跳转”,语法简单但容易破坏代码结构,仅推荐 2 种场景使用!
1. 基本语法
goto 标签名; // 跳转指令
...
标签名: 语句; // 跳转目标(标签名自定义,后加冒号)
2. 推荐使用场景
(1)多层循环快速退出(比多个 break 简洁)
// 三层循环,满足条件直接退出所有循环
int main()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
if (k == 1)
goto exit; // 直接跳出所有循环
printf("i=%d,j=%d,k=%d\n", i, j, k);
}
}
}
exit: // 跳转目标
printf("循环结束\n");
return 0;
}
(2)统一错误处理(跳转至错误处理代码)
// 简化示例:模拟程序出错后跳转
int main()
{
int err = 1; // 假设程序出错
if (err)
goto error; // 跳转到错误处理
printf("程序正常执行\n");
error:
printf("程序出错,请检查!\n");
return 0;
}
3. 禁忌:禁止滥用 goto(比如跳转至循环中间),否则代码逻辑混乱,调试起来头大!
八、随机数生成:让程序 “不确定”(实战基础)
想做猜数字、抽奖等程序,必须会生成随机数!rand () 函数生成 “伪随机数”,需配合 srand () 和 time () 才能生成真正的随机数。
1. 核心函数(需包含头文件)
rand():生成 0~RAND_MAX(32767)的伪随机数(头文件:stdlib.h);srand(unsigned int seed):初始化随机数种子(seed 不同,rand () 结果不同);time(NULL):返回当前时间戳(从 1970-01-01 到现在的秒数,头文件:time.h)。
2. 关键错误修正(原笔记高频错!)
// 错误示例:用%f打印rand()(rand()返回int,需用%d)
int main()
{
printf("%f\n", rand()); // 错误:输出乱码
return 0;
}
// 正确示例:用%d打印
int main()
{
printf("%d\n", rand()); // 正确:输出0~32767的整数
return 0;
}
3. 生成真正的随机数(种子随时间变化)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
// 初始化种子(仅需执行1次,放在程序开头)
srand((unsigned int)time(NULL));
// 生成随机数(多次调用rand())
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
return 0;
}
4. 生成指定范围的随机数(公式记牢!)
- 公式:
rand() % (最大值 - 最小值 + 1) + 最小值; - 示例:生成 1~100 的随机数:
rand() % 100 + 1; - 原理:
rand() % 100生成 0~99,加 1 后变成 1~100。
九、实战项目:猜数字游戏(综合应用所有知识点)
整合分支、循环、随机数,做一个完整的交互游戏,包含菜单、游戏逻辑、次数限制,直接复制就能运行!
1. 完整代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 菜单函数:显示功能选项
void menu()
{
printf("*****************************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("*****************************\n");
}
// 游戏核心函数
void game()
{
int guess = 0;
// 1.生成1~100的随机数(仅1次)
int ret = rand() % 100 + 1;
// 2.猜数字(最多5次机会)
int count = 5;
while (count > 0)
{
printf("你还有%d次机会\n", count);
printf("请输入要猜的数字:>");
scanf("%d", &guess);
// 3.判断猜大/猜小/猜对
if (guess < ret)
printf("猜小了\n");
else if (guess > ret)
printf("猜大了\n");
else
{
printf("恭喜你,猜对了!数字是:%d\n", ret);
break; // 猜对退出循环
}
count--; // 机会减少1次
}
if (count == 0)
printf("很遗憾,机会用完了!正确数字是:%d\n", ret);
}
int main()
{
int input = 0;
// 初始化随机数种子(仅执行1次)
srand((unsigned int)time(NULL));
do
{
menu(); // 显示菜单
printf("请选择:>");
scanf("%d", &input);
// 根据选择执行功能
switch (input)
{
case 1: game(); break; // 开始游戏
case 0: printf("退出游戏\n"); break; // 退出
default: printf("选择错误,请重新选择\n"); break; // 输入错误
}
} while (input != 0); // input=0时退出循环
return 0;
}
2. 游戏功能说明
- 菜单交互:输入 1 开始游戏,0 退出,其他提示错误;
- 随机数:每次运行生成不同的 1~100 随机数;
- 次数限制:最多 5 次机会,用完提示正确答案;
- 反馈机制:猜大 / 猜小 / 猜对都有明确提示。
3. 扩展建议(自己动手优化)
- 增加难度等级:简单(1~50,10 次机会)、中等(1~100,5 次)、困难(1~200,3 次);
- 记录猜中次数:显示 “你用了 x 次猜对!”;
- 增加排行榜:记录历史最高正确率。
📝 总结
这篇博客覆盖了 C 语言分支与循环的所有核心知识点:从结构化设计到 if/switch 分支,从四大运算符到三大循环,再到随机数生成与实战游戏,每个部分都有 “生活化比喻 + 可复制代码 + 避坑指南”。
如果这篇博客帮你避开了几个坑,欢迎点赞收藏!
1248

被折叠的 条评论
为什么被折叠?



