第4章 流程控制

第4章 流程控制

本章读者可以学到如下实例

  • 实例019 判断某一年是否为闰年
  • 实例020 验证登录信息的合法性
  • 实例021 为新员工分配部门
  • 实例022 用switch语句根据消费金额计算折扣
  • 实例023 判断用户输入月份的季节
  • 实例024 使用while循环语句与自增运算符循环遍历数组
  • 实例025 使用for循环输出杨辉三角形
  • 实例026 使用嵌套循环在控制台上输出九九乘法表
  • 实例027 使用while循环计算1+1/2!+1/3!…1/20!
  • 实例028 使用for循环输出空心的菱形
  • 实例029 终止循环体
  • 实例030 循环体的过滤器

实例019 判断某一年是否为闰年

实例说明

地球绕太阳一圈称之为一年,所用时间是365天5小时48分46秒,取365天为一年,4年将多出23小时15分6秒,将近一天,所以4年设一个闰日(2月29日),这年称为闰年。本实例将要求用户输入年份,并判断输入的年份是否为闰年。实例的运行效果如图4.1所示。

实现过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.mingrisoft;
import java.util.Scanner;

public class Demo {
/**
* @param args
*/
public static void main(String[] args) { //主方法
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个年份:"); //向控制台输出一个提示信息
long year;
try {
year = scan.nextLong();
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { // 是闰年
System.out.print(year + "是闰年!");
} else { // 不是闰年
System.out.print(year + "不是闰年!");
}
} catch (Exception e) {
System.out.println("您输入的不是有效的年份!");
}
}
}

指点迷津

java.util包的Scanner类是一个用于扫描输入文本的简单文本扫描器,可以用这个类从控制台写入数据。该类的netlOg()方法可以将输入信息扫描为一个long型的数据,如果输入的信息不能被成功转换为long型,将抛出java.Util.InputMismatchException异常。

技术要点

本实例主要的技术就是应用if语句判断闰年。判断一个年份是否为闰年,要满足两个条件个是能被4整除但不能被100整除,另一个是能被400整除。判断闰年的公式用Java语法实现的格式如下:

1
year%4==0&&year%100!=0||year%400==0

实例020 验证登录信息的合法性

大多系统的登录模块都会接收用户通过键盘输入的登录信息,这些登录信息将会被登录模块验证,如果使用的是指定的用户名与密码,则允许用户登录;否则将用户拒之门外。本实例将通过if…else语句进行多条件判断实现登录信息验证。实例的运行效果如图42所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.mingrisoft;

import java.util.Scanner;
public class CheckLogin {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);// 创建扫描器
System.out.println("请输入登录用户名:");
String username = scan.nextLine();// 接收用户输入登录名
System.out.println("请输入登录密码:");
String password = scan.nextLine();// 接收用户输入登录密码
if (!username.equals("mr")) {// 判断用户名合法性
System.out.println("用户名非法。");
} else if (!password.equals("mrsoft")) {// 判断密码合法性
System.out.println("登录密码错误。");
} else {// 通过以上两个条件判断则默认通过登录验证
System.out.println("恭喜您,登录信息通过验证。");
}
}
}

多学两招
字符串属于对象而非基本数据类型,不能使用“==”来判断两个字符串是否相当,所以需要通过equals方法来判断两个宇符串内容是否相同,正如本实例对用户名和密码的判断那样。使用“==”判断的将是两个字符串对象的内存地址,而非字符串内容.

实例022 用switch语句根据消费金额计算折扣

实例说明

俗话说“商场如战场”,各大商家为了笼络有限的顾客,经常会打出各种各样的促销手段。例如,会员折扣制度,即对会员的消费金额进行累加,当超过一定数额时,可以享受相应的折扣。累计消费金额越高,享受的折扣越多。本实例将应用switch语句计算累计消费金额达到一定数额时,享受不同的折扣价格。实例的运行效果如图44所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.mingrisoft;

