# 第5课:嵌套循环与图形打印 ## 教学目标 - 理解嵌套循环的执行流程(外层管行、内层管列) - 能分析图形规律,写出对应的行列公式 - 掌握矩形、直角三角形、等腰三角形、菱形的打印方法 - 掌握多层循环以及分支与循环相互嵌套的二级必考写法 ## 核心考点:嵌套循环中的行列关系 ### 考什么 题目会给出矩形、三角形或菱形,要求分析每一行应输出多少空格和符号,再用嵌套循环打印。考试重点不是背某个图形,而是能从行号推导本行各部分的数量。 ### 必须理解 外层循环每执行一次就完成一整行,因此负责行数;内层循环在当前行中重复输出,负责列数或某种字符数量。解决图形题应先列出“第 i 行有多少空格、多少星号”,再把数量写成关于 i 和总行数 n 的公式。例如等腰三角形第 i 行:前导空格 `n-i` 个,星号 `2*i-1` 个。每一类字符分别使用一个内层循环,行末统一换行。 ### 核心写法 ```cpp for (int i = 1; i <= n; i++) { for (int j = 1; j <= n - i; j++) cout << ' '; for (int j = 1; j <= 2 * i - 1; j++) cout << '*'; cout << endl; } ``` 外层的 i 表示当前行,两个内层循环的上界由 i 决定,所以每行形状都会变化。 ### 常见错误 - 把换行写进内层循环,导致每输出一个字符就换行。 - 内层循环上界始终写 n,无法随行号改变图形。 - 行号从 0 开始,却直接套用从 1 开始推导的公式。 - 只凭眼睛试代码,不先写出行号与数量表。 ### 判断是否掌握 面对新图形时,能先列前三行的空格数和符号数,推导出关于 i 的公式,再独立写出外层、内层和换行代码。 --- ## 题目一:打印实心矩形 ### 核心代码(一句话) > 嵌套循环的核心:**外层循环管行数,内层循环管列数**,两层 `for` 一套就行。 ### 自然语言思路 我们要打印一个 n 行 m 列的矩形,全是星号。 第一步,确定要印几行:n 行,所以外层循环从 1 到 n。 第二步,每一行里面要印几个星号:m 个,所以内层循环从 1 到 m。 第三步,每印完一行,记得换行 `cout << endl`。 第四步,把上面三步写成代码 —— 外层 `for` 套一个内层 `for`,里面 `cout` 星号,外面 `cout` 换行。 > 想象你在一行一行地写字:外层决定写几行,内层决定每行写几个字。 ### 伪代码 ``` 1. 输入 n, m 2. for i = 1 到 n: // 外层:控制行 3. for j = 1 到 m: // 内层:控制列 4. 输出 "* " 5. 输出换行 ``` ### 真实代码 ```cpp #include using namespace std; int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { // 外层循环:n 行 for (int j = 1; j <= m; j++) { // 内层循环:每行 m 个 cout << "* "; } cout << endl; // 每行结束换行 } return 0; } ``` ### 注意点 1. **内层循环变量名**:习惯用 `j`,因为 `i` 已经被外层用了。不要在外层和内层用同一个变量名。 2. **换行位置**:`cout << endl` 放在外层循环里面、内层循环外面,每行结束只换一次。 3. **嵌套理解口诀**:外层每走一步,内层跑完全程。就像时钟——时针走一格,分针转一整圈。 --- ## 题目二:直角三角形(左下 + 右下) ### 核心代码(一句话) > 直角三角形的核心:**第 i 行打印 i 个星号**,内层循环的终止条件用 `j <= i`。 ### 自然语言思路 **左下直角三角形**: 第一步,观察规律:第1行1个星,第2行2个星,第3行3个星……第 i 行 i 个星。 第二步,每行的星号数量**等于行号**。 第三步,内层循环写成 `for (j = 1; j <= i; j++)`,就搞定了。 **右下直角三角形**: 第一步,先看空格:第1行前面有 n-1 个空格,第2行前面有 n-2 个空格……第 i 行前面有 n-i 个空格。 第二步,空格用**另一个内层循环**先打印:`for (j = 1; j <= n - i; j++)`。 第三步,再打印星号,和第 i 行 i 个星一样。 第四步,每行顺序:先空格、后星号、再换行。 ### 伪代码 **左下直角三角形**: ``` 1. 输入 n 2. for i = 1 到 n: 3. for j = 1 到 i: // 第 i 行 i 个星 4. 输出 "* " 5. 输出换行 ``` **右下直角三角形**: ``` 1. 输入 n 2. for i = 1 到 n: 3. for j = 1 到 n-i: // 先打 n-i 个空格 4. 输出 " " // 两个空格(跟星号对齐) 5. for j = 1 到 i: // 再打 i 个星 6. 输出 "* " 7. 输出换行 ``` ### 真实代码 **左下直角三角形**: ```cpp #include using namespace std; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { // 关键:j <= i cout << "* "; } cout << endl; } return 0; } ``` **右下直角三角形**: ```cpp #include using namespace std; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { // 先打空格 for (int j = 1; j <= n - i; j++) { cout << " "; // 两个空格,跟 "* " 宽度一致 } // 再打星号 for (int j = 1; j <= i; j++) { cout << "* "; } cout << endl; } return 0; } ``` ### 注意点 1. **空格数量要对齐**:如果星号之间用 `"* "`(星号+空格),那么空格也要打印两个空格 `" "`,否则对不齐。 2. **左下直角三角形最简单**:第 i 行 = i 个星,这是所有图形打印的母题,先把这个吃透。 3. **右下 = 左下 + 空格**:右下直角就是把左下直角往右推,推的力度 = 前面的空格数。 --- ## 题目三:等腰三角形与菱形 ### 核心代码(一句话) > 等腰三角形的核心:第 i 行有 **2i - 1** 个星号,前面的空格数为 **n - i**;菱形 = 正等腰 + 倒等腰。 ### 自然语言思路 **等腰三角形**: 第一步,观察规律:n=5 时,第1行1个星,第2行3个星,第3行5个星……每行多2个星。 第二步,归纳公式:第 i 行星号数 = `2 * i - 1`。 第三步,空格规律和右下直角一样:第 i 行前面 n-i 个空格。 第四步,先打空格,再打星号,换行,搞定。 **菱形**: 第一步,把菱形拆成两半:上半 = n 行等腰三角形,下半 = n-1 行倒等腰三角形。 第二步,上半直接复用等腰三角形代码。 第三步,下半倒过来:从第 n-1 行开始,递减到第 1 行。空格和星号公式不变,只是循环方向反过来。 第四步,上下拼起来就是菱形。 ### 伪代码 **等腰三角形**: ``` 1. 输入 n 2. for i = 1 到 n: 3. for j = 1 到 n-i: // 空格:n-i 个 4. 输出 " " 5. for j = 1 到 2*i-1: // 星号:2i-1 个 6. 输出 "*" 7. 输出换行 ``` **菱形**: ``` 1. 输入 n(上半部分行数) 2. // 上半:正等腰三角形 3. for i = 1 到 n: 4. 打空格、打星号、换行(同上) 5. // 下半:倒等腰三角形 6. for i = n-1 递减到 1: 7. 打空格、打星号、换行(同上) ``` ### 真实代码 **等腰三角形**: ```cpp #include using namespace std; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { // 空格 for (int j = 1; j <= n - i; j++) { cout << " "; } // 星号:2i - 1 for (int j = 1; j <= 2 * i - 1; j++) { cout << "*"; } cout << endl; } return 0; } ``` **菱形**: ```cpp #include using namespace std; int main() { int n; cin >> n; // 上半部分:正等腰三角形 for (int i = 1; i <= n; i++) { for (int j = 1; j <= n - i; j++) cout << " "; for (int j = 1; j <= 2 * i - 1; j++) cout << "*"; cout << endl; } // 下半部分:倒等腰三角形(n-1 行) for (int i = n - 1; i >= 1; i--) { for (int j = 1; j <= n - i; j++) cout << " "; for (int j = 1; j <= 2 * i - 1; j++) cout << "*"; cout << endl; } return 0; } ``` ### 注意点 1. **等腰三角形星号公式 `2*i-1`**:这是最核心的公式,建议学生背下来。推导:第1行1个,每行多2个 → 等差数列 → 1 + 2×(i-1) = 2i-1。 2. **菱形下半部分循环递减**:`for (i = n-1; i >= 1; i--)`,注意从 `n-1` 开始,不是 `n`,否则中间那行会重复。 3. **空格只用一个空格**:等腰三角形通常用一个空格 `" "` 而不是两个,因为星号之间不加空格。 4. **如果 n=1**:下半部分 `i = 0`,`0 >= 1` 为假,不执行,只打印一行星号,也是对的。 --- ## 图形打印技巧总结 | 图形 | 第 i 行星号数 | 第 i 行空格数 | 关键点 | |------|-------------|-------------|--------| | 左下直角三角形 | `i` | 0 | 最简单,母题 | | 左上直角三角形 | `n - i + 1` | 0 | 倒过来即可 | | 右下直角三角形 | `i` | `n - i` | = 左下 + 空格 | | 右上直角三角形 | `n - i + 1` | `i - 1` | = 左上 + 空格 | | 等腰三角形 | `2i - 1` | `n - i` | 核心公式 | | 倒等腰三角形 | `2i - 1` | `n - i` | i 递减即可 | | 菱形 | 上同等腰,下同倒等腰 | 同上 | 上下拼接 | --- ## 本课打油诗 > 外层循环管行数,内层循环管列数。 > 图形打印找规律,行列关系是正路。 > 第 i 行星号看公式,空格星号分清楚。 > 等腰三角二 i 减一,菱形上下拼一處。 --- ## 课后作业 1. 输入 n,打印左上直角三角形(第1行 n 个星,第2行 n-1 个星……) 2. 输入 n,打印数字三角形(第1行1,第2行1 2……) 3. 输入 n 和 m,打印 n 行 m 列的空心矩形(只有边框有星号) 4. 输入 n,打印九九乘法表(第 i 行输出 i 个乘法式子)