AP计算机科学A复习:Unit 4 – Iteration 循环结构

Unit 4 – Iteration 选择结构

相对人来说,机器更适合执行重复的工作。第4单元介绍的是Java编程中基础的循环语句。循环语句实现了让计算机在特定的条件下反复执行某一部分程序的功能。例如,如果要输出整数1-100之间所有的偶数,就需要判断1-100之间每一个整数是否能整除2,总共需要循环100次。但是运用循环语句我们不需要一行一行的编写这100个判断语句,只需要设置好循环的条件即可。

U4.1 While Loops

这是一种基础的循环语句,由「while」关键词、「condition」条件、以及「body」三个部分组成。其中,condition 应该是一个boolean expression或者boolean value。比如,你可以直接在里面填上「true」或者「false」,也可以填上诸如「 i <= 100 」这样的表达式。具体的写法是这样:

		while(/*这里写条件*/) {
			//这里是body,也就是被循环执行的部分
		}

用下面的框图来理解。在while语句的最开始,电脑将会判断「条件」是否为真,只有当条件为真时才会执行「body」里面的程序语句。等到 body 里面的程序语句被执行完毕后,电脑将再次判断 while 语句的条件是否成立,如果条件仍然成立,则再次执行 body 里面的语句。如此循环往复,直到某次判断条件是否成立时发现条件不再成立,则 while 循环语句结束。

比如,假设下图中 i 的初始值是 1,而 n 的值为2。当程序运行时,电脑将会首先判断 i <= n 是否成立,第一次发现 1 <= 2 确实成立,得到「真」的结果。所以「body」会被运行,i 的值被递增了1(就是加1,只是「递增」的说法看起来很高级)。此时,i 的值为2,n 的值仍然为2。电脑再次判断条件是否成立,发现2 <= 2 确实仍然成立,所以条件仍然为真。电脑再次将 i 的值递增1。此时 i 的值为 3,n 的值为 2。电脑再次判断条件是否成立,发现 3 <= 2 并不成立,因此条件为假。这个时候电脑就不会再运行 body 里面的语句,而是结束这个 while 循环。 在整个程序中,i 的值在每次循环中被递增 1 ,作用是计数器,可以让电脑知道当前的循环是第几次。计数器是限制循环次数的重要工具。i 的值每次变化的大小被称为步长,步长可以为正也可以为负。

如果把上面的程序完整的写出来,就是这样的:

		int i = 1;
		int n = 2;
		while(i <= n) {
			System.out.println(i);
			i = i +1;
		}

尝试自己在eclipse里面尝试编写一个 while 循环语句:输出1 – 10之间所有的整数。

U4.2 for Loops

这是一个更加集成化的循环语句。我们可以在一句话里完成计数器变量的声明、循环条件的设置、以及循环递增递减步长的设置。

		for (/*声明计数器变量*/; /*循环条件*/; /*递增递减*/) {
			//被循环的语句
		}

在 for 循环语句的后面也有一个小括号。这个小括号里面有三个需要编写的部分,每个部分之间用分号隔开。第一个部分是声明计数器变量,语法和正常的声明变量一致,比如「 int i = 1; 」,这个部分仅在循环语句的最开始被执行一次。第二个部分用来填写循环条件的boolean expression,比如「i <= 3; 」,在每次循环的开始之前都会判断一次条件是否成立,如果成立则运用要被循环的语句,如果不成立则结束循环。第三个部分是循环的递增递减设置,这个语句将在每次循环结束后被执行一次,比如「 i ++ 」就是在每次循环结束之后把 i 递增1。那么我们写一下这个例子:

		for (int i = 1; i <= 3; i++) {
			System.out.println(i);
		}

