循环结构练习:
下面来做两个练习,通过这两个练习可以让你对流程控制,尤其是for循环掌握的更加牢靠。
用for循环输出下列倒三角:
*****
****
***
**
*
先看代码:
public class Triangle01 {
public static void main(String[] args) {
/*有两个量在进行循环,一个是行数i,一个是对应行的星数j*/
for (int i = 1; i <= 5; i++) {
for (int j = 6 - i; j >= 1; j--) {//第一行5*第二行4*。。。第i行(6-i)*
System.out.print("*");
}
System.out.println();
}
}
输出结果:
*****
****
***
**
*
下面我们来分析为什么这么写。
分析过程
-
首先我们可以看出有两个量在进行循环,一个是行数i,从1-5循环。一个是对应行的星数j:第一行5颗星,第二行4颗星。。。第i行(6-i)颗星。
-
因此我们不难想到用行数i和星数j来循环嵌套。
-
关于j为什么是
j--
的问题,我们可以看出for (int j = 6 - i; j >= 1; j--)
只规定了j的下限为1,但是并没有规定上限制。而迭代语句的功能是为了让循环体能结束。如果是j++
的话可以看到j循环会一直进行下去永远不会停止,也永远不会跳出循环体。 -
对于初学者可能会写成
for (int j = 5; j >= 1; j--)
而不是for (int j = 6-i; j >= 1; j--)
。我们来输出一下写成for (int j = 5; j >= 1; j--)
的结果:/*有两个量在进行循环,一个是行数i,一个是对应行的星数j*/ for (int i = 1; i <= 5; i++) { for (int j = 5; j >= 1; j--) {//第一行5*第二行4*。。。第i行(6-i)* System.out.print("*"); } System.out.println(); } 输出结果: ***** ***** ***** ***** *****
那么怎么想到for (int j = 6-i; j >= 1; j--)
呢?这就需要从for循环的运行流程去推导了:
前面我们说过for的运行流程:
for(a.初始化;b.布尔表达式;c.更新)
d.//代码语句
}
e.//循环体后的语句
运行流程顺序:a.——b.——c.——b.——c…——e.
那么本题的流程如下:
for (int i = 1; i <= 5; i++) {
for (int j = 5; j >= 1; j--) {//第一行5*第二行4*。。。第i行(6-i)*
System.out.print("*");
}
System.out.println();
}
1. 初始化i=1,判断i<=5为真,进入i的循环体:
2. 初始化j=5,判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==4
3.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==3
4.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==2
5.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==1
6.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==0
7.判断j>=1为假,不进入j的循环体。顺序向下运行System.out.println();即换行。
以上,i的循环执行完一次。
此时程序的输出结果为
*****
可见,至此已经打印出第一行的5个*
如果是for (int j = 5; j >= 1; j--)
通过上述流程不难看出i==2的循环执行完后第二行打印出来的也依旧还是5个*
因此我们想到每次进入i的循环体时j的上限也是会变的。我们已经有了变量i且知道每次进入循环体i的值都会变。
为此我们寻求j与i的关系得到:int j = 6 - i;
可得第一次进入i的循环体时j的上限为j = 6 - 1 = 5
第二次进入i的循环体时j的上限为j = 6 - 2 = 4
然后开始i的第二次循环流程:
1. 初始化i=2,判断i<=5为真,进入i的循环体:
2. 初始化j=6-i=4,判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==3
3.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==2
4.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==1
5.判断j>=1为真,进入j的循环体:打印一个*
进入j的迭代:j--得到j==0
7.判断j>=1为假,不进入j的循环体。顺序向下运行System.out.println();即换行。
以上,i的循环体执行完第二次。
此时程序的输出结果为
****
至此,我们逐行减少*数量的目的就达到了。
然后开始i的第三次循环流程、第四次、第五次。。。。
最终实现输出。
用for循环输出下列正三角:
*
***
*****
*******
*********
依旧还是先上代码再分析。
public class Triangle01 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
for (int j = 5 - i; j > 0; j--) {
System.out.print(" ");
}
for (int k = 2*i-1; k>0 ; k--) {
System.out.print("*");
}
System.out.println();
}
}
}
输出结果:
*
***
*****
*******
*********
分析过程
-
不难看出,1-5行的行数依旧是一个循环量,除此之外还有每一行最先打印的空格数量和*数。
-
前面的空格形状正好是上一个练习的形状。
-
设行数为i可得循环
for (int i = 1; i <= 5; i++){}
,可以看出空格数量j与行数i之间的关系为j=5-1
,每行打印的*与i之间的关系为k=2*i-1
. -
具体分析也可以向上一题一样逐个流程分析。本题的流程如下:
for (int i = 1; i <= 5; i++) {
for (int i = 1; i <= 5; i++) {
for (int j = 5 - i; j > 0; j--) {
System.out.print(" ");
}
for (int k = 2*i-1; k>0 ; k--) {
System.out.print("*");
}
System.out.println();
}
1.初始化i=1,判断i<=5为真,进入i的循环体:
2.初始化j=5-1==4,判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==3
3.判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==2
4.判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==1
5.判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==0
7.判断j>0为假,不进入j的循环体。顺序向下进入k的循环体:
8.初始化k=2*1-1==1,判断k>0为真,进入k的循环体:打印一个*
进入k的迭代:k--得到j==0
9.判断k>0为假,不进入k的循环体,循序向下运行System.out.println(),即换行。
以上,i的循环执行完一次。
此时程序的输出结果为(4个空格)*
10.然后进入i 的迭代:i++得到i==2判断i<=5为真,进入i的循环体:
11.初始化j=5-2==3,判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==2
12.判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==1
13.判断j>0为真,进入j的循环体:打印一个空格
进入j的迭代:j--得到j==0
14.判断j>0为假,不进入j的循环体。顺序向下进入k的循环体:
15.初始化z=2*2-1==3,判断k>0为真,进入k的循环体:打印一个*
进入k的迭代:k--得到k==2
16.判断k>0为真,进入k的循环体:打印一个*
进入k的迭代:k--得到k==1
17.判断k>0为真,进入k的循环体:打印一个*
进入k的迭代:k--得到k==0
18.判断k>0为假,不进入k的循环体,循序向下运行System.out.println(),即换行。
以上,i的循环执行完一次。
此时程序的输出结果为(3个空格)***
然后依次进入i 的迭代和i的循环体,最终得到结果。
通过以上练习和过程分析,相必读者对于Java流程控制和for循环已经有了更深入的理解。