适用对象: 完成了第 4 课(for 循环、累加)的同学 使用方式: 自学讲义。放在电脑旁边,边读边照着做 学完本课,你应该能:
遇到问题怎么办: 这节课最容易乱的地方是"到底谁转得快"。记住一句话:外层转一圈,内层要整个跑完一遍。
打开上节课的 t3.cpp(7
的乘法表),重新运行一遍,确认输出的是 7、14、21……63 共 9 行。
上节课结尾我说过:完整的九九乘法表(9 行 9 列)"需要循环里再套一层循环,以后学"。今天就学这个。
先看一个问题: 怎么打印 3 行星星,每行 5 个?
*****
*****
*****
上节课学的 for 只能解决"一行 5 个星星":
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int j = 1; j <= 5; j++) {
cout << "*";
}
cout << endl;
return 0;
}输出:*****
那"重复做 3 次这件事"呢?
再套一层循环就行——把上面那段整个塞进另一个 for 里:
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 3; i++) { // 外层:控制行,转 3 圈
for (int j = 1; j <= 5; j++) { // 内层:控制每行几个星星
cout << "*";
}
cout << endl; // 一行打完了,换行
}
return 0;
}输出:
*****
*****
*****
📝 外层循环转一圈,内层循环要从头到尾整个跑完一遍。 所以内层一共跑了 3 × 5 = 15 次,打出 15 个星星。
⚠️ 内层循环的变量不能和外层同名。 外层用了
i,内层就要换一个名字,习惯上用 j。两层都用
i 会互相打架。
看不见执行顺序?把 i 和 j
都打印出来:
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 3; j++) {
cout << "i=" << i << " j=" << j << endl;
}
}
return 0;
}输出:
i=1 j=1
i=1 j=2
i=1 j=3
i=2 j=1
i=2 j=2
i=2 j=3
看清楚了吗?i 一直是 1 的时候,j 已经从 1
数到 3 了;j 数完一轮,i
才敢往前走一步。内层跑得快,外层跑得慢。
新建 check1.cpp:用嵌套循环打印 2 行、每行 4 个
#。
九九乘法表长这样——注意第 1 行只有 1 个式子,第 2 行有 2 个,第 9 行有 9 个:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
...
秘密就在内层循环的"继续条件"上:内层不是固定跑到
9,而是跑到外层的 i 为止——写成
j <= i:
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) { // 注意这里是 j <= i,不是 j <= 9
cout << j << "*" << i << "=" << i * j << "\t";
}
cout << endl;
}
return 0;
}输出:
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
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
📝 "\t"
是"制表符",作用是让后面的内容对齐到下一个"跳格位置",比空格整齐得多。写在双引号里,一个反斜杠加一个字母
t。
📝 内层循环的次数可以跟着外层变。
j <= 5 是每行都一样多,j <= i
是每行越来越多——这是嵌套循环最有用的技巧。
明白了"内层次数跟着外层变",就能画三角形了。
正三角形(一行比一行多):
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= i; j++) {
cout << "*";
}
cout << endl;
}
return 0;
}输出:
*
**
***
****
*****
倒三角形(一行比一行少): 把外层改成倒着数就行:
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 5; i >= 1; i--) { // 外层从 5 倒数到 1
for (int j = 1; j <= i; j++) {
cout << "*";
}
cout << endl;
}
return 0;
}输出:
*****
****
***
**
*
错误 1:内外层用了同一个变量名
for (int i = 1; i <= 3; i++) {
for (int i = 1; i <= 5; i++) { ← 内层又叫 i!
cout << "*";
}
cout << endl;
}
编译器可能不报错(因为内层的 i 是一个"新盒子",把外层的
i 挡住了),但程序会变得极难看懂,一旦想在内层用外层的
i(比如乘法表里的 i * j)就彻底乱套。
📝 老老实实外层 i、内层 j,第三层用
k。
错误 2:endl 放错了地方
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 5; j++) {
cout << "*" << endl; ← endl 写在内层了!
}
}
本来想要 3 行、每行 5 个星星,结果每打一个星星就换一次行,变成了 15 行、每行 1 个星星。
📝 endl 写在内层 =
每个符号一行;endl 写在内层循环的后面(外层里面)=
每行一组。想清楚"什么时候该换行",endl
就该放在哪。
⭐ 基础题 1:星星长方形(文件名
t1.cpp)
打印 4 行、每行 6 个星星。
输出样例:
******
******
******
******
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 6; j++) {
cout << "*";
}
cout << endl;
}
return 0;
}⭐⭐ 实战题 2:n 行直角三角形(文件名
t2.cpp)
输入一个正整数 n,打印 n 行的星星直角三角形(第 1 行 1 个,第 n 行 n 个)。
输入样例:
6
输出样例:
*
**
***
****
*****
******
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << "*";
}
cout << endl;
}
return 0;
}内层条件写 j <= i,行数由读进来的 n
控制——这题就是把课上的正三角形改成"行数可变"。
⭐⭐⭐ 冲刺题 3:完整九九乘法表(文件名
t3.cpp)
打印完整的九九乘法表,格式 1*1=1,同一行的式子之间用
"\t" 隔开,第 i 行有 i 个式子。
输出样例(前 3 行):
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
cout << j << "*" << i << "=" << i * j << "\t";
}
cout << endl;
}
return 0;
}上节课的"7 的乘法表"其实就是这张表里 i = 7
的那一行——现在你能一次把 9 行全打出来了。想打印上三角形式(第 1 行 9
个、第 9 行 1 个)的话,把内层改成
for (int j = i; j <= 9; j++) 试试看。
| 写法 | 意思 |
|---|---|
for (int i = ...) { for (int j = ...) { ... } } |
嵌套循环:外层转一圈,内层整个跑完一遍 |
内层 j <= 5 |
每行个数固定 |
内层 j <= i |
每行个数跟着外层变(三角形、乘法表) |
"\t" |
制表符,让输出对齐成表格 |
变量名惯例: 外层 i、内层
j、再往里 k,不要重名。
易错点:
| 症状 | 原因 |
|---|---|
| 每个符号占一行 | endl 写在内层循环里面了 |
内层想用外层的 i 结果拿到的是内层的 |
内外层变量重名 |
| 图形多一行或少一行 | 循环条件的 <= 和 < 搞混了 |
j <= i
这个条件的作用