输出值是整数 1 至 3 。在这个循环语句的最开始,声明了变量 i 赋并且初值为 1。随后,电脑判断循环的条件是否成立,发现 1<= 3 确实成立,条件的值为真,所以开始执行被循环的部分。在例子里面是使用输出语句输出 i 当前的值,因此这时输出了 1 。当被循环的部分执行完后,第一圈的循环结束,这时候就要执行递增递减的操作。在这个例子里,小括号的第三个部分里面写的是「 i ++ ; 」,也就是把 i 在当前数值的基础上递增 1 。i 此时的数值是 1, 再加上1,就得到了 i 递增后的数值,也就是 2。注意,这里的「i ++ ; 」和「i = i + 1; 」是等效的,你可以选其中任何一种写在小括号的第三部分里面。递增结束后,就进入到第二圈循环。在循环的开始,电脑再次判断循环的条件,「i <= 3」的假设这是就成了「2 <= 3」,仍然是成立的,条件还为真。因为条件为真,所以这一圈循环还要执行大括号括起来的「body」部分。 i 的数值被再次输出,这次输出的是 2 。当 body 部分运行完毕,就到了第二圈循环的末尾,又要执行递增递减。仍然根据这个例子的设置,i 的数值被再加一,所以现在 i 的数值成为了 3 。程序接下来开始第三圈循环,判断条件是否成立,发现「 3 <= 3」依然成立,条件还是为真,所以执行 body 部分,这次输出了3。第三圈末尾,再次将 i 递增 1,此时 i 的值已经是 4 了。程序来到第 4 圈开头,电脑判断循环的条件是否成立。这次就发现在「i <= 3」的条件下,出现了「 4 <= 3」的情况,这样的情况下假设是不成立的,因此条件的boolean value为假。循环结束。

U4.3 Developing Algorithms Using Strings

U2.7已经了解 substring() method的用法。使用这个 method 可以得到某个数组的特定部分。比如:

		String a = "abcde";
		System.out.println(a.substring(1,3));

我使用 substring() ; method 输出了字符串 a 的里面的字母「bc」。注意字符串要从0开始计算数字母的编号,所以字母 a 的编号是 0 ,字母 b 的编号才是 1。因此在 substring (); method 里面的第一个表示开始位置的参数应该输入 1。而 substring() ; method 的第二个参数则是输出结束的位置+1,所以如果要输出第二个字母c,就要在第二个参数里输入「2 + 1 = 3」。这样一来,两个参数就分别是 1 和 3 。

最后输出结果是 「bc」。

使用变量替换 substring() ; method 的两个参数,并配合循环语句,就可以一个一个的拿到字符串中的字母。比如,你需要把一个字符串倒序输出的时候,就可以这样做:

		String a = "abcde";
		for (int i = a.length()-1 ; i >= 0; i--) {
			System.out.print(a.substring(i, i+1));
		}

在这个程序中,循环语句的计数器变量的初值是字符串长度的数值减一。因为,如果要倒叙输出一个字符串,我们就需要从尾巴往最开头一个一个地访问字符串中的字母。而使用 length() method获得的字符串长度和字母在字符串里的编号是有差别的:

从上面的对比表格可以看到, 字母在字符串里的编号从0开始,但是 length() method 获得的字符串长度实际上是用正常人类数数的方式来完成的计数。在这里,字母 a, b, c, d, e 一共有五个字母,所以正常人数数就是 1,2,3,4,5,一共五个字母。但是在字符串里面,字母  a 的编号是 0 ,第二个字母 b 的编号才是 1,所以最后一个字母的编号是 4 而不是 5 。这就是为什么当使用 length() method 得到字符串的真实长度 5 之后, 还需要在它的基础上减一才能得到正确的最后一个字母的编号 4。因为我们在 substring() method 的参数里使用的是字母在字符串里面的编号来进行访问。

接着,字符串的字母编号从后往前访问,所以 i 作为计数器应该从 4 开始递减。注意,字母在字符串里的编号最小是 0 。所以我们在循环语句的括号里将循环的条件写为「i >= 0」,即计数一旦小于0 就终止循环;同样的,递增递减设置也应该是「i ——」,每次递减 1 。这样, i 的数值在第一圈循环就应该是 4;第二圈为3;第三圈为2;第四圈为1;直到第五圈为0,再然后就无法继续循环了。如此,就完成了对全部五个字母的倒序访问。在每一圈中,我们使用一个 substring() method,参数填写 i 和 i + 1 来访问 i 的数值对应位置的字母。根据我们在前面U2.7了解到的 substring 的参数填写格式,这样就可以在第一圈循环输出编号为 4 的字母 e ,再在第二圈循环输出编号为3的字母 d ,以此类推,就实现了倒序输出。

U4.4 Nested Iteration

在循环语句的 body 里面又写一个或者多个循环语句,就叫做 Nested Iteration。一般地,我们使用一个整数变量来记当前循环的圈数,相当于是在一个数轴上进行操作,只有横着递增或递减两个方向;但是如果在一个循环中又嵌套另一个循环,我们就拥有了两个维度的操作空间,可以看作是对一个表格进行操作,不仅能够横着递增递减,还能竖着递增递减。