public class ProductPrice {
public static void main(String[] args) {
float money = 1170; // 金额
String rebate = ""; // 折扣
if (money > 200) {
int grade = (int) money / 200; // 等级
switch (grade) { // 根据等级计算折扣比例
case 1:
rebate = "九五折";
break;
case 2:
rebate = "九折";
break;
case 3:
rebate = "八五折";
break;
case 4:
rebate = "八三折";
break;
case 5:
rebate = "八折";
break;
case 6:
rebate = "七八折";
break;
case 7:
rebate = "七五折";
break;
case 8:
rebate = "七三折";
break;
case 9:
rebate = "七折";
break;
case 10:
rebate = "六五折";
break;
default:
rebate = "六折";
}
}
System.out.println("您的累计消费金额为:" + money);// 输出消费金额
System.out.println("您将享受" + rebate + "优惠!"); // 输出折扣比例
}
}

脚下留神

在程序开发中经常使用的都是正数,负数因为使用得少,常常被忽略,例如“N%2==1”本来是用来计算数字N是否为奇数的,但是开发者没有考虑到负数的情况,从而导致这个算法的失败,因为任何负数应用这个算法都会等于-1。

实例023 判断用户输入月份的季节

实例说明年有四季,每季3个月。其中,

  • 12月、1月和2月为冬季,
  • 3月、4月和5月为春季,
  • 6月、7月和8月为夏季,
  • 9月、10月和11月为秋季。

本实例将根据用户输入的月份来判断季节,这是一个最典型的演示switch语法的例子,通过这个例子,读者可以完全掌握switch语句的用法与技巧。实例的运行效果如图45所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.mingrisoft;

import java.util.Scanner;
public class JudgeMonth {

public static void main(String[] args) {
Scanner scan = new Scanner(System.in); // 创建扫描器
// 提示用户输入月份
System.out.println("请输入一个月份,我能告诉你它属于哪个季节。");
int month = scan.nextInt(); // 接收用户输入
switch (month) { // 判断月份属于哪个季节
case 12:
case 1:
case 2:
System.out.print("您输入的月份属于冬季。");
break;
case 3:
case 4:
case 5:
System.out.print("您输入的月份属于春季");
break;
case 6:
case 7:
case 8:
System.out.print("您输入的月份属于夏季");
break;
case 9:
case 10:
case 11:
System.out.print("您输入的月份属于秋季");
break;
default:
System.out.print("你那有" + month + "月份吗?");
}
}
}

脚下留神

switch语句的每个case关键字都用于判断一个常量并做出相应的业务处理,熟练掌握switch语句之后可以组合多个case来完成多条件的处理,就是多个常量结果执行相同的业务处理,如本实例中应用的格式。

实例024 使用while循环语句与自增运算符循环遍历数组

实例说明在多数情况下,遍历数组都是使用for循环语句实现。其实应用while循环语句和自增运算符也可实现遍历数组。本实例将利用自增运算符结合while循环语句实现数组的遍历,并将遍历结果输出到控制台。实例的运行效果如图46所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.mingrisoft;

public class ErgodicArray {
public static void main(String[] args) {
// 创建鸟类数组
String[] aves = new String[] { "白鹭", "黄鹂", "鹦鹉", "乌鸦",
"喜鹊","布谷鸟", "斑鸠", "百灵鸟" };
int index = 0;// 创建索引变量
System.out.println("我的花园里有很多鸟,大约包括:");
while (index < aves.length) {// 遍历数组
System.out.println(aves[index++]);// 自增索引值
}
}
}

指点迷津
自增自减运算符分前置和后置两种。其中,前置运算如“++index”,会先将index的值递增,然后再使用递增后的值;而后置运算如“index++”,会首先使用该变量的值,然后再把变量值递增.

实例025 使用for循环输出杨辉三角形

实例说明
杨辉三角形由数字排列,可以把它看作一个数字表,其基本特性是两侧数值均为1,其他位置的数值是其正上方的数值与左上角数值之和。本实例将使用for循环输出包括10行内容的杨辉三角形。实例的运行效果如下所示:

