Please enable java script to visit.
NOTEBOOK
HOMEPHP / MySQLJS / HTMLWXappPythonC++Blender其他
多重循环套嵌 for 循环【**】 - NOTEBOOK
多重循环套嵌 for 循环【**】
C++
Posted on 2023-08-04
摘要 : 制作各种字符图形,三角形/金字塔/反转金字塔/沙漏型。
循环遍历的问题。
❱ 数字正三角

描述:输入一个整数打印数字图形。
输入:一个整数(0<n<10)
输出:一个数字图形


❱ 1.找出每一行行号和最大值的关系

第一行,数字最大值是1。(2*1-1=1)
第二行,数字最大值是3。(2*2-1=3)
第三行,数字最大值是5。(2*3-1=5)
。。。
很明显数字最大值和行号i是有关系的。可以总结为 2*i-1。
使用 for 循环一行一个数字打印出来:
#include<iostream>
// #include <iomanip>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1;i<=n;i++){
cout <<2*i-1;
cout <<endl;
}
return 0;
}

运行结果:
1
2
3


❱ 2.每一行中,打印数字

每一行,都从1开始显示数字,一直到该行的最大值。在每一行中,使用 for 循环一个数字一个数字打印出来:
#include<iostream>
// #include <iomanip>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int k=1;k<=2*i-1;k++){
cout <<k;
}
cout <<endl;
}
return 0;
}

运行结果:
1
123
12345


❱ 3.每一行中,插入对应的空格

同样,要找出每一行对应空格的最大值,然后用for循环显示空格(在数字之前)。
第一行,数字最大值是1。空格2个。
第二行,数字最大值是3。空格1个。
第三行,数字最大值是5。空格0个。
如果是4行:
第一行,数字最大值是1。空格3个。(4-1=3)
第二行,数字最大值是3。空格2个。(4-2=2)
第三行,数字最大值是5。空格1个。(4-3=1)
第四行,数字最大值是7。空格0个。(4-4=0)
分析之后,发现第一行的空格数是跟随总行数变化的,但最后一行总是0,所以很明显空格的数量和总行数n、行号是有关系的。可以总结为 n-i 。
那现在在每一行数字之前,打印空格出来:
#include<iostream>
// #include <iomanip>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=1;i<=n;i++){
// 打印空格,逐行递减
for(int j=n-i;j>=1;j--){
cout <<" ";
}

// 打印数字,从1 到 最大值 2*n-1 ,逐行递增
for(int k=1;k<=2*i-1;k++){
cout <<k;
}
cout <<endl;
}
return 0;
}

运行结果:
1
123
12345
1234567


如果把打印字符改成“*”:
*
***
*****
*******



❱ 反转金字塔

只要修改for循环方向,就可以实现逆向打印。
for(int i=1;i<=n;i++){

修改成,即可实现逆向:

for(int I=n;i>=1;i--){

完整代码:
#include<iostream>
// #include <iomanip>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=n;i>=1;i--){
// 打印空格,逐行递减
for(int j=n-i;j>=1;j--){
cout <<" ";
}

// 打印数字,从1 到 最大值 2*n-1 ,逐行递增
for(int k=1;k<=2*i-1;k++){
cout <<"*";
}
cout <<endl;
}
return 0;
}

运行结果:
*******
*****
***
*



❱ 沙漏型:正反金字塔合并

反向和正向金字塔的代码先后显示,就可以实现沙漏造型。
代码:
#include<iostream>
// #include <iomanip>
using namespace std;
int main() {
int n;
cin>>n;
// 反向金字塔
for(int i=n;i>=1;i--){
// 打印空格,逐行递减
for(int j=n-i;j>=1;j--){
cout <<" ";
}

// 打印数字,从1 到 最大值 2*n-1 ,逐行递增
for(int k=1;k<=2*i-1;k++){
cout <<"*";
}
cout <<endl;
}
// 正向金字塔
for(int i=1;i<=n;i++){
// 打印空格,逐行递减
for(int j=n-i;j>=1;j--){
cout <<" ";
}

// 打印数字,从1 到 最大值 2*n-1 ,逐行递增
for(int k=1;k<=2*i-1;k++){
cout <<"*";
}
cout <<endl;
}
return 0;
}

运行结果:
// 中间有两个行一个星号。
*******
*****
***
*
*
***
*****
*******


❱ 这时会发现,中间有两行 * (一个星号)

如果只想保留一个星号,可以把上面金字塔去掉最后一行,或者下面金字塔去掉第一行。
具体办法是,在 for 循环中,修改循环范围。
例如把上面金字塔去掉最后一行:
for(int i=n;i>=1;i--){

修改成

for(int i=n;i>1;i--){

例如把下面金字塔去掉第一行:
for(int i=1;i<=n;i++){

修改成

for(int i=2;i<=n;i++){

运行结果:
// 中间只有一行一个星号。
*******
*****
***
*
***
*****
*******


❱ 输入单数行,打印对应的沙漏

上面的程序,如果输入4,可以出现 7 行的沙漏,但我想修改成输入 5,就出现 5行的沙漏;输入 7,就出现 7行的沙漏。
上面的程序整体的完整度已经很高了,所以尽量不要修改主体,而是修改输入的变量。
❱ 分析

其实对应上述例子,
原先的程序,
显示五行的沙漏,原本输入数据是3,现在希望要输入5来实现。
显示七行的沙漏,原本输入数据是4,现在希望要输入7来实现。
显示九行的沙漏,原本输入数据是5,现在希望要输入9来实现。
。。。
我们输入5,要先让它变成3,再交给程序去打印沙漏。
我们输入7,要先让它变成4,再交给程序去打印沙漏。
我们输入9,要先让它变成5,再交给程序去打印沙漏。
所以总结出,设输入为x,则 n=x/2+1 。

这样的话,我们不需要修改原先的主体 for 循环,而只要在代码最前面修改成:
int x;
cin >>x;
int n = x/2+1;

完整代码:
#include<iostream>
// #include <iomanip>
using namespace std;
int main() {
int x; // 输入沙漏总行数
cin>>x;
int n=x/2+1;// 修改成半个沙漏(金字塔)的行数

// 交给原先的循环代码去打印
// 反向金字塔
for(int i=n;i>=1;i--){
// 打印空格,逐行递减
for(int j=n-i;j>=1;j--){
cout <<" ";
}

// 打印数字,从1 到 最大值 2*n-1 ,逐行递增
for(int k=1;k<=2*i-1;k++){
cout <<"*";
}
cout <<endl;
}
// 正向金字塔
for(int i=2;i<=n;i++){
// 打印空格,逐行递减
for(int j=n-i;j>=1;j--){
cout <<" ";
}

// 打印数字,从1 到 最大值 2*n-1 ,逐行递增
for(int k=1;k<=2*i-1;k++){
cout <<"*";
}
cout <<endl;
}
return 0;
}

运行结果:
5
*****
***
*
***
*****

7
*******
*****
***
*
***
*****
*******

9
*********
*******
*****
***
*
***
*****
*******
*********