Kodewick
第 7 课,共 30 课目录

break、continue 和嵌套循环

第 7 课,共 30 课 · 第 1 部分 · 起步 · 约 15 分钟

上一课的循环都是老老实实地转完,直到条件不成立。可有时候事情做完了,没必要再转;有时候这一圈不想做,想直接跳到下一圈。这一课讲 break 和 continue,再讲循环里面再放一个循环。

main.c
1#include <stdio.h>2 3int main(void) {4    for (int n = 51; n <= 100; n++) {5        if (n % 7 == 0) {6            printf("找到了:%d\n", n);7            break;8        }9    }10    printf("不找了\n");11    return 0;12}
输出
找到了:56
不找了

要找的是大于 50 的第一个 7 的倍数。找到 56 就够了,break 让循环马上结束,57 到 100 都不用再试。

break:马上结束循环

break 一跑,整个循环就结束了,程序跳到循环后面接着跑,循环体里 break 后面的代码也不会再跑。

break 常和 while (1) 一起用。1 永远是真,所以这个循环自己停不下来,**唯一的出口就是 break**。比如手里有 50 元,一件东西 12 元,能买几件:

main.c
1#include <stdio.h>2 3int main(void) {4    int budget = 50;5    int spent = 0;6    int items = 0;7    while (1) {8        if (spent + 12 > budget) {9            break;10        }11        spent += 12;12        items++;13    }14    printf("买了 %d 件,花了 %d 元\n", items, spent);15    return 0;16}
输出
买了 4 件,花了 48 元

点单步,看第五圈:spent + 12 是 60,超过了 50,break 跳出循环,后面的 spent += 12; 没有跑。

小技巧: 写 while (1) 时,一定要确认 break 总有一天会跑到,不然就是死循环。

continue:跳过这一圈

continue 不结束循环,只是跳过这一圈剩下的代码,直接进入下一圈。在 for 里,下一圈之前照样会跑 i++。下面显示 1 到 10,跳过 3 的倍数:

main.c
1#include <stdio.h>2 3int main(void) {4    for (int i = 1; i <= 10; i++) {5        if (i % 3 == 0) {6            continue;7        }8        printf("%d ", i);9    }10    printf("\n");11    return 0;12}
输出
1 2 4 5 7 8 10 
先猜一猜

这段程序显示几行?

1#include <stdio.h>2 3int main(void) {4    for (int i = 1; i <= 5; i++) {5        if (i == 3) {6            continue;7        }8        if (i == 5) {9            break;10        }11        printf("%d\n", i);12    }13    return 0;14}

在 while 里用 continue 要小心:如果 i++ 写在循环体的最后,continue 会把它也跳过,i 就再也不变了,变成死循环。所以要在 continue 之前先让变量变好,或者改用 for。

循环里套循环

循环体里可以再放一个循环,叫嵌套循环。外面的循环每转一圈,里面的循环都要从头到尾转完一整遍:

main.c
1#include <stdio.h>2 3int main(void) {4    for (int i = 1; i <= 2; i++) {5        for (int j = 1; j <= 3; j++) {6            printf("i = %d, j = %d\n", i, j);7        }8    }9    return 0;10}
输出
i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 2, j = 1
i = 2, j = 2
i = 2, j = 3

外面 2 圈,里面每次 3 圈,一共 6 行。点单步,看 j 怎么一次次地从 1 重新开始。

用嵌套循环可以打出一张乘法表。外面的 i 管第几行,里面的 j 管这一行的第几个,j 只走到 i:

main.c
1#include <stdio.h>2 3int main(void) {4    for (int i = 1; i <= 5; i++) {5        for (int j = 1; j <= i; j++) {6            printf("%d×%d=%-4d", j, i, i * j);7        }8        printf("\n");9    }10    return 0;11}
输出
1×1=1   
1×2=2   2×2=4   
1×3=3   2×3=6   3×3=9   
1×4=4   2×4=8   3×4=12  4×4=16  
1×5=5   2×5=10  3×5=15  4×5=20  5×5=25  

注意 printf("\n") 的位置:它在里面的循环外面、外面的循环里面,所以每一行结束时换一次行。

画三角形

同样的办法,把数换成星号,就能画出图形。第 row 行打 row 个 *:

main.c
1#include <stdio.h>2 3int main(void) {4    int height = 4;5    for (int row = 1; row <= height; row++) {6        for (int k = 1; k <= row; k++) {7            printf("*");8        }9        printf("\n");10    }11    return 0;12}
输出
*
**
***
****

画图形时,先想清楚每一行要打几个字符,和行号是什么关系,再写里面那个循环的条件。

break 只跳出一层

在嵌套循环里,break 只结束它所在的那一层循环,外面的循环照样转:

main.c
1#include <stdio.h>2 3int main(void) {4    for (int i = 1; i <= 3; i++) {5        for (int j = 1; j <= 3; j++) {6            if (j == 2) {7                break;8            }9            printf("i = %d, j = %d\n", i, j);10        }11    }12    return 0;13}
输出
i = 1, j = 1
i = 2, j = 1
i = 3, j = 1

想一找到就把两层都结束,可以用一个变量做记号:里面找到了,先把记号设成 1 再 break;外面每一圈结束时看看记号,是 1 就也 break。下面找第一对乘起来等于 12 的数:

main.c
1#include <stdio.h>2 3int main(void) {4    int found = 0;5    for (int i = 1; i <= 9; i++) {6        for (int j = 1; j <= 9; j++) {7            if (i * j == 12) {8                printf("%d × %d = 12\n", i, j);9                found = 1;10                break;11            }12        }13        if (found) {14            break;15        }16    }17    return 0;18}
输出
2 × 6 = 12

把外面那个 if (found) 删掉再运行,看看会多出哪几行。

变量在哪里能用

在花括号里声明的变量,只在这对花括号里能用;在 for 的括号里声明的 i,只在这个循环里能用。循环结束后再用它,编译不过:

main.c
1#include <stdio.h>2 3int main(void) {4    for (int i = 1; i <= 3; i++) {5        int square = i * i;6        printf("%d\n", square);7    }8    printf("%d\n", i);9    return 0;10}
输出
main.c: In function 'main':
main.c:8:20: error: 'i' undeclared (first use in this function)
    8 |     printf("%d\n", i);
      |                    ^
main.c:8:20: note: each undeclared identifier is reported only once for each function it appears in

编译器说 'i' undeclared,也就是 i 没有声明:在第 8 行,i 已经不存在了。square 也一样,而且它每一圈都是新的,上一圈的值留不下来。循环结束后还要用的变量,要在循环前面声明,比如把 int i; 写在 for 之前,再写 for (i = 1; i <= 3; i++)。变量能用的范围叫作用域,第 9 课再细讲。

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。

练习 1

第一个平方超过 200 的数

从 1 开始一个一个地试,找到第一个平方大于 200 的数,显示它(15),然后用 break 结束循环。

要显示
15
exercise1.c
1#include <stdio.h>2 3int main(void) {4    for (int n = 1; n <= 100; n++) {5 6    }7    return 0;8}
输出
点「运行」或按 Ctrl+Enter
练习 2

跳过 4 的倍数

把 1 到 20 加起来,但跳过 4 的倍数,用 continue 写。显示结果 150。

要显示
150
exercise2.c
1#include <stdio.h>2 3int main(void) {4    int total = 0;5    for (int i = 1; i <= 20; i++) {6 7        total += i;8    }9    printf("%d\n", total);10    return 0;11}
输出
点「运行」或按 Ctrl+Enter
练习 3

倒过来的三角形

用嵌套循环显示一个倒过来的三角形:第一行 4 个 *,每行少一个,最后一行 1 个。

要显示
****
***
**
*
exercise3.c
1#include <stdio.h>2 3int main(void) {4    int height = 4;5 6    return 0;7}
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • break 马上结束循环;while (1) 只能靠 break 出来,要确认它一定会跑到。
  • continue 跳过这一圈剩下的代码,进入下一圈;在 while 里小心别把让变量变的那一行也跳过了。
  • 嵌套循环:外面每转一圈,里面都从头转完一整遍;乘法表和三角形都是这样打出来的。
  • 嵌套循环里的 break 只跳出一层;要两层都结束,用一个记号变量。
  • 在花括号里或 for 的括号里声明的变量,出了那个范围就不能用了。