1       
1       1
1       2       1
1       3       3       1
1       4       6       4       1
1       5       10      10      5       1
1       6       15      20      15      6       1
1       7       21      35      35      21      7       1
1       8       28      56      70      56      28      8       1
1       9       36      84      126     126     84      36      9       1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.mingrisoft;

public class YanghuiTriangle {
public static void main(String[] args) {
int triangle[][]=new int[10][];// 创建二维数组
// 遍历二维数组的第一层
for (int i = 0; i < triangle.length; i++) {
triangle[i]=new int[i+1];// 初始化第二层数组的大小
// 遍历第二层数组
for(int j=0;j<=i;j++){
// 将两侧的数组元素赋值为1
if(i==0||j==0||j==i){
triangle[i][j]=1;
}else{// 其他数值通过公式计算
triangle[i][j]=triangle[i-1][j]+triangle[i-1][j-1];
}
System.out.print(triangle[i][j]+"\t"); // 输出数组元素
}
System.out.println(); //换行
}
}
}

指点迷津

在创建二维数组时,其第一维的长度即是要输出杨辉三角形的行数。例如,在本实例中要输出10行的杨辉三角形就可以将其第一维的长度设置为10.

指点迷津

Java语言中的二维数组其实是每个元素都是一个一维数组的一维数组,所以第二维的长度可以任意,就像本实例中那样。这比其他语言的数组更灵活,而且多维数组也是如此。

技术要点

本实例应用的主要技术是应用for循环语句根据杨辉三角形的公式遍历二维数组。杨辉三角形的公式包括两部分,一部分是两侧数值都是1,也就是说二维数组的triangle[0][0]triangle[i][0]或者triangle[i][i]的元素值为1,另一部分是其他位置的数值是其正上方的数值与左上角数值之和,也就是triangle[i][j]=triangle[i-1][j]+triangle[i-1][j-1].

指点迷津

