🔷 第五章 循环语句
📄 一句话概括

循环体里再放一个循环,就是嵌套——像时钟:分针转一圈,时针才挪一格,即外圈走一格 = 内圈走一整圈。总次数 = 外 × 内。实例07 打印三角形是经典范式:外圈管"几行"、内圈管"每行几个",内层上界跟着外层变量变(j <= i),就能打出 1、2、3……递增的星号。

📝 本节和前面几节的关系

4.5 的 if 嵌套在讲"层层设卡",本篇的循环嵌套在讲"层层重复"——同样的结构思想(外层框架 + 内层细节)。要看清嵌套的行为,靠的还是 5.2.1 的执行顺序;调试时 5.3.2 的 break 有个专属提醒:它只跳最内层。

一、嵌套的读法:外层慢、内层快

for (int i = 1; i <= 3; i++) {         // 外圈:管"几行"
    for (int j = 1; j <= 3; j++) {     // 内圈:管"每行几个"
        cout << "(" << i << "," << j << ") ";
    }
    cout << endl;                       // 一行结束换行
}

输出:

(1,1) (1,2) (1,3)
(2,1) (2,2) (2,3)
(3,1) (3,2) (3,3)

读法:i 停在 1 不动,内层 j 从头跑到尾;然后 i 才 +1,内层重新从头开始。总次数 3×3 = 9——外次数 × 内次数。

两条硬规矩: 1. 两层变量名不同(i 和 j)——都用 i 会互相踩(内层 i++ 让外层失控)。 2. 换行 endl 写在外层里、内层外——它是"一行结束"的记号,不是"一个星号"的。

二、实例 07:打印三角形

任务:打印 5 行直角三角形:

*
* *
* * *
* * * *
* * * * *
#include <iostream>
using namespace std;

int main() {
    int n = 5;                            // 行数
    for (int i = 1; i <= n; i++) {        // 外层:第 i 行
        for (int j = 1; j <= i; j++) {    // 内层:这行打 i 个
            cout << "* ";
        }
        cout << endl;                     // 换行
    }
    return 0;
}

看到什么算成功:上面那个三角形。关键点在 j <= i——内层的上界跟着外层变量走,所以第 1 行打 1 个、第 5 行打 5 个,总共 1+2+3+4+5 = 15 个星号。

变形练习(30 秒实验):把 j <= i 改成 j <= n + 1 - i——得到倒三角形(第 1 行 5 个、第 5 行 1 个)。再改成 j <= n——得到 5×5 的正方形。一个不等式,换出三种图形,这就是嵌套的威力。

三、常见误区

  1. "内外层用同一个变量名"——内层 for (int i = 1; ...) 会遮蔽外层的 i(2.1.5 作用域);编译能过,但逻辑全乱。i、j、k 顺序用最省心。
  2. "内层上界只能是常数"——可以跟外层变量走(j <= i 就是),这正是打印各种图形的开关。
  3. "break 能一次跳出两层"——不能,break 只结束它所在的最内层;内层 break 后外层继续(要一起退出得用标志变量或把嵌套抽成函数 return)。
  4. "嵌套越深越强"——三层以上就该拆(比如把内两层抽成独立循环或函数);可读性优先,和 4.5 一个道理。
自测三问(点开对答案) 1. 外层 3 圈、内层 4 圈,循环体共跑几次?——12 次(外 × 内)。 2. 三角形打印里 `j <= i` 起什么作用?——内层上界跟外层走,第 i 行打 i 个星号。 3. 内层写 break,外层会停吗?——不会,只结束内层那一圈,外层继续。

相关笔记