【C语言】分支和循环(上)
程序流程控制是编程语言中用于设定代码执行顺序的核心部分。通过流程控制,我们可以实现条件判断、循环执行等复杂的逻辑,让程序变得"智能"。本文将详细梳理C语言中的分支与循环结构。
1. if 语句
if 语句是C语言中最基本的分支判断结构,用于根据条件的真假来决定是否执行某段代码。
1.1 if
if 语句的基本形式是,如果括号内的条件表达式为真(非0),则执行其后的语句。
c
int age = 20;
if (age >= 18) {
printf("已成年。\n");
}
1.2 else
else 与 if 配对使用,用于指定当 if 的条件为假(0)时需要执行的代码。
c
int temperature = 15;
if (temperature > 25) {
printf("天气炎热。\n");
} else {
printf("天气凉爽。\n");
}
1.3 分支中包含多条语句
当 if 或 else 分支需要执行的语句超过一条时,必须使用花括号 {} 将这些语句包裹起来,形成一个代码块。这是一个非常重要的编程规范。
c
int is_logged_in = 1;
if (is_logged_in) {
printf("欢迎回来!\n");
printf("正在加载您的个人资料...\n");
} else {
printf("您尚未登录。\n");
printf("请先登录再进行操作。\n");
}
1.4 嵌套if
if 语句内部可以包含另一个 if 语句,形成嵌套结构,以实现更复杂的逻辑判断。
c
int score = 85;
if (score >= 60) {
printf("及格。\n");
if (score >= 80) {
printf("成绩良好。\n");
}
} else {
printf("不及格。\n");
}
1.5 悬空else问题
当存在多个 if 和 else,但没有使用花括号时,else 会遵循就近原则 ,与离它最近且尚未配对的 if 结合。
c
int a = 0, b = 2;
if (a == 1)
if (b == 2)
printf("A\n");
else // 这个else与 if(b == 2) 配对,而不是 if(a == 1)
printf("B\n");
由于 a == 1 为假,整个外层 if 不执行,因此屏幕上什么都不会输出。为了避免这种混淆,最佳实践是始终为 if 和 else 分支使用花括号,即使只有一条语句。
2. 关系操作符
关系操作符用于比较两个值,其结果为"真"(在C中通常表示为1)或"假"(表示为0)。
>: 大于<: 小于>=: 大于等于<=: 小于等于==: 等于(注意:是两个等号,一个等号是赋值)!=: 不等于
3. 条件操作符
条件操作符,也称为三元(或三目)操作符,是C语言中唯一一个需要三个操作数的运算符。它提供了一种 if-else 语句的紧凑写法。
语法 :条件 ? 表达式1 : 表达式2
如果"条件"为真,则整个表达式的值为"表达式1"的值;否则为"表达式2"的值。
c
int a = 10, b = 20;
int max = (a > b) ? a : b; // 如果 a > b,max = a;否则 max = b
printf("最大值是: %d\n", max); // 输出 20
4. 逻辑操作符: &&, ||, !
逻辑操作符用于组合或修改关系表达式。
4.1 逻辑取反运算符 !
! 用于对一个表达式的逻辑值取反。真变假,假变真。
c
int is_open = 0; // 0 表示假
if (!is_open) { // !is_open 为真
printf("门是关着的。\n");
}
4.2 与运算符 &&
&& 表示逻辑"与"。只有当两边的表达式都为真时,整个表达式的结果才为真。
4.3 或运算符 ||
|| 表示逻辑"或"。只要两边的表达式中有一个为真,整个表达式的结果就为真。
4.4 练习:闰年的判断
一个年份是闰年的条件是:能被4整除但不能被100整除,或者能被400整除。
c
int year = 2024;
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
printf("%d 是闰年。\n", year);
}
4.5 短路
逻辑运算符 && 和 || 具有短路求值的特性。
- 对于
expr1 && expr2,如果expr1为假,则expr2不会被求值,因为整个表达式的结果已确定为假。 - 对于
expr1 || expr2,如果expr1为真,则expr2不会被求值 ,因为整个表达式的结果已确定为真。
这个特性常用于在执行某个操作前先进行条件检查。
5. switch 语句
switch 语句是另一种分支结构,适用于根据一个整数或字符表达式的多个不同取值来执行不同的代码块。
5.1 if语句和switch语句的对比
if-else适用于范围判断和复杂的逻辑组合。switch适用于对一个变量的多个离散常量值进行判断,代码结构通常更清晰。
5.2 switch语句中的 break
在 switch 结构中,case 只是一个入口标签。如果没有 break,程序会从匹配的 case 开始,穿透 并执行后续所有 case 和 default 的代码,直到遇到 break 或 switch 语句结束。因此,通常每个 case 块的末尾都需要一个 break。
5.3 switch语句中的 default
default 子句是可选的。当表达式的值与所有 case 的常量值都不匹配时,default 后的代码块会被执行。
5.4 switch语句中的 case 和 default 的顺序问题
case 和 default 标签的出现顺序是任意的,不影响逻辑。但为了代码的可读性,通常将 default 放在所有 case 之后。
c
char grade = 'B';
switch (grade) {
case 'A':
printf("优秀\n");
break;
case 'B':
printf("良好\n");
break;
case 'C':
printf("及格\n");
break;
default:
printf("不及格\n");
break;
}
6. while 循环
while 循环用于在给定条件为真时,重复执行一段代码。
6.1 if 和 while 的对比
if:只进行一次条件判断,代码块最多执行一次。while:每次执行完循环体后,会再次进行条件判断,只要条件为真,就不断重复执行。
6.2 while语句的执行流程
- 判断
while后的条件是否为真。 - 如果为假,跳出循环。
- 如果为真,执行循环体内的代码。
- 执行完毕后,返回第1步。
6.3 while循环的实践与练习
计算1到100的累加和。
c
int i = 1;
int sum = 0;
while (i <= 100) {
sum += i;
i++;
}
printf("总和为: %d\n", sum);
7. for 循环
for 循环提供了一种更紧凑的循环结构,特别适合在循环次数已知的情况下使用。它将初始化、条件判断和更新三个部分集中在一起。
语法 :for (初始化; 条件; 更新)
c
// 使用for循环计算1到100的累加和
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
printf("总和为: %d\n", sum);
8. do-while 循环
do-while 循环与 while 类似,但它保证循环体至少被执行一次,因为它的条件判断在循环体执行之后。
8.1 语法形式与执行流程
- 执行
do后面的循环体。 - 执行完毕后,判断
while后的条件是否为真。 - 如果为真,返回第1步。
- 如果为假,跳出循环。
8.2 do while循环的实例与练习
一个简单的菜单程序,至少显示一次菜单。
c
#include <stdio.h>
int main() {
int choice;
do {
printf("请输入选项 (输入0退出): ");
scanf("%d", &choice);
// ... 处理选项 ...
} while (choice != 0);
printf("程序退出。\n");
return 0;
}```
9. break和continue语句
break 和 continue 用于在循环内部提供更精细的控制。
break:立即终止 并跳出当前所在的整个循环(for,while,do-while)或switch语句。continue:跳过 本次循环中continue之后的剩余语句,并立即开始下一次循环的迭代。
9.1 在各种循环中使用
- break举例:在1到10中寻找第一个能被7整除的数。
c
for (int i = 1; i <= 10; i++) {
if (i % 7 == 0) {
printf("找到了: %d\n", i);
break; // 找到后立即退出循环
}
}
- continue举例:打印1到10之间所有的奇数。
c
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) { // 如果是偶数
continue; // 跳过本次循环的printf,直接进入下一次迭代
}
printf("%d ", i);
}
10. 循环的嵌套
一个循环体内可以包含另一个完整的循环结构,形成嵌套循环。
10.1 练习:打印9x9乘法表
c
#include <stdio.h>
int main() {
// 题目解析:外层循环控制行(1到9),内层循环控制列。
// 列的范围取决于当前是第几行。
for (int i = 1; i <= 9; i++) { // 外层循环,控制行
for (int j = 1; j <= i; j++) { // 内层循环,控制列
printf("%d*%d=%-2d ", j, i, i * j); // %-2d表示左对齐,占2位宽度
}
printf("\n"); // 每打印完一行后换行
}
return 0;
}
11. goto 语句
goto 语句可以实现程序在任意位置之间的无条件跳转。它需要配合一个标签使用。
c
// 示例(不推荐使用)
goto end_label;
printf("这行代码不会被执行\n");
end_label:
printf("程序跳转到这里\n");
注意 :滥用 goto 语句会严重破坏程序的结构化,使代码逻辑混乱,难以阅读和维护,形成所谓的"意大利面条式代码"。在现代C语言编程中,应极力避免 使用 goto 语句。所有 goto 能实现的逻辑,都可以通过 if, switch, while, for, do-while 等结构化语句以更清晰的方式实现。