c语言知识总结(3.控制结构)
一、条件语句:
1. if与else的运用
if:条件为真(非0)时执行
if (条件) { // 成立时执行 }if-else:二选一
if (条件) { // 成立时执行 } else { // 不成立时执行 }多分支:多选一,从上到下匹配,遇到第一个真条件执行后结束
if (条件1) { // 条件1成立 } else if (条件2) { // 条件1不成立且条件2成立 } else { // 全都不成立 }嵌套:if 里再放 if
if (条件1) { if (条件2) { // 条件1和条件2都成立 } }常见错误与规则
| 错误/规则 | 说明 | 示例 |
|---|---|---|
| 忘加 {} | if 默认只管一条语句,多条必须加{} | if (x>0) a++; b++;b 不在 if 内 |
| = 和 == | if (x = 1)是赋值,恒真 | if (x == 1)才是判断 |
| else 匹配规则 | else 与最近未配对的 if 配对 | 见下方示例 |
| else 单独使用 | else 不能脱离 if 存在 | else { ... } |
| 中间多写语句 | if 和 else 之间不能有其他语句 | if (x>0) a++; b++; else ... |
| 条件顺序 | 多分支时范围大的放前面或后面 | if (>=60) 不及格顺序错误 |
else 匹配规则示例
if (a > 0) if (b > 0) printf("a和b都大于0"); else printf("a不大于0"); // 这个 else 匹配的是内层 if(b>0)! //解决:用 {} 明确范围 if (a > 0) { if (b > 0) { printf("a和b都大于0"); } } else { printf("a不大于0"); // 明确匹配外层 if }2.switch的使用
2.1基本用法
switch 用于多分支等值判断,根据表达式的值跳转到对应的 case 执行。
switch (整型表达式) { case 常量1: // 表达式 == 常量1 时执行 break; // 跳出 switch case 常量2: // 表达式 == 常量2 时执行 break; default: // 以上都不匹配时执行 }- 表达式必须是整型(int、char、enum)
case 后面必须是常量
从上到下匹配,找到相等的 case 后执行该 case 及后面所有语句(直到遇到 break 或 switch 结束)
break用于跳出 switch,防止穿透
default处理所有未匹配的情况(可省略)
int week = 3; switch (week) { case 1: printf("星期一\n"); break; case 2: printf("星期二\n"); break; case 3: printf("星期三\n"); break; case 4: printf("星期四\n"); break; default: printf("输入错误\n"); } // 输出:星期三int n = 2; switch (n) { case 1: printf("一"); case 2: printf("二"); // 执行这里 case 3: printf("三"); // 穿透继续执行 } // 输出:二三2.2穿透性质的应用
| 场景 | 示例 |
|---|---|
| 成绩分组 | 90-100分、80-89分 归为同一档 |
| 月份天数 | 1、3、5、7、8、10、12月都是31天 |
| 字符分类 | 元音字母、数字字符、空格符等 |
| 状态机 | 多个状态触发同一动作 |
int month = 7; int days; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; // 这些月份都是31天 break; case 4: case 6: case 9: case 11: days = 30; // 这些月份都是30天 break; case 2: days = 28; // 2月单独处理 break; }二、循环语句
1.for循环
1.1 基本语法
for (初始化表达式; 循环条件; 循环更新) { // 循环体语句 }| 部分 | 作用 | 执行时机 |
|---|---|---|
| 初始化 | 定义循环变量,赋初值 | 循环开始前执行一次 |
| 循环条件 | 判断是否继续循环 | 每次循环开始前判断 |
| 循环更新 | 改变循环变量 | 每次循环体执行完后执行 |
| 循环体 | 要重复执行的代码 | 条件为真时执行 |
基本示例:输出 1 到 5
for (int i = 1; i <= 5; i++) { printf("%d ", i); }1.2 使用建议
| 建议 | 说明 |
|---|---|
| 循环变量用 i、j、k | 约定俗成,清晰明了 |
| 不要修改循环变量 | 容易造成混乱或无限循环 |
循环体内加{} | 即使只有一条语句 |
| 避免太深的嵌套 | 超过三层考虑重构 |
| 循环变量作用域最小化 | C99 后可在 for 内定义循环变量 |
2.while循环
2.1 基本语法
while 循环用于未知循环次数,根据条件决定是否继续循环。
while (循环条件) { // 循环体语句 }| 部分 | 作用 | 执行时机 |
|---|---|---|
| 循环条件 | 判断是否继续循环 | 每次循环开始前判断 |
| 循环体 | 要重复执行的代码 | 条件为真时执行 |
基本示例:输出 1 到 5
int i = 1; while (i <= 5) { printf("%d ", i); i++; }2.2使用建议
| 建议 | 说明 |
|---|---|
| 确保循环变量更新 | 避免无限循环 |
循环体内加{} | 即使只有一条语句 |
| 避免用赋值当条件 | while (i = 5)是常见错误 |
| 注意 continue 位置 | 确保循环变量能更新 |
3.do-while循环
3.1 基本语法
do-while 循环与 while 类似,但先执行一次循环体,再判断条件。
do { // 循环体语句 } while (循环条件); // 注意这里有分号!| 部分 | 作用 | 执行时机 |
|---|---|---|
| 循环体 | 要重复执行的代码 | 至少执行一次 |
| 循环条件 | 判断是否继续循环 | 每次循环体执行完后判断 |
3.2 do-while 与 while 的对比
| 对比 | do-while | while |
|---|---|---|
| 执行顺序 | 先执行后判断 | 先判断后执行 |
| 最少执行次数 | 1 次(至少执行一次) | 0 次(可能一次都不执行) |
| 适用场景 | 至少需要执行一次 | 可能一次都不执行 |
| 语法 | 结尾有分号 !!! | 结尾无分号 |
对比示例:条件一开始为假
// do-while:至少执行一次 int i = 10; do { printf("至少执行一次\n"); // 会执行 } while (i < 5); // while:一次都不执行 int i = 10; while (i < 5) { printf("不会执行\n"); // 不执行 }4.嵌套循环
嵌套循环指一个循环语句内部再包含另一个完整的循环语句。外层循环执行一次,内层循环执行完整一轮。
4.1嵌套意义
外层循环控制“行”,内层循环控制“列”——嵌套循环用来处理二维结构或重复做某件事多次。
三大典型应用场景
| 场景 | 意义 | 示例 |
|---|---|---|
| 处理二维数据 | 访问矩阵、表格、图像像素 | 遍历二维数组、矩阵运算 |
| 打印图形 | 控制行和列的数量关系 | 矩形、三角形、菱形 |
| 重复执行某件事多次 | 对每个外层元素,内层做固定操作 | 排序算法、穷举搜索 |
4.2执行次数计算
| 循环结构 | 执行次数 | 示例 |
|---|---|---|
| 单层循环 | n | 1 到 n |
| 双层循环 | n × m | 3 × 4 = 12 次 |
| 三层循环 | n × m × k | 2 × 3 × 4 = 24 次 |
4.3常见错误
1:内外层使用相同循环变量
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) { // 内层同名变量 printf("%d ", i); } }2:忘记初始化内层变量
int j = 0; while (j < 3) { printf("%d ", j); j++; } // 输出:0 1 2 int i = 0; while (i < 2) { while (j < 3) { // ❌ j 已经是 3,内层一次都不执行 printf("(%d,%d)", i, j); j++; } i++; } // 输出:(空)3:花括号缺失
for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) printf("(%d,%d) ", i, j); printf("\n"); // 这行不在内层循环后5.循环常见错误
循环通用陷阱
| 陷阱 | 说明 | 错误示例 |
|---|---|---|
| 忘记加 {} | 循环默认只管一条语句 | while (i<5) a++; b++;b不在循环内 |
| 分号放错 | )后面直接加分号,循环体为空 | for (i=0; i<5; i++); |
| 赋值当条件 | =写成==,条件恒真 | while (i = 5)无限循环 |
| 条件写反 | 循环条件逻辑错误 | for (i=5; i>0; i++)越来越大 |
| 忘记更新变量 | 循环变量不更新,死循环 | while (i<5) { printf("%d", i); }忘写 i++ |
各循环独有的坑
| 循环 | 独有陷阱 | 说明 | 示例 |
|---|---|---|---|
| for | 分号放错位置 | for (...);循环体为空 | for (i=0; i<5; i++); { printf("%d", i); } |
| while | continue跳过更新 | continue 可能导致循环变量更新被跳过 | while (i<5) { if (i==3) continue; i++; } |
| do-while | 末尾忘记分号 | } while (条件)后面必须有; | do { ... } while (条件)编译错误 |
6.三种循环对比*
| 对比项 | for 循环 | while 循环 | do-while 循环 |
|---|---|---|---|
| 语法 | for (初始化; 条件; 更新) {} | while (条件) {} | do {} while (条件); |
| 执行顺序 | 先判断后执行 | 先判断后执行 | 先执行后判断 |
| 最少执行次数 | 0 次 | 0 次 | 1 次 |
| 适用场景 | 已知循环次数 | 未知次数,条件控制 | 至少执行一次 |
| 初始化位置 | 在 for 头部 | 循环外定义 | 循环外定义 |
| 更新位置 | 在 for 头部 | 循环体内手动 | 循环体内手动 |
| 无限循环 | for (;;) | while (1) | do {} while (1); |
| 结尾分号 | 无 | 无 | 必须有; |
| 场景 | 推荐循环 | 原因 |
|---|---|---|
| 已知循环次数 | for | 初始化、条件、更新集中 |
| 未知次数,可能一次都不做 | while | 先判断后执行 |
| 至少要做一次 | do-while | 先执行后判断 |
| 无限循环 | for(;;)或while(1) | 个人喜好 |
次数已知用 for,可能不做用 while,至少一次 do-while,无限循环看心情。
三、跳转语句
1.break的应用
1.1 基本用法
break用于立即跳出当前所在的循环或 switch 语句,不再执行循环中剩余的代码,也不再进行下一次循环。
| 使用场景 | 作用 |
|---|---|
| 循环中(for/while/do-while) | 立即跳出整个循环 |
| switch 中 | 跳出 switch,防止穿透 |
| 嵌套循环中 | 只跳出当前层循环!!! |
1.2 在选择语句的应用
有break版本(正确)
int week = 3; switch (week) { case 1: printf("星期一\n"); break; // 跳出 switch case 2: printf("星期二\n"); break; case 3: printf("星期三\n"); break; // 执行到这里,跳出 switch default: printf("输入错误\n"); } // 输出:星期三无break版本(穿透)(在特定情况下可以利用穿透的性质)
int week = 3; switch (week) { case 1: printf("星期一\n"); case 2: printf("星期二\n"); case 3: printf("星期三\n"); default: printf("输入错误\n"); } // 输出: 星期三(换行) 错误输入1.3在循环语句的应用
for (int i = 1; i <= 10; i++) { if (i == 5) break; // i=5 时跳出循环 printf("%d ", i); } // 输出:1 2 3 42.continue的应用
2.1基本语法
continue用于跳过本次循环中剩余的代码,直接进入下一次循环。
| 使用场景 | 作用 |
|---|---|
| 循环中 | 结束本次循环,进入下一次 |
| while/do-while 中 | 注意循环变量更新位置 |
2.2 在 for 循环中的应用
for (int i = 1; i <= 5; i++) { if (i == 3) continue; // 跳过 i=3 printf("%d ", i); } // 输出:1 2 4 52.3在 while 循环中的应用
留意更新位置,避免使用continue语句跳过。
//错误:continue 跳过更新 int i = 1; while (i <= 5) { if (i == 3) continue; // 跳到下次循环,i++ 被跳过 printf("%d ", i); i++; // i=3 时这行不执行 → 无限循环 }3.goto的应用
3.1 基本作用
goto用于无条件跳转到程序中指定的标签位置。
| 场景 | 说明 |
|---|---|
| 跳出多层循环 | 比标志位更直接 |
| 统一错误处理 | 多个错误跳转到同一位置 |
| 清理资源 | 函数结束前统一释放 |
goto 标签名; // ... 标签名: // 要跳转到的代码示例:
//跳出多层循环 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == 1 && j == 1) { goto end; // 直接跳出所有循环 } printf("(%d,%d) ", i, j); } printf("\n"); } end: printf("循环结束\n");3.2 使用建议
唯一推荐的两种使用场景
| 场景 | 示例 |
|---|---|
| 统一错误处理 | if (失败) goto cleanup; |
| 跳出多层循环 | if (找到) goto found; |
了解语法即可,实际编程中严禁使用,直到你成为经验丰富的开发者并遇到非用不可的场景。
