Java循环结构进阶

简介: Java循环结构进阶

1二重循环结构

通过前面的学习,我们已经知道了什么是循环,以及循环的三种形式,即 while 循环do-while循环for 循环,本章我们将深入学习循环——二重循环,并使用二重循环解决更复杂的问题。

1.1 技能训练

上机练习1

练习——计算竞赛平均分

需求说明

  • 某次程序大赛,某班有四名学员参加,学员的成绩由用户输入,计算该班参赛学员的平均分。

  • 程序运行结果如图 9.1 所示。

图 9.1 上机练习 1 的运行结果

提示:参考实现步骤如下。

(1) 定义一个数组,保存学员成绩。

(2) 利用循环将数组中的成绩累加。

(3) 计算平均成绩并输出。

1.2 为什么使用二重循环

问题:在上机练习 1 中通过编写程序,计算出了一个班级的平均分,但如果有三个班级各四名学员参赛,如何计算每个班级参赛学员的平均分呢?


分析:循环能够解决计算机重复执行的动作,所以对于上机练习 1, 利用循环重复输入一个班级四位参赛学员的成绩。现在是三个班级,因此需要循环三次计算每个班的平均分。而每个班有四名学员,所以对每个班级需要循环四次累加总分。可以用一个循环控制班级的数量,用另一个循环控制每个班级学员的数量,这样就得到了二重循环。

1.3 什么是二重循环

什么是二重循环呢?简单地说,二重循环就是一个循环体内又包含另一个完整的循环结构。前面我们学习了三种循环: while 循环、 do-while 循环和 for 循环。这三种循环之间是可以互相嵌套的,一个循环要完整地包含在另一个循环中,如下面四种形式都是合法的。


语法


//while与while循环嵌套


while() {


  //循环操作1


  while(循环条件2) {


      //循环操作2;


}


}


//do-while与do-while循环嵌套


do {


  //循环操作1


  do {


      //循环操作2


}while(循环条件2);


}while(循环条件1);


//for与for循环嵌套


for(循环条件1){


//循环操作1


for(循环操作2) {


   //循环操作2


}


}


//while与for循环嵌套


while(循环条件1){


//循环操作1


for(循环条件2){


   //循环操作2


}


}


上面四种形式中,循环条件 1 和循环操作 1 对应的循环称为外层循环,循环条件 2 和循环操作 2对应的循环称为内层循环,内层循环结束后才执行外层循环的语句。在二重循环中,外层循环变量变化一次,内层循环变量要从初始值到结束值变化一遍。

1.4 如何使用二重循环

知道了二重循环的形式,下面就利用二重循环解决计算三个班级平均分的问题。

示例1

package cn.jbit.array;

import java.util.Scanner;

/*

* 计算3个班级的平均分

*/

public class AvgScore {

   public static void main(String args[]){

       int[] score = new int[4];           //成绩数组

       int classNum = 3;                 //班级数目

       double sum = 0.0;                 //成绩总和

       double average = 0.0;              //平均成绩


       //循环输入学员成绩

       Scanner input = new Scanner(System.in);

       for(int i = 0; i < classNum; i++){

           sum = 0.0f;                      //成绩总和归0

           System.out.println("请输入第" + (i+1) + "个班级的成绩");

           for(int j = 0; j < score.length; j++){

               System.out.print("第" + (j+1) + "个学员的成绩:");

               score[j] = input.nextInt();

               sum = sum + score[j];        //成绩累加

           }

           average = sum / score.length;  //计算平均分

           System.out.println("第" + (i+1) + "个班级参赛学员的平均分是:" + average + "\n");

       }

   }

}


b16aca5f40da442c9dd4cb27768d9252.png

示例 1 演示了如何用二重循环计算每个班级平均分的问题。在这个示例中,使用了两个 for 循环,其中外层循环控制班级的数量,内层循环控制每个班参赛学员的人数。程序运行结果如图 9.2所示。


2fa9bbf5a38248c3b4aa59c9aa4ae42d.png


                                                   图 9.2 示例 1 的运行结果

二重循环使用起来很方便。下面通包一个示例,学习如何用二重循环打印图形。

问题:用字符*打印矩形图案,效果如下。

*****

*****

*****

*****

*****

