在 C 语言的学习过程中,循环是处理重复任务的利器,而循环中的跳转语句 break、continue 以及更加自由的 goto 则是精确控制流程的关键。今天这篇超详细文章将带你从基础语法出发,结合大量练习,层层深入,彻底吃透这些看似简单却容易混淆的知识点。文中的每一个示例都来自经典课堂练习,我会逐行分析、补充原理、总结易错细节,让你不仅会写,更能理解背后的执行逻辑。
break 不能单独出现,它必须搭配 switch 选择结构或者循环结构(for、while、do-while)使用。它的作用是立即终止当前所在的整个循环,程序会跳到循环之后的语句继续执行。如果是嵌套循环,break 只能跳出它所直接隶属的那一层循环。
for (int i = 1; i <= 100; i++) {
if (i % 3 == 0 && i % 5 == 0) {
printf("%d\n", i);
break;
}
}详细解析:
核心要点:
continue 也只能写在循环内部,它的作用是结束本次循环,直接进入下一次循环的条件判断和迭代。对于 for 循环,执行 continue 后会立即跳转到循环更新部分(如 i++),然后进行条件检查;对于 while 循环,则会直接回到条件判断。
for (int i = 1; i <= 5; i++) {
if (i == 3) {
printf("这个%d包子有虫子\n", i);
continue;
}
printf("在吃第%d个包子\n", i);
}运行结果:
在吃第1个包子
在吃第2个包子
这个3包子有虫子
在吃第4个包子
在吃第5个包子详细解析:
核心要点:
当循环中出现嵌套时,最有效的分析方法是从内向外看:先把最内层的循环逻辑搞明白,然后把整个内层循环当作一个整体,放到外层循环中重复执行。这种思维能帮助我们快速理解二维图形打印、乘法表等复杂输出。
细节提示:
for (int i = 1; i <= 5; i++) { // 外层:控制行
for (int j = 1; j <= 5; j++) { // 内层:控制每一行的星号数
printf("*");
}
printf("\n"); // 一行结束后换行
}解析:
*,连续输出 5 个。/*
预期输出:
*****
****
***
**
*
*/
for (int i = 1; i <= 5; i++) {
for (int j = i; j <= 5; j++) {
printf("*");
}
printf("\n");
}解析:
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= i; j++) {
printf("*");
}
printf("\n");
}解析:
\tfor (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
int temp = i * j;
printf("%d * %d = %d\t", j, i, temp);
}
printf("\n");
}输出格式分析:
关于 \t 的细节:
问题: 统计 1~100 范围内有多少个质数(也叫素数)。
质数定义: 大于 1 的自然数中,除了 1 和它本身以外不再有其他因数。也就是说,对于数 n(n>1),如果存在整数 m(1 < m < n)能整除 n,则 n 不是质数。
int count = 0;
for (int j = 2; j <= 100; j++) {
int index = 0; // 标记是否找到因数,0 表示未找到
for (int i = 2; i < j; i++) {
if (j % i == 0) {
index++; // 找到一个能整除 j 的数
break; // 已经确定不是质数,直接跳出内循环
}
}
if (index == 0) { // 如果整个内循环都没找到因数
count++;
}
}
printf("%d", count); // 输出 25逐步解析:
优化思想:
long long rov = 0;
for (int i = 1; i <= 10; i++) {
long long pow = 1;
for (int j = 1; j <= i; j++) {
pow = pow * i; // 计算 i 的 i 次方
}
rov = rov + pow; // 累加到总和
}
printf("%lld\n", rov);详细解读:
运行结果: 总和是一个很大的数,具体为 10405071317(可以动手算一算加深记忆)。
易错提醒:
for (int i = 0; i <= 1000; i++) {
int number = i;
int sum = 0;
while (number != 0) {
int temp = number % 10; // 取出最后一位数字
number = number / 10; // 去掉最后一位
sum = sum + temp; // 累加到和
}
if (sum == 15) {
printf("%d\n", i);
}
}算法解析:
典型输出举例:
这是一个有趣的小彩蛋,利用数学不等式和双重循环在控制台打印一个心形图案。
float x, y;
for (y = 1.5f; y > -1.5f; y -= 0.1f) {
for (x = -1.5f; x < 1.5f; x += 0.05f) {
float ver = x * x + y * y - 1;
if (ver * ver * ver - x * x * y * y * y <= 0) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}原理浅析:
细节:
goto 语句允许程序无条件跳转到同一函数内带有标签(label)的任意位置。它的基本格式是:
标签名:
// 代码块
goto 标签名;#include <stdio.h>
int main() {
int i = 1;
a: printf("看看我是多少:%d\n", i);
i++;
if (i == 15) {
goto b;
} else {
goto a;
}
b: printf("看看我执行没有");
return 0;
}执行流程:
运行结果会输出:
看看我是多少:1
看看我是多少:2
...
看看我是多少:14
看看我执行没有(注意当 i 变成 15 时直接跳转,不会执行标签 a 后的打印,所以只显示到 14。)
虽然 goto 很灵活,但在结构化程序设计中应尽量避免使用,因为它会破坏代码的模块性和可读性,使程序流程变得混乱,容易产生所谓的“意大利面条式代码”。在大多数情况下,break、continue、函数调用、循环和条件语句已经能够清晰表达所有逻辑。
少数合理的应用场景:
在初学阶段,请将 goto 作为一种语法了解,实际编程时优先使用结构化控制流。
通过以上十个循序渐进的练习,我们全面梳理了 C 语言循环控制中的关键概念:
| 语句/技术 | 作用 | 注意事项 |
|---|---|---|
break | 立即终止当前循环 | 只能跳出最近一层循环;常与条件配合 |
continue | 跳过本次循环剩余部分,进入下一次迭代 | 在 for 中仍会执行更新表达式;注意避免死循环 |
| 循环嵌套 | 多重循环实现二维问题 | 从内向外分析,外层控制整体重复次数 |
\t 制表符 | 动态对齐输出 | 基于制表位,与前面内容长度有关 |
goto | 无条件跳转到标签 | 强大但易滥用,慎用! |