程序并不是把语句从上到下机械地执行一遍。面对不同输入,它需要做出选择;遇到重复任务,它需要自动执行多次;在特殊情况下,还要提前结束当前操作。分支、循环和跳转语句,正是 c 语言组织执行流程的基本工具。
本文从实际编程场景出发,梳理这些语句的写法、执行规律和常见陷阱,并通过几个小案例说明它们如何组合成完整的程序逻辑。
一、先理解条件表达式
c 语言会把条件表达式的结果当作真假使用:
0表示假;- 任何非零值都表示真。
因此,下面两种写法都可以进入分支:
if (1) {
printf("条件成立\\n");
}
int value = -3;
if (value) {
printf("非零值也会被视为真\\n");
}实际开发中,条件最好写得明确,例如 score >= 60,这样更容易阅读和维护。
二、用 if 处理二选一和多路判断
1. 基本形式
if 用来判断一个条件是否成立:
if (条件表达式) {
/* 条件为真时执行 */
}
当需要提供另一条路径时,可以加入 else:
if (age < 18) {
printf("未成年\\n");
} else {
printf("成年\\n");
}如果存在多个区间或多个互斥条件,可以使用 else if:
if (age < 18) {
printf("青少年\\n");
} else if (age < 30) {
printf("青年\\n");
} else if (age < 50) {
printf("中年\\n");
} else if (age < 80) {
printf("中老年\\n");
} else {
printf("高龄阶段\\n");
}条件可以通过逻辑运算符组合。&& 表示“并且”,|| 表示“或者”,! 表示“非”。例如,age >= 18 && age < 30 表示年龄处于 18(含)到 30(不含)之间。
2. 语句块和大括号
if 后面如果只有一条语句,大括号可以省略;但只要分支中包含多条语句,就应使用 {}:
if (score >= 60) {
printf("及格\\n");
printf("可以进入下一阶段\\n");
}即使当前只有一条语句,也建议保留大括号。这样在以后增加代码时,不容易因为缩进误导而产生逻辑错误。
3. 小心悬空 else
当 if 嵌套而没有大括号时,else 总是与最近的、尚未匹配的 if 配对:
if (a == 1)
if (b == 2)
printf("hehe\\n");
else
printf("haha\\n");
这里的 else 属于内层 if (b == 2),而不是外层 if (a == 1)。想表达清楚,应显式写出大括号:
if (a == 1) {
if (b == 2) {
printf("hehe\\n");
}
} else {
printf("haha\\n");
}
4. 让比较更不容易写错
赋值运算符是 =,相等比较运算符是 ==。为了减少把 == 误写成 = 的风险,可以把常量放在左侧:
if (5 == number) {
printf("number 等于 5\\n");
}
如果误写成 5 = number,编译器会直接报错;而 number = 5 在语法上是合法的,却可能悄悄改变程序逻辑。
三、用 switch 表达多路选择
当一个表达式需要与多个固定值比较时,switch 通常比很长的 if...else if 更清晰:
switch (day) {
case 1:
printf("星期一\\n");
break;
case 2:
printf("星期二\\n");
break;
default:
printf("输入无效\\n");
break;
}
case 后面跟常量表达式和冒号。程序匹配到某个 case 后,会从该位置继续执行;break 用来跳出整个 switch。如果忘记 break,就会继续执行后面的分支,这种行为叫“贯穿”。
贯穿有时是有意的,例如把 1 到 5 归为工作日:
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
printf("weekday\\n");
break;
case 6:
case 7:
printf("weekend\\n");
break;
default:
printf("invalid day\\n");
break;
}
default 用于处理所有未匹配的值。它不是强制项,但为异常输入提供处理路径通常更稳妥。一个 switch 中最多只能有一个 default,它可以放在任意位置。
四、while:先判断,再重复
while 适合“只要条件成立就继续”的场景:
while (条件表达式) {
/* 循环体 */
}
例如打印 1 到 10:
int i = 1;
while (i <= 10) {
printf("%d ", i);
i++;
}
循环变量必须在循环体中得到正确更新,否则条件可能永远成立,程序就会陷入死循环。
break:立即结束循环
break 会直接结束它所在的那一层循环:
int i = 1;
while (i <= 10) {
if (i == 5) {
break;
}
printf("%d ", i);
i++;
}
输出为 1 2 3 4。在菜单退出、密码验证成功、查找命中等场景中,break 都很常用。
continue:跳过本轮剩余代码
continue 不会结束循环,它只会跳过本轮循环后面的语句,直接进入下一次条件判断:
int i = 0;
while (i < 10) {
i++;
if (i == 5) {
continue;
}
printf("%d ", i);
}
这段代码会跳过数字 5。使用 continue 时尤其要注意循环变量的更新位置。如果把 i++ 放在 continue 之后,那么当 i == 5 时更新语句永远不会执行,循环就可能无限进行。
continue 也适合过滤输入。例如只输出输入流中的数字字符:
int ch;
while ((ch = getchar()) != eof) {
if (ch < '0' || ch > '9') {
continue;
}
putchar(ch);
}
五、for:把循环控制集中起来
当循环具有清晰的初始化、条件判断和步进过程时,for 往往更简洁:
for (初始化; 条件; 调整) {
/* 循环体 */
}
打印 1 到 10:
for (int i = 1; i <= 10; i++) {
printf("%d ", i);
}
三部分的执行顺序是:先执行初始化;再判断条件,条件为真才进入循环体;循环体执行完后执行调整表达式,然后回到条件判断。
for 和 while 可以实现相同功能,但 for 将循环控制信息集中在一行,阅读和修改通常更方便。实际使用时,建议让循环变量只在一个明确的位置初始化、判断和更新。
break 和 continue 在 for 中
两者在 for 中的含义与 while 基本一致:
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // 结束整个循环
}
printf("%d ", i);
}
for (int i = 1; i <= 10; i++) {
if (i == 5) {
continue; // 跳过本轮,随后执行 i++
}
printf("%d ", i);
}与 while 不同的是,for 的调整表达式会在循环体结束时执行,即使本轮通过 continue 结束,也会执行 i++。
for 的一些写法
初始化、条件和调整部分都可以省略,但分号必须保留:
for (;;) {
/* 无限循环,需要通过 break 等方式退出 */
}
也可以在一个 for 中操作多个变量:
for (int x = 0, y = 0; x < 2 && y < 5; x++, y++) {
printf("x=%d, y=%d\\n", x, y);
}
嵌套 for 常用于遍历二维数据或生成图形。需要特别注意内层循环变量的初始化位置,避免因为变量没有重新初始化而导致内层循环只执行一次。
此外,条件中使用 = 而不是 == 是一个典型错误。例如 for (i = 0; k = 0; i++, k++) 中的 k = 0 是赋值,结果为 0,条件一开始就是假,循环体一次也不会执行。
六、do…while:至少执行一次
do...while 先执行循环体,再判断条件:
do {
/* 循环体 */
} while (条件表达式);
注意 while 后面要有分号。它适合菜单交互、输入校验等“必须先执行一次”的场景:
int choice;
do {
printf("1. 开始\\n");
printf("0. 退出\\n");
scanf("%d", &choice);
} while (choice != 0);
即使初始条件为假,循环体也会执行一次:
int i = 10;
do {
printf("%d\\n", i);
i++;
} while (i < 10);
break 和 continue 同样可以出现在 do...while 中。使用 continue 时,要确保循环变量在跳转前已经更新,否则也可能造成死循环。
七、循环嵌套与流程控制
循环可以嵌套,break 默认只结束当前所在的那一层。例如在两层循环中,内层 break 不会自动跳出外层循环。
对于需要一次性离开多层嵌套的特殊场景,c 语言提供了 goto:
for (...) {
for (...) {
if (发生严重错误) {
goto error;
}
}
}
error:
printf("处理错误并退出\\n");goto 可以简化某些多层嵌套中的错误清理流程,但大量使用会让代码跳跃难以追踪。多数情况下,可以通过函数、标志变量、break 或 return 让流程更清晰。是否使用 goto,关键在于它是否让控制流更容易理解。
八、把语句组合成实用程序
1. 计算阶乘
阶乘天然适合用循环表达:
#include <stdio.h>
int main(void) {
int n;
long long result = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
result *= i;
}
printf("%lld\\n", result);
return 0;
}如果还要计算 1! + 2! + ... + 10!,可以在同一个循环中逐步更新阶乘并累加,避免每一项都从 1 重新计算。
2. 密码最多尝试三次
for 负责限制次数,break 负责在验证成功后提前结束:
#include <stdio.h>
#include <string.h>
int main(void) {
char password[32];
int i;
for (i = 0; i < 3; i++) {
printf("请输入密码:");
scanf("%31s", password);
if (strcmp(password, "password") == 0) {
break;
}
}
if (i == 3) {
printf("尝试次数用尽\\n");
} else {
printf("登录成功\\n");
}
return 0;
}3. 在有序数组中进行二分查找
二分查找每次把搜索范围缩小一半,数组必须已经按升序排列:
int binary_search(const int arr[], int left, int right, int key) {
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] > key) {
right = mid - 1;
} else if (arr[mid] < key) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}循环结束后返回 -1 表示没有找到目标。写成 left + (right - left) / 2,比直接使用 (left + right) / 2 更能避免整数相加溢出。
4. 猜数字游戏
猜数字游戏可以把多种流程控制语句组合起来:外层 do...while 负责反复显示菜单,switch 处理用户选择,内部 while 负责持续猜测,break 在猜中时结束本轮游戏。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int choice;
srand((unsigned)time(null));
do {
printf("1. 开始游戏\\n");
printf("0. 退出\\n");
printf("请选择:");
scanf("%d", &choice);
switch (choice) {
case 1: {
int target = rand() % 100 + 1;
int guess;
while (1) {
printf("请输入 1 到 100 的数字:");
scanf("%d", &guess);
if (guess > target) {
printf("猜大了\\n");
} else if (guess < target) {
printf("猜小了\\n");
} else {
printf("猜对了!\\n");
break;
}
}
break;
}
case 0:
break;
default:
printf("无效选择,请重试\\n");
break;
}
} while (choice != 0);
return 0;
}这个例子体现了一个重要思路:复杂程序通常不是依赖某一种语句,而是把“判断、重复、提前结束”组合起来,形成清晰的状态变化。
九、写好流程控制代码的几个习惯
- 给嵌套分支和循环加上大括号,避免
else配对和缩进带来的误解。 - 区分
=与==,条件判断中尽量使用有意义、易读的表达式。 - 检查循环变量是否一定会更新,尤其要关注
continue跳过的路径。 - 使用
switch时明确是否需要贯穿,并在每组逻辑结束处写出break。 - 为输入提供
default或错误处理,避免程序面对异常值时行为不明确。 - 让一个循环只负责一件主要事情;嵌套过深时,可以考虑拆分函数。
- 对无限循环设置明确的退出条件,避免程序无法返回。
结语
分支决定程序“走哪条路”,循环决定程序“重复多少次”,跳转语句则负责在必要时改变当前执行节奏。掌握这些语句的语法只是起点,更重要的是理解它们的执行顺序、作用范围和边界条件。
当你能够熟练地把 if、switch、while、for、do...while、break 和 continue 组合起来,就可以从简单的判断题、循环题,逐步写出登录验证、查找算法和交互式小游戏等完整程序。清晰的控制流,是写出可靠 c 程序的基础。
到此这篇关于c语言分支与循环语句的文章就介绍到这了,更多相关c语言分支与循环语句内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论