分析:上面的图形共有五行,需循环五次打印每行,每行有五个字符*,需循环五次打印字符*,可以用二重循环实现。外层循环控制行数,内层循环控制每行的字符*的个数。所以外层循环变量i的值为 1〜5,内层循环变量j 的值也为1〜5 。

用二重循环打印矩形字符*的代码如示例 2 所示。

示例2


package cn.jbit.array;

/**

* 打印矩形

*/

public class Rectangle {

   public static void main(String[] args) {

       System.out.println("打印矩形");

       for(int i = 0; i < 5; i++){

           for(int j = 0; j <5; j++){

               System.out.print("*");

           }

           System.out.print("\n");       //换行

       }

   }

}


67cfcaab62304c51a58bec34f565b40d.png

循环结构包括循环条件和循环操作。上述代码中,变量 i 表示第 i 行,现在要打印五行,可以得到外层循环条件。内层循环操作就是打印字符*,变量 j 控制了内层循环的循环条件。根据分析,每行打印五个字符*,这样就得到了内层循环条件,打印完一行后要换行。程序运行结果如图 9.3 所示。

图 9.3 示例 2 的运行结果

2 跳转语句进阶

如果希望循环在某种条件下不按正常流程执行,需要用到continue或break语句。那么,如何在二重循环中使用continue和break语句呢?它们怎样控制程序的执行呢?

2.1 在二重循环中使用 continue 语句

示例3的代码是在示例1的基础上扩展的,同学们能看出它的作用吗?这段代码的作用就是统计成绩在85分及以上的学员共有多少名。

示例3


package cn.jbit.array;

import java.util.Scanner;

/**

* continue断点演示:计算成绩85分以上的学员人数

*

*/

public class ContinueDemo {

   public static void main(String[] args) {

       int[] score = new int[4];           //成绩数组

       int classnum = 3;                 //班级数目

       double sum = 0.0;                 //成绩总和

       double average = 0.0;              //平均成绩


       int count = 0;                   //记录85分以上学员人数


       //循环输入学员成绩

       Scanner input = new Scanner(System.in);

       for(int i = 0; i < classnum; i++){

           sum = 0.0f;                      //成绩总和归0

           System.out.println("请输入第" + (i+1) + "个班级的成绩");

           for(int j = 0; j < score.length; j++){

               System.out.print("第" + (j+1) + "个学员的成绩:");

               score[j] = input.nextInt();

               sum = sum + score[j];        //成绩累加


               if(score[j] < 85){ //成绩小于85,则跳出本轮循环

                   continue;

               }

               count++;

           }

           average = sum / score.length;

           System.out.println("第" + (i+1) + "个班级参赛学员的平均分是:" + average + "\n");

       }

       System.out.println("成绩85分以上的学员人数有" + count + "人");

   }

}


程序运行结果如图9.9所示。

6b82646a392a4052a5d825e6547a9c48.png

从运行结果中可以看出,当输入的成绩小于85分时,continue语句后面的count++不会执行,而是回到内层for循环的开始继续输入下一个学员的成绩。如果输入的成绩大于85分,则会执行count++。输入完三个班级所有参赛学员的成绩后,打印出count的值。所以在内层循环中的continue语句,跳转时是跳过了内层循环中的剩余语句进入内层循环的下一次循环。

图9.9示例3的运行结果

2.2 在二重循环中使用 break 语句

问题:使用循环和break语句模拟购物结账问题。假设有五家衣服专卖店,每家限购三件衣服。用户可以选择离开,也可以买衣服。最后打印出总共购买了几件衣服。

分析:使用二重循环解决,其中外层循环控制去每个专卖店的过程,内层循环控制买衣服的过程。如果用户选择离开,则进入下一家店,因此购物过程大致如下。


for (int i = 0; i < 5; i++) {        //每次进入一家店


for(int j = 0; j < 3; j ++) {    //每家店限购三件衣服


if  (离开这家店){


break;


}


//选购一件衣服;


}


//结账;


}


示例4是实现的代码。


示例4


package cn.jbit.array;

import java.util.Scanner;

/*

* break断点演示:实现购物结账

*/

public class BreakDemo {

