目录
1、if语句
1.1 if语句的基本语法
1.1.1 单分支结构
if (条件表达式) {
// 条件为真时执行的代码块
}
-
执行逻辑:若条件表达式结果为真(非零),则执行代码块;否则跳过。
-
示例:
int age = 18; if (age >= 18) { printf("成年人\n"); // 输出 }
1.1.2 双分支结构
if (条件表达式) {
// 条件为真时执行
} else {
// 条件为假时执行
}
-
执行逻辑:根据条件表达式结果选择执行其中一个分支。
-
示例:
int score = 75; if (score >= 60) { printf("及格\n"); // 输出 } else { printf("不及格\n"); }
1.1.3 多分支结构
if (条件1) {
// 条件1为真时执行
} else if (条件2) {
// 条件2为真时执行
} else {
// 所有条件均为假时执行
}
-
执行逻辑:按顺序检查条件,执行第一个满足条件的分支。
-
示例:
int temperature = 28; if (temperature > 30) { printf("炎热\n"); } else if (temperature > 20) { printf("温暖\n"); // 输出 } else { printf("凉爽\n"); }
1.2 if语句的核心规则
1.2.1 条件表达式
-
结果类型:必须是整型或布尔类型(C99起支持_Bool)。
-
真值判断:
-
非零值为真(如5,-1,'A')。
-
零值为假(如0,NULL)。
-
-
常见形式:
if (a > b) { ... } // 比较运算 if (a && b) { ... } // 逻辑与 if (flag || error) { ... } // 逻辑或 if (!valid) { ... } // 逻辑非
1.2.2 代码块与大括号
-
单语句省略:若代码块仅一行,可省略大括号(但不建议)。
if (x > 0) printf("正数\n"); // 单语句可省略大括号 -
多语句必须:多行代码必须使用大括号。
if (x > 0) { printf("正数\n"); x *= 2; // 多语句必须用大括号 }
1.2.3 嵌套if语句
-
嵌套结构:if内部可包含另一个if。
if (a > 0) { if (b > 0) { printf("a和b均为正数\n"); } } -
注意缩进:嵌套时应合理缩进,避免逻辑混乱。
1.3 if语句的使用场景
1.3.1 数值范围判断
int score = 85;
if (score >= 90) {
printf("A\n");
} else if (score >= 80) {
printf("B\n"); // 输出
} else {
printf("C\n");
}
1.3.2 字符或枚举类型判断
char op = '+';
if (op == '+') {
printf("加法\n"); // 输出
} else if (op == '-') {
printf("减法\n");
}
1.3.3 逻辑组合判断
int age = 25;
bool isStudent = true;
if (age >= 18 && isStudent) {
printf("成年学生\n"); // 输出
}
1.4 if语句的注意事项
1.4.1 常见错误
-
赋值运算符误用:
if (x = 5) { ... } // 错误:将 x 赋值为5,条件永真修正:使用==:if(x == 5)
-
浮点数精度问题:
float a = 0.1 + 0.2; if (a == 0.3) { ... } // 可能不成立修正:使用误差范围:
if (fabs(a - 0.3) < 1e-6) { ... }
1.4.2 悬空else问题
-
代码歧义:else匹配最近的未匹配if。
if (a > 0) if (b > 0) printf("a和b均为正数\n"); else printf("a非正数\n"); // 实际匹配内层if修正:使用大括号明确作用域:
if (a > 0) { if (b > 0) { printf("a和b均为正数\n"); } } else { printf("a非正数\n"); }
1.5 if语句的优缺点
优点
-
灵活性:支持任意复杂的条件表达式。
-
通用性:适用于所有数据类型(整型、浮点型、指针等)。
缺点
-
效率问题:多分支时需逐条判断,效率可能低于switch。
-
可读性:深层嵌套或复杂条件可能导致代码难以阅读。
1.6 总结
| 特性 | 说明 |
|---|---|
| 核心功能 | 根据条件选择执行代码分支 |
| 适用场景 | 范围判断、逻辑组合、错误处理等 |
| 语法要点 | 条件表达式必须为整型或布尔值,注意大括号使用 |
| 常见错误 | 误用 = 代替 ==,浮点数精度问题,悬空else |
| 与switch对比 | if更灵活,switch适合离散值多分支 |
2、switch语句
2.1 switch语句的基本语法
switch (表达式) {
case 常量1:
// 代码块1
break;
case 常量2:
// 代码块2
break;
...
default:
// 默认代码块
break;
}
-
核心组成部分
-
switch(表达式)
-
表达式必须是 整型 或 枚举类型(如int、char)。
-
不支持浮点数、字符串或其他复杂类型。
-
-
csae 常量:
-
case后跟一个整型常量表达式(如1、'A'),不能是变量或表达式。
-
所有case的常量值必须唯一。
-
-
break;
-
用于退出switch语句,防止代码“穿透”到下一个case。
-
-
default:
-
当所有case均不匹配时执行。
-
default可以省略,但建议保留以处理意外情况。
-
2.2 switch语句的执行逻辑
-
计算表达式:先计算switch后的表达式值。
-
匹配case:从上到下依次与各case的常量值匹配。
-
执行代码块:找到匹配的case后,执行其代码块。
-
退出或穿透:
-
遇到break时退出整个switch。
-
若无break,代码会继续执行下一个case的代码块(称为 穿透)。
-
2.3 switch语句的使用场景
2.3.1 多分支离散值判断
-
示例:菜单选择、状态码处理。
int choice = 2;
switch (choice) {
case 1:
printf("开始游戏\n");
break;
case 2:
printf("加载存档\n"); // 输出
break;
default:
printf("无效选项\n");
break;
}
2.3.2 字符类型处理
-
示例:解析用户输入的字符指令。
char command = 'S';
switch (command) {
case 'N':
printf("向北移动\n");
break;
case 'S':
printf("向南移动\n"); // 输出
break;
default:
printf("未知指令\n");
break;
}
2.3.3 利用穿透特性合并分支
-
示例:多个case共享同一段代码。
int month = 2;
switch (month) {
case 1:
case 3:
case 5:
printf("31天\n");
break;
case 2:
printf("28或29天\n"); // 输出
break;
default:
printf("30天\n");
break;
}
2.4 switch 语句的注意事项
2.4.1 csae值的限制
-
必须是常量:csae后不能使用变量或表达式。
int x = 10; switch (x) { case 5 + 5: // 合法(常量表达式) printf("10\n"); break; case x: // 非法(x 是变量) printf("error\n"); break; }
2.4.2 必须使用break
-
穿透问题:若省略break,代码会继续执行后续csae。
int num = 1; switch (num) { case 1: printf("1\n"); // 输出 // 缺少 break case 2: printf("2\n"); // 也会输出 break; }
2.4.3 default的使用
-
非必须但建议:处理未覆盖的情况。
int code = 404; switch (code) { case 200: printf("成功\n"); break; default: printf("错误代码: %d\n", code); // 输出 "错误代码: 404" break; }
2.5 switch vs if 的对比
| 特性 | switch 语句 | if 语句 |
|---|---|---|
| 条件类型 | 仅整型或枚举类型 | 任意布尔表达式 |
| 分支逻辑 | 基于离散值匹配 | 支持范围判断和复杂逻辑 |
| 效率 | 分支多时可能优化为跳转表 | 逐条判断,效率可能较低 |
| 可读性 | 适合多分支离散值 | 适合简单或复杂条件 |
| 常见错误 | 忘记break导致穿透 | 误用 = 代替 == |
2.6 示例代码
2.6.1 处理枚举类型
enum Color { RED, GREEN, BLUE };
enum Color c = GREEN;
switch (c) {
case RED:
printf("红色\n");
break;
case GREEN:
printf("绿色\n"); // 输出
break;
case BLUE:
printf("蓝色\n");
break;
}
2.6.2 穿透特性实现多条件合并
char grade = 'B';
switch (grade) {
case 'A':
case 'B':
case 'C':
printf("合格\n"); // 输出
break;
case 'D':
case 'F':
printf("不合格\n");
break;
}
2.7 总结
| 特性 | 说明 |
|---|---|
| 核心功能 | 基于离散值匹配执行多分支代码 |
| 适用场景 | 菜单选择、状态码处理、字符指令解析 |
| 语法要点 | case后必须为整型常量,break防止穿透,default处理未匹配情况 |
| 常见错误 | 忘记 break,case使用变量或非整型值 |
| 性能优势 | 分支较多时可能被编译器优化为跳转表 |
3、while语句
3.1 while语句的基本语法
while (条件表达式) {
// 循环体代码块
}
-
执行逻辑:
-
先判断条件表达式是否为真(非零)。
-
若为真,执行循环体代码块,然后重复步骤1。
-
若为假,退出循环。
-
3.2 while的核心特点
-
先判断后执行:可能一次都不执行循环体(条件初始即为假)。
-
适合不确定次数的循环:循环次数由动态条件决定。
-
灵活性:条件可以是任意布尔表达式(整型、逻辑运算等)。
3.3 使用场景
3.3.1 用户输入验证
int num;
printf("请输入一个正数: ");
scanf("%d", &num);
while (num <= 0) { // 若输入不合法,循环提示
printf("输入错误!请重新输入: ");
scanf("%d", &num);
}
3.3.2 遍历数组或集合
int arr[] = {1, 2, 3, 4, 5};
int i = 0;
while (i < 5) {
printf("%d ", arr[i]); // 输出: 1 2 3 4 5
i++;
}
3.3.3 动态条件循环
int x = 10;
while (x > 0) {
printf("%d ", x); // 输出: 10 9 8 ... 1
x--;
}
3.3.4 无限循环(需配合break)
while (1) { // 条件永真
printf("按Q退出: ");
char c = getchar();
if (c == 'Q') break; // 手动退出
}
3.4 注意事项
3.4.1 避免无限循环
-
错误示例:未更新循环变量。
int i = 0; while (i < 5) { // i 始终为0,条件永真 printf("无限循环\n"); } -
修正:在循环体内更新变量。
int i = 0; while (i < 5) { printf("%d\n", i); i++; // 更新条件变量 }
3.4.2 条件表达式的副作用
-
避免在条件中修改变量(除非必要)。
int x = 5; while (x-- > 0) { // 合法,但可能降低可读性 printf("%d ", x); // 输出: 4 3 2 1 0 }
3.4.3 复杂的退出条件
-
若循环退出条件复杂,可结合break使用。
while (1) { // 复杂逻辑... if (满足退出条件) break; }
3.5 变体:do-while语句
- 语法:
do {
// 循环体代码块
} while (条件表达式);
-
特点:先执行后判断,循环体至少执行一次。
-
适用场景:菜单界面、至少执行一次的操作。
int choice; do { printf("1. 开始\n2. 退出\n"); scanf("%d", &choice); } while (choice != 1 && choice != 2); // 输入非法时重复
3.6 总结
| 特性 | 说明 |
|---|---|
| 核心功能 | 根据条件重复执行代码块 |
| 执行逻辑 | 先判断条件,后执行循环体 |
| 适用场景 | 输入验证、动态条件循环、不确定次数的操作 |
| 常见错误 | 忘记更新循环变量导致无限循环,条件表达式副作用 |
| 与for对比 | while更灵活,for更紧凑 |
4、for语句
4.1 for语句的基本语法
for (初始化表达式; 条件表达式; 更新表达式) {
// 循环体代码块
}
-
核心组成部分
-
初始化表达式:
-
在循环开始前执行一次,通常用于初始化循环变量。
-
可以声明变(C99起支持循环内声明,如 for(int i = 0; ; ...))。
-
-
条件表达式:
-
每次循环前检查条件,若为真(非零)则执行循环体,否则退出循环。
-
-
更新表达式:
-
每次循环体执行后执行,通常用于更新循环变量。
-
4.2 for循环的典型使用场景
4.2.1 固定次数的循环
for (int i = 0; i < 5; i++) {
printf("%d ", i); // 输出: 0 1 2 3 4
}
4.2.2 遍历数组或集合
int arr[] = {10, 20, 30};
for (int i = 0; i < 3; i++) {
printf("%d ", arr[i]); // 输出: 10 20 30
}
4.2.3 倒序循环
for (int i = 5; i > 0; i--) {
printf("%d ", i); // 输出: 5 4 3 2 1
}
4.2.4 多变量控制
for (int i = 0, j = 10; i < j; i++, j--) {
printf("%d-%d ", i, j); // 输出: 0-10 1-9 2-8 ... 4-6
}
4.3 for循环的灵活性
4.3.1 表达式可省略(但分号必须保留)
int i = 0;
for (; i < 5; ) { // 省略初始化和更新表达式(等效于 while 循环)
printf("%d ", i);
i++;
}
4.3.2 空循环体
for (int i = 0; i < 1000000; i++); // 空循环,常用于延时
4.3.3 嵌套循环
for (int i = 0; i < 3; i++) { // 外层循环
for (int j = 0; j < 2; j++) { // 内层循环
printf("(%d,%d) ", i, j); // 输出: (0,0) (0,1) (1,0) (1,1) (2,0) (2,1)
}
}
4.4 for vs while 的对比
| 特性 | for 语句 | while 语句 |
|---|---|---|
| 代码结构 | 集成初始化、条件、更新,结构紧凑 | 初始化在循环外,更新在循环体内 |
| 适用场景 | 循环次数已知或需要明确控制变量 | 循环次数不确定或动态条件 |
| 变量作用域 | C99起支持循环内变量声明(局部作用域) | 变量需在循环外声明 |
| 可读性 | 适合固定模式的循环,逻辑集中 | 适合复杂条件或动态退出逻辑 |
4.5 注意事项
4.5.1 避免无限循环
-
错误示例:条件表达式永真。
for (int i = 0; i >= 0; i++) { // i 始终 ≥0,无限循环 printf("%d ", i); }
4.5.2 循环变量作用域(C99起)
-
循环内声明变量:仅在循环体内有效。
for (int i = 0; i < 5; i++) { printf("%d ", i); // i 仅在循环内可见 } // printf("%d", i); // 错误:i 未定义
4.5.3 浮点数循环的精度问题
-
错误示例:浮点数精度丢失导致循环次数异常。
for (float x = 0.1; x != 1.0; x += 0.1) { // 可能无限循环 printf("%f ", x); }修正:改用整数控制循环。
for (int i = 1; i <= 10; i++) { float x = i * 0.1; printf("%f ", x); }
4.6 高级用法
4.6.1 逗号运算符
-
在初始化或更新表达式中使用逗号分隔多个操作。
for (int i = 0, j = 10; i < j; i++, j--) { printf("%d-%d ", i, j); // 输出: 0-10 1-9 ... 4-6 }
4.6.2 循环控制语句
-
break:立即退出整个循环。
for (int i = 0; i < 10; i++) { if (i == 5) break; // 循环在 i=5 时终止 printf("%d ", i); // 输出: 0 1 2 3 4 } -
continue:跳过本次循环剩余代码,进入下一轮循环。
for (int i = 0; i < 5; i++) { if (i == 2) continue; printf("%d ", i); // 输出: 0 1 3 4 }
4.7 总结
| 特性 | 说明 |
|---|---|
| 核心功能 | 通过初始化、条件、更新表达式实现紧凑的循环控制 |
| 适用场景 | 固定次数循环、数组遍历、多变量控制 |
| 优势 | 结构清晰,集成循环控制逻辑,减少代码冗余 |
| 常见错误 | 浮点数精度问题、无限循环、变量作用域混淆 |
| 与while对比 | for更紧凑,适合明确循环次数;while更灵活,适合动态条件循环 |
1820

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



