本讲定位:二级最难的一讲,也是二级编程题的主要考点。官方大纲要求”掌握多层循环结构,掌握
for语句、while语句、do...while语句,及相互嵌套的方法”。一级第 08 讲学的是”一段代码跑 n 遍”;这一讲要理解的是”跑 n 遍的那段代码,本身又跑了 m 遍”——总共 $n \times m$ 遍。学生在这里的掉队率比一级第 08 讲还高,因为两个循环变量同时在动,脑子跟不上。本讲的解法只有一个:手工模拟表,而且要画得比一级更细。对应官方大纲:二级知识块 7「多层循环语句」——
while循环、do...while循环、for循环的嵌套。前置知识:一级第 08 讲(三种循环、
break/continue、手工模拟表)、二级第 06 讲(嵌套的层次梳理)。一级第 08 讲没吃透的学生,本讲必然崩盘——请先回去补。代码说明:本讲所有代码均已用 g++ 11.5(
-std=c++11)编译运行验证,输出结果即为文中标注结果。
下面程序的输出是什么?
for (int i = 1; i <= 2; i++) { for (int j = 1; j <= 3; j++) { cout << i << j << " "; } }
学生的典型错误答案是 11 22(以为两个循环变量”手拉手”一起走)。
正确答案:
11 12 13 21 22 23
规律:外层 i 每取一个值,内层 j 要把 1、2、3 完整跑一遍**。** 所以一共输出 $2 \times 3 = 6$ 组。
这就是循环嵌套的全部秘密,本讲剩下的内容都是它的应用。
外层走一步,内层走一圈。总执行次数 = 外层次数 × 内层次数。内层的循环变量,每次进入内层都要重新初始化。
这是本讲的核心工具,比一级的模拟表多了一列。
以第 1 节的代码为例:
外层 i |
内层 j |
输出 | 说明 |
|---|---|---|---|
| 1 | 1 | 11 |
内层第 1 圈开始 |
| 1 | 2 | 12 |
|
| 1 | 3 | 13 |
|
| 1 | 4 | — | 4 <= 3 假,内层结束,回外层 |
| 2 | 1 | 21 |
⚠️ j 重新从 1 开始 |
| 2 | 2 | 22 |
|
| 2 | 3 | 23 |
|
| 2 | 4 | — | 内层结束 |
| 3 | — | — | 3 <= 2 假,外层结束 |
⚠️⚠️ 表中标 ⚠️ 的那一行是全讲最重要的一行:外层进入第 2 轮时,
j又变回 1 了。因为for (int j = 1; ...)这句初始化,每次进入内层循环都会重新执行一次。学生最常犯的错就是以为
j会接着上次的 4 继续走。画表时一定要把这一步显式写出来。