在二维数组中,第1个下标值代表的是行数,第2个下标值代表的是列数,即triangle[o代表的是第i行第0列的元素.

实例026 使用嵌套循环在控制台上输出九九乘法表

实例说明

对于九九乘法表读者都不会陌生,几乎每个人都能倒背如流。那么如何通过嵌套循环,在控制台上输出九九乘法表呢?这个内容在掌握了for循环的嵌套后,就不难实现。本实例将应用嵌套的for循环实现在控制台上输出九九乘法表。实例的运行效果如图4.8所示。

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

脚下留神:
在上面的代码中,在内层循环输出计算结果时,应用的是System.out对象的print()方法输出,应用该方法不换行,在内层循环结来后,再应用System.out对象的println()方法换行。
指点迷津:
循环语句可用于完成复杂的运算,也可以用于控制程序的递归流程,而多层循环可以实现更加复杂的业务逻辑,是学习编程必须掌握的一种应用。在处理有规则的大量数据时,应该考虑使用多层循环来优化程序代码,但是建议添加详细的代码注释,便于以后的维护与修改工作。
技术要点
要在控制台上输出九九乘法表,可以通过嵌套的for循环来实现,即创建双层的for循环。

  • 第一层for循环,也称外循环,用于控制表格的行;
  • 第二层for循环,也称内循环,用于控制表格的列。

其中,

  • 第一层for循环的控制变量的最大值是9,
  • 第二层for循环的控制变量的最大值要等于行数的最大值。
    • 然后输出内层与外层循环控制变量的乘积,即可实现九九乘法表。

实例027 使用while循环计算1+1/2!+1/3!…1/20!

实例说明

本实例在计算阶乘的算法之上应用while循环语句计算1+1/2!+1/3!…1/20!的和。如果使用基本数据类型double是无法精确地显示运算结果的,所以本实例使用了BigDecimal类的实例来完成这个运算。实例的运行效果如图49所示。

1+1/2!+1/3!···1/20!的计算结果等于:
1.71828182845904522367258882524732563634867246268558104448130832136101139366719986414383110243797108748822820657493330665752903534700022508204525385549479876951292493516361991885142411580915233808389198581342610980977425822951724476374113374431295345516733481291917383751991568557019209000617394017755970330759280319424925748716392429788018461622511631047241914024775263254452027548084334842631749679270930789639542724477953673333791555400257219557963341089085618184152725912383836106812569589258574113531875910271222819280308083619226237539764181652472718046378704910462924352995976893461209516866339555490458432187283021232937484781081946952237499593023333299830547132009915333667625253213008545235615683712431845561218831886238965727822680526029924244310460181428675093053813137695411922636380686046919663567678071558475494384765625
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.mingrisoft;

import java.math.BigDecimal;

public class Example {
public static void main(String args[]) {
BigDecimal sum = new BigDecimal(0.0); // 和
BigDecimal factorial = new BigDecimal(1.0); // 阶乘项的计算结果
int i = 1; // 循环增量
while (i <= 20) {
sum = sum.add(factorial); // 累加各项阶乘的和
++i; // i加1
factorial = factorial.multiply(new BigDecimal(1.0 / i)); // 计算阶乘项
}
System.out.println("1+1/2!+1/3!···1/20!的计算结果等于:\n" + sum); // 输出计算结果
}
}

公式推导

1/3!=1/(3*2*1)=(1/3)*(1/2)*(1/1)=(1/1)*(1/2)*(1/3)

脚下留神:

对于高精度要求或者运算数较大的计算,应该使用BigDecimal类实现,否则Java基本类型的数据无法保证浮点数的精度,也无法对超出其表示范围的数字进行运算

技术要点

本实例主要应用了while循环和BigDecimal类的实例对象的相关方法实现计算1+1/2!+1/3!+…+1/20!的和。
BigDecimal类型的数字可以用来做超大的浮点数的运算,如加、减、乘、除等。使用BigDecimal对象的add()方法可以实现加法运算,使用multiply()方法可以实现乘法运算。

实例028 使用for循环输出空心的菱形

实例说明本实例在输出菱形的基础上加大难度,输出空心的菱形图案,这在等级考试与公司面试时也出现过类似题目,实例目的在于要求熟练掌握for循环的嵌套使用。实例的运行效果如图4.10所示

1
2
3
4
5
6
7
      *
* *
* *
* *
* *
* *
*

实现过程

(2)在com.Mingrisoft包中创建类文件,名称为Diamond,并在该类的主方法中调用printHollowRhombus方法完成7行的空心菱形输出。其中printHollowRhombus方法是实例中自定义的,该方法使用两个双层for循环分别输出菱形的上半部分与下半部分。关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.mingrisoft;

public class Diamond {
public static void main(String[] args) {
printHollowRhombus(6);
}

public static void printHollowRhombus(int size) {
if (size % 2 == 0) {
size++;// 计算菱形大小
}
for (int i = 0; i < size / 2 + 1; i++) {
for (int j = size / 2 + 1; j > i + 1; j--) {
System.out.print(" ");// 输出左上角位置的空白
}
for (int j = 0; j < 2 * i + 1; j++) {
if (j == 0 || j == 2 * i) {
System.out.print("* ");// 输出菱形上半部边缘
} else {
System.out.print(" ");// 输出菱形上半部空心
}
}
System.out.println(""); // 换行
}
for (int i = size / 2 + 1; i < size; i++) {
for (int j = 0; j < i - size / 2; j++) {
System.out.print(" ");// 输出菱形左下角空白
}
for (int j = 0; j < 2 * size - 1 - 2 * i; j++) {
if (j == 0 || j == 2 * (size - i - 1)) {
System.out.print("* ");// 输出菱形下半部边缘
} else {
System.out.print(" ");// 输出菱形下半部空心
}
}
System.out.println(""); // 换行
}
}
}

脚下留神

for循环中有3个表达式,这3个表达式都是可选的,也就是说for循环可以没有表达式.例如for(;;)这样的for循环将是一个无限循环,读者在使用for循环时应注意避免无限循for循环中有3个表达式,这3个表达式都是可选的,也就是说for循环可以没有表达式.

技术要点

本实例应用的主要技术是for循环语句的嵌套和ifelse语句。其中,ifelse语句用于控制菱形中心位置不输出*号,即输出空心菱形。

实例029 终止循环体

实例说明

循环用于复杂的业务处理,可以提高程序的性能和代码的可读性,但是循环中也有特殊情况,例如由于某些原因需要立刻中断循环去执行下面的业务逻辑,这时就可以使用break语句实现。本实例将实现应用break语句中断单层循环中断双层for循环。实例的运行效果如图4.l1所示。

实现过程

(1)在eclipse中创建项目029,并在该项目中创建com.mingrisoft包。
(2)在com.mingrisoft包中创建类文件,名称为BreakCyc。在该类的主方法中,首先创建一个字符串数组,然后在使用for循环遍历时判断如果发现数组中包含字符串“老鹰”则立刻中断循环。最后再创建一个整数类型的二维数组,并使用双层for循环遍历,当发现第一个小于60的数组元素时,立刻中断整个双层循环,而不是内层循环。关键代码如下:

指点迷津

充分利用循环可以提高程序的开发与执行效率,但是如果不注重循环中的算法很容易导致程序的死循环,所以在循环体中要对可能出现的特殊情况使用break语句中断循环,

技术要点

本实例应用的主要技术是break语句。break语句用于强行退出循环。使用带标签的break语句,可以强行退出多层循环。例如,要退出双层的for循环,可以使用下面的语法:

1
2
3
4
5
6
7
8
9
lable:
for(元素变量x:遍历对象obj){
for(元素变量x1:遍历对象obj1){
// 引用了x的Java语句;
if(条件表达式){
break lable;

}
}

在上面的语法中,如果执行到break,正常情况下应该结束内层循环去执行外层循环,但是由于break后带有标签,所以程序将结束标签处的外层循环。

实例030 循环体的过滤器

实例说明

循环体中可以通过break语句中断整个循环,这增加了循环的控制能力,但是对于特殊情况还是不够,例如某些条件下需要放弃部分循环处理,而不是整个循环体。Java提供了continue语句来实现这一功能,continue语句可以放弃本次循环体的剩余代码,不执行它们而开始下轮的循环。本实例利用continue语句实现了循环体过滤器,可以过滤“老鹰”字符串,并做相应的处理,但是放弃continue语句之后的所有代码。实例的运行效果如图412所示

实现过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.mingrisoft;

public class CycFilter {
public static void main(String[] args) {
// 创建数组
String[] array = new String[] { "白鹭", "丹顶鹤", "黄鹂", "鹦鹉", "乌鸦", "喜鹊", "老鹰", "布谷鸟", "老鹰", "灰纹鸟", "老鹰", "百灵鸟" };
System.out.println("在我的花园里有很多鸟类,但是最近来了几只老鹰,请帮我把它们抓走。");
int eagleCount = 0;
// foreach遍历数组
for (String string : array) {
// 如果遇到老鹰
if (string.equals("老鹰")) {
System.out.println("发现一只老鹰,已经抓到笼子里。");
eagleCount++;
continue;// 中断循环
}
// 否则输出数组元素
System.out.println("搜索鸟类,发现了:" + string);
}
System.out.println("一共捉到了:" + eagleCount + "只老鹰。");
}
}

多学两招

break语句和continue语句都是对循环体的控制语句,它们不仅应用于for循环,在任何循环体中都可以使用这些语句,灵活使用可以让循环实现更加复杂的运算和业务处理。

技术要点

本实例应用的主要技术是continue语句。continue语句只能应用在forwhiledowhile循环语句中,用于让程序直接跳过其后面的语句,进行下一次循环。continue语句的语法比较简单,只需要在循环体中使用关键字continue加分号即可.