比如,我们可以使用 Nested Iteration 来输出 9 * 9 乘法表。乘法表里面所有的算式的格式都是「a * b」,正好是两个的数据。在这里,我使用横向循环的圈数来表示 a 的数值,纵向循环的圈数来表示 b 的数值。这是因为,电脑程序的输出是从左往右再从上往下的,如果要按这样的格式输出:

就要在第一排输出 1*1,2*1…… 第一行的所有 b 的值都是 1,而 a 的值则随循环增大。这表示 b 做的是外层循环,而 a 是内层循环。外层循环的每一圈都包括一次完整的内层循环。也就是说,在外层循环的第一圈里面,内层循环完整的运行了一次,完成9次循环:

		for (int b = 1; b <= 1 ; b++) {
			for (int a = 1; a <= 9; a++) {
				System.out.print(a +" * " +b + " = "+ a*b+ "\t");
			}
		}

在你的eclipse里面运行上面这段代码做个实验。可以看到,如果只让外层循环转一圈,在这个过程中,b 的值为 1 ,但是 a 的值就经历了从 1 递增到 9 的完整循环。所以,这就是「外层循环的每一圈都包括一次完整的内层循环」。既然已经实现了 a 从 1 到 9 的循环,现在就只需要让 b 也完成这样的循环,同时将每种 a 和 b 组合的可能性相乘就可以得到一张完整的乘法表。注意要在每一个内层循环结束之后换行,这样才可以得到正确的表格格式。

		for (int b = 1; b <= 9 ; b++) {
			for (int a = 1; a <= 9; a++) {
				System.out.print(a +" * " +b + " = "+ a*b+ "\t");
			}
			System.out.print("\n");//换行
		}

运行上面的程序,你会得到下面的输出结果:

这个表格显然已经包括了乘法表的所有元素,但是多了一半。这多的一半是因为 a 和 b 都经历了从 1 至 9 的循环,所以会出现诸如「 1 * 3 =3」 和「3 * 1 =3」这样顺序不同、结果相同的重复输出。我们可以通过选择语句来丢弃这样的重复。考虑到乘法表是正三角的形状,我会丢弃右上半边的重复输出。例如「 3 * 1 = 3」需要被丢弃,观察可以发现这里的 a的值是大于 b 的值的。那么我们试着丢弃所有的「 a > b」的算式,但是注意,如果 a 和 b 等值,我们还是需要进行输出,否则乘法表会丢失诸如「 2 *2 =4」这样的一类情况:

		for (int b = 1; b <= 9 ; b++) {
			for (int a = 1; a <= 9; a++) {
				if (a <= b) {
				System.out.print(a +" * " +b + " = "+ a*b+ "\t");
				} else {
					System.out.print("\t");
				}
			}
			System.out.print("\n");//换行
		}

由此可见,只有在 「 a <= b」的情况下,程序才使用输出语句来打印当前的算式。不过,如果遇到了需要丢弃重复算式的情况,也不能直接跳过,而是要使用一个「\t 」的 tab 占位符来保持表格格式。这样,我们就得到了一个真正的乘法表:

在你的Eclipse里面使用 Nested Iteration 输出一个乘法表。

U4.5 Informal Code Analysis

这部分考点的出题形式是,由题目给出一段程序,你需要代替电脑自己读懂这段程序然后预测这段程序要作出的反应。比如,题目给了一个循环语句,你需要分析得出这个循环的圈数、或者输出结果。例题如下:

(College Board, 2019)

题干要求回答这个循环语句的循环圈数。所以我们可以使用草稿纸来模拟一下这个程序运算的过程:

所以,这个循环一共运行了 9 次。

总结

至此,基本的程序语法已经介绍完毕。我们可以使用循环语句来让计算机在预想的情况下重复运行部分代码直到满足特定条件。结合使用循环语句、选择语句可以实现更复杂的运算和输出效果。除了输出乘法表,还能对一组数据进行排序等等。此外,还要习惯阅读一段已经写好的程序,并分析这段程序的行为。

练习

  1. 2009-1

2. 2009-6

3. 2008-2

4. 2009-9

by Oscar.L
E-mail [email protected]
No Comments

Send Comment Edit Comment

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
Previous
Next