   public static void main(String[] args) {

       int count = 0;    //记录一共买了几件衣服

       String choice;    //顾客选择是否离开

       Scanner input = new Scanner(System.in);


       for(int i = 0; i < 5; i++){

           System.out.println("欢迎光临第" + (i+1) + "家专卖店");

           for(int j = 0; j < 3; j++){

               System.out.print("要离开吗(y/n)?");

               choice = input.nextLine();

               if("y".equals(choice)){    //如果离开,则跳出,进入下一家店

                   break;

               }

               System.out.println("买了一件衣服");

               count++;

           }

           System.out.println("离店结账\n");

       }

       System.out.println("总共买了" + count + "件衣服");

       choice = input.nextLine();

   }

}

4b3160d41bec441ba9a09d291b879de9.png


根据专卖店的数量得到外层循环的条件,根据限购衣服的数量得到内层循环的条件。在内层循环中,如果用户选择离开,则跳出内层循环,离店结账,进入下一家店。当五家专卖店都购物完毕时,打印出总共购买了几件衣服。程序运行结果如图9.10所示。

图9.10示例4的运行结果

2.3  二重循环中 continue 和 break 语句的对比

当continue和break语句用在内层循环时,只会影响内层循环的执行,对外层循环没有影响,它们的不同点在于执行该语句后,程序跳转的位置不同,以二重for循环为例,两个语句的对比如表9-1所示。

表9-1 continue和break语句的对比

Continue

break

for(……)

{

for(……)

{

    ……

    continue;

    ……

}

……

}

for(……)

{

for(……)

{

    ……

    break;

    ……

}

……

}

由表9_1可以看出,continue语句是跳出本次循环,进入下一次循环。而break是跳出本层循环,即提前结束本层循环,执行循环下面的语句。

目录
相关文章
|
4月前
|
Java C语言
|
5月前
|
Java Perl
Java进阶之正则表达式
【7月更文挑战第17天】正则表达式(RegEx)是一种模式匹配工具,用于在字符串中执行搜索、替换等操作。它由普通字符和特殊元字符组成,后者定义匹配规则。
36 4
|
5月前
|
设计模式 Java
Java进阶之代理
Java进阶之代理
28 4
|
5月前
|
设计模式 Java
Java进阶之代理
Java进阶之代理
31 3
|
5月前
|
设计模式 Java
Java进阶之代理
【7月更文挑战第16天】Java动态代理通过`java.lang.reflect.Proxy`和`InvocationHandler`实现,无需编译期定义代理类。与静态代理相比,它更灵活,代码更简洁,适用于方法数量变化或未知接口代理。
32 2
|
5月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
43 6
|
5月前
|
Java 编译器 API
Java进阶之标准注解
【7月更文挑战第15天】Java标准注解包括标记注解(如@Deprecated)、@Override(检查方法重写)、@SuppressWarnings(抑制警告)。多值注解如@RequestMapping在Spring中用于HTTP请求映射。元注解如@Retention控制注解保留策略,@Target指定应用位置。Java8引入类型注解(@FunctionalInterface、@SafeVarargs)和重复注解(@Repeatable)。自定义注解可通过反射读取,如示例中的MyMarkerAnnotation等。
27 2
|
5月前
|
安全 Java
Java进阶之枚举
【7月更文挑战第11天】Java枚举是Java 5引入的特性,用于定义固定常量集合,如星期。枚举是继承自`java.lang.Enum`的特殊类,编译后成为final类,每个枚举值是静态final实例。定义枚举用`enum`关键字,如`public enum Weekday {MONDAY, TUESDAY, ...}`。枚举可包含方法和变量,能实现接口但不能继承其他类。例如,`Weekday`枚举可实现`Describe`接口,提供`describe()`方法。在实际应用中,枚举常用于表示如响应状态等固定选项,便于类型安全和代码阅读。
41 8
|
5月前
|
Java 编译器 API
Java进阶之标准注解
Java进阶之标准注解
31 1
|
5月前
|
IDE Java 测试技术
Java进阶之反射
【7月更文挑战第14天】Java反射机制允许在运行时动态获取类信息、创建对象及调用其方法。它基于`Class`类,让我们能访问类的属性、方法、构造器。例如,通过`Class.forName()`加载类,`Class.newInstance()`创建对象,`Method.invoke()`执行方法。反射广泛应用于动态代理、单元测试、序列化及框架中,提供灵活性但牺牲了性能,且可破坏封装性。IDE的代码补全也是反射的应用之一。在使用时需谨慎,避免对私有成员的不当访问。
41 1