C++ 循环嵌套详解
困难26循环嵌套:就像时钟的时针和分针
想象一下,你盯着墙上的时钟看时间:分针要跑完一圈(60分钟),时针才会动一格(1小时)。在编程里,循环嵌套就是这种“大循环套小循环”的结构——外层循环每执行一次,内层循环就要完整地跑完一整轮。我们用它来处理像表格、棋盘、图形这类有“行和列”的二维问题。
一、循环嵌套到底是怎么执行的?
我们先把分钟和小时的关系写成伪代码:
for (小时 = 1; 小时 <= 12; 小时++) { // 外层:时针走一圈
for (分钟 = 1; 分钟 <= 60; 分钟++) { // 内层:分针走一圈
时间过去了1分钟
}
}
当小时 = 1 时,内层的 分钟 要从1跑到60,等分钟跑完了,小时才变成2,然后分钟又从1跑到60……这样一共会输出 12 × 60 = 720 条“时间过去了1分钟”。
把这种思想搬到编程里,就是外层循环控制“大范围”(比如行数、组数),内层循环控制“小范围”(比如列数、每组的个数)。两个循环套在一起,就能生成像表格、图形、组合排列这样的二维数据。
小例子:班里排座位,4行5列。你从第1行开始,每行要依次坐满5个同学(第1列→第2列→…→第5列),然后换到第2行,再坐满5个同学……这就是一个嵌套循环。
二、用嵌套循环打印图形
1. 打印一个5行5列的星号矩形
想象你有一个5行5列的棋盘,每个格子放一个星号 *。外层循环管“第几行”,内层循环管“这一行里放几个星”。
for (int row = 1; row <= 5; row++) { // 外层:控制行数(1到5)
for (int col = 1; col <= 5; col++) { // 内层:控制列数(每行5个)
cout << "* "; // 打印一个星号加空格
}
cout << endl; // 一行结束后换行
}
输出效果:
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
2. 打印直角三角形
如果想让星号排成三角形的形状,比如:
*
* *
* * *
* * * *
观察规律:第1行1个星,第2行2个星,第3行3个星……也就是内层循环的次数等于当前的行号。我们可以让内层循环的条件依赖于外层循环的变量。
for (int i = 1; i <= 4; i++) { // 外层:控制行数(1到4)
for (int j = 1; j <= i; j++) { // 内层:每行打印 i 个星
cout << "* ";
}
cout << endl; // 换行
}
试一试:把
j <= i改成j <= 5会怎样?那就变成矩形了,因为每一行都固定打印5个星。
3. 倒着打印三角形(自己练手)
如果想把三角形倒过来:
* * * *
* * *
* *
*
你应该怎么做?提示:第一行4个星,第二行3个星……内层循环的上限可以写成 5 - i 或者 4 - i + 1。试着自己写一写吧!
三、实战:打印九九乘法表
乘法表是我们最熟悉的嵌套循环应用:行从1到9,列从1到当前的行数。比如第5行只打印1×5=5、2×5=10、3×5=15、4×5=20、5×5=25,一共5个算式。
for (int i = 1; i <= 9; i++) { // 外层:乘数 i(1到9)
for (int j = 1; j <= i; j++) { // 内层:被乘数 j(1到i)
cout << j << "x" << i << "=" << i * j << "\t"; // 输出算式,\t是制表符,让列对齐
}
cout << endl; // 换行
}
输出效果(部分):
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
...
生活小联想:这种“列数随行数增长”的模式,就像课间排队打水——第1个人只和自己比,第2个人要和前两个人比……每排的“比较次数”越来越多。
四、生活中的嵌套循环无处不在
- 时钟:时针(外层循环12格)和分针(内层循环60格)
- 日历:月份(外层,1
12)和日期(内层,128/30/31) - 超市货架:第几排(外层)和第几列(内层),每排的商品数量可能不同
- 课间操队列:第几排(外层)和第几个同学(内层)
- 巧克力排:一盒巧克力有3行4列,吃的时候要一行一行地吃,每行从左到右吃4块
五、新手最容易犯的3个错误
错误1:内外层变量混用
for (int i = 1; i <= 5; i++) {
for (int i = 1; i <= 5; i++) { // ❌ 内层也用了 i,外层 i 被覆盖
cout << "* ";
}
}
正确做法:外层用 i,内层用 j(或者 k、col 等),不要重名。如果内层也用了 i,编译器可能会报错或产生奇怪的循环次数。
错误2:忘记换行
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++) {
cout << "* ";
}
// 这里忘记写 cout << endl;
}
结果:所有星号挤在一行里,变成了 * * * * * * * * * * * * * * * * * * * * * * * * *。每处理完一行,必须手动换行!
错误3:内层循环条件写错
比如想打印直角三角形,却写成 j <= 5:
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 5; j++) { // ❌ 固定5列,不会随着 i 变化
cout << "* ";
}
cout << endl;
}
结果会打印一个4行5列的矩形,而不是三角形。
六、完整可运行示例:打印一个带边框的空心矩形
下面是一个完整的 C++ 程序,包含了头文件、主函数。它用嵌套循环打印一个 5×7 的空心矩形,只有边框有星号:
#include <iostream>
using namespace std;
int main() {
int rows = 5; // 行数
int cols = 7; // 列数
// 外层循环:控制每一行
for (int i = 1; i <= rows; i++) {
// 内层循环:控制每一列
for (int j = 1; j <= cols; j++) {
// 如果是第一行、最后一行、第一列、最后一列,打印星号,否则打印空格
if (i == 1 || i == rows || j == 1 || j == cols) {
cout << "* ";
} else {
cout << " "; // 两个空格(一个星号占两个字符)
}
}
cout << endl; // 换行
}
return 0;
}
运行结果:
* * * * * * *
* *
* *
* *
* * * * * * *
你可以试着修改 rows 和 cols,或者把 if 条件改成其他图案(比如对角线)。
七、如果还想继续学什么?
- 二维数组:嵌套循环常和二维数组搭配使用,比如存储班级成绩表
- 多层嵌套:最多嵌套3层就够了,比如三维坐标(x, y, z)或者三层比赛(年级→班级→学号)
- break 和 continue:在嵌套循环中,
break只跳出它所在的那一层循环;想跳出所有外层需要额外标记(goto或 flag 变量) - 循环优化:尽量减少内层循环中的计算量,比如把常数计算提到外层
现在就打开你的编译器,把上面的代码敲进去运行一下,再自己改一改,看看会得到什么新图形吧!
例题精讲
以下C++代码中,内层循环体(cout << "*";)总共执行多少次? for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { cout << "*"; } }
以下代码的输出是什么? for (int i = 1; i <= 3; i++) { for (int j = 1; j <= i; j++) { cout << j; } cout << endl; }
在嵌套循环中,外层循环每执行一次,内层循环就会完整地从头到尾执行一轮。
以下代码段执行后,输出的星号数量是6个。 for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 2; j++) { cout << "*"; } }
补全以下代码,使得程序输出如下图案(三行,第一行输出1,第二行输出12,第三行输出123):
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= ___; j++) {
cout << j;
}
cout << endl;
}
return 0;
}