java循环结构进阶-2

简介: 指导——输入行数,打印直角三角形

9.1.5 技能训练

上机练习2


指导——输入行数,打印直角三角形


训练要点


二重循环及循环条件的设定。

使用 Scanner 对象接收用户输入。

需求说明


从控制台输入直角三角形的高度(行数)。

每行字符*的个数依次为1、3、5、7、9等。

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

实现思路及关键代码


(1) 外层循环控制行数。根据用户输入的行数得到外层循环条件。例如,假如用户输入的行数是 5, 则外层循环变量 i 的值为 1〜5 。


(2) 分析每行打印的内容。每一行均打印字符*,某一行与该行字符*个数是什么关系呢?首先分析内层循环变量 j 的变化规律(假如用户输入的行数是 5):


第一行,i = 1,打印 1 个字符*, 内层循环 1 次,j 的取值只有 1 。


第二行,i = 2,打印 3 个字符*, 内层循环 3 次,j 的取值为 1〜3 。


第三行,i = 3,打印 5 个字符*, 内层循环 5 次,j 的取值为 1〜5 。


第四行,i = 4,打印 7 个字符*, 内层循环 7 次,j 的取值为 1〜7 。


第五行,i = 5,打印 9 个字符*, 内层循环 9 次,j 的取值为 1〜9 。


不难发现,对于每一行,j 的最大值为 2×i-1, 从而得到内层循环条件,即 2×i-1。


(3) 每一行打印字符*结束后要换行。


图 9.4 上机练习 2 的运行结果


参考解决方案

package cn.jbit.array;
import java.util.Scanner;
/**
 * 输入行数打印直角三角形
 */
public class RTriAngle {
    public static void main(String[] args) {
        int rows = 0;  //三角形行数
        System.out.print("请输入直角三角形的行数:");
        Scanner input = new Scanner(System.in);
        rows = input.nextInt();
        //打印直角三角形
        for(int i = 1; i <= rows; i++){
            for(int j = 1; j <= 2*i-1; j++){
                System.out.print("*");
            }
            System.out.print("\n");
        }
    }
}

上机练习3


练习——输入行数,打印倒直角三角形


需求说明


从控制台输入直角三角形的高度(行数)。

每行字符*的个数从下至上依次为1、2、3、4等。

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

图9.5上机练习3的运行结果


提示:


外层循环控制行数,根据用户输入的行数得到外层循环条件。

分析每行打印的内容:每一行均打印字符 * ,某一行与该行字符 * 个数之和等于行数加1,从而得到内层循环条件。

参考代码示范

package cn.jbit.array;
import java.util.Scanner;
/**
 * 输入行数打印倒直角三角形
 */
public class InvertRTriAngle {
    public static void main(String[] args) {
        int rows = 0;  //三角形行数
        System.out.print("请输入直角三角形的行数:");
        Scanner input = new Scanner(System.in);
        rows = input.nextInt();
        //打印倒直角三角形
        for(int i = 1; i <= rows; i++){
            for(int j = 1; j <= rows+1-i; j++){
                System.out.print("*");
            }
            System.out.print("\n");
        }
    }
}

上机练习4


练习——输入行数,打印等腰三角形


需求说明


从控制台输入等腰三角形的高度(行数)。

每行字符*的个数依次为1、3、5、7等。

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

图9.6上机练习4的运行结果


提示:外层循环控制行数,根据用户输入的行数得到外层循环条件。


分析每行打印的内容:每一行先打印空格,再打印字符*。打印空格和打印字符*用两个不同的for循环。为了清晰起见,下面以#号代替空格来分析每行空格数、字符*个数和行数的关系,程序运行结果如图9.7所示。


由图9.7可以看出,从第一行开始字符#个数分别为4、3、2、1,而字符*个数为1、3、5、7、9。因此我们可以得到如下关系:第i行的空格数与i 之和等于rows,第i 行字符*个数为2×i-l,从而得到两个内层for循环的循环条件。


图9.7上机练习4的运行结果分析


参考代码示范

package cn.jbit.array;
import java.util.Scanner;
/**
 * 输入行数打印等腰三角形
 */
public class IsoTriangle2 {
    public static void main(String[] args) {
        int rows = 0;  //三角形行数
        System.out.print("请输入等腰三角形的行数:");
        Scanner input = new Scanner(System.in);
        rows = input.nextInt();
        //打印等腰三角形
        for(int i = 1; i <= rows; i++){
            for(int j = 1; j <= rows-i; j++){
                System.out.print("#");
            }
            for(int k = 1; k <= 2*i-1; k++){
                System.out.print("*");
            }
            System.out.print("\n");
        }
    }
}


上机练习5


指导——打印九九乘法表


训练要点


复杂的二重循环。

需求说明


利用二重循环实现九九乘法表。

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

图9.8上机练习5的运行结果


实现思路及关键代码


(1)九九乘法表共有九行,因此:


for (int i = 1; i <= 9; i++) {
//打印第 i 行;
//换行;
}


(2) 第i行上有i个式子,因此:

for(int i = 1; i <= 9; i++){
for(int j = 1; j <= i; j ++) {
//打印第 i 行上的第 j 个式子;
}
//换行;
}


(3) 分析第i行上的第j个式子,应该为j的值×i的值=j×i的值。


参考解决方案

package cn.jbit.array;
/**
 * 打印九九乘法表
 */
public class MuITable {
    public static void main(String[] args) {
        int rows = 9;                 //乘法表的行数
        for(int i = 1; i<=rows; i++){     //一共9行
            for(int j = 1; j <= i; j++){   //第i行有i个式子
                System.out.print(j+"*"+i+"="+j*i+" ");
            }
            System.out.print("\n");          //打印完一行后换行
        }
    }
}


9.2跳转语句进阶

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


9.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所示。


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


图9.9示例3的运行结果


9.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();
    }
}


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


图9.10示例4的运行结果


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

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


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



image.png


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


9.2.4 技能训练

上机练习6


练习——统计打折商品的数量


需求说明


有三名顾客去商场购物,每人买了三件商品。规定:单价300元以上的商品享受八折优惠。请编写程序统计每人享受打折优惠的商品有多少。

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

提示:


外层循环控制顾客数量,即i<3。


内层循环控制每人买了多少件商品,即j<3。


循环接收每人所购商品的价格。


判断商品单价是否高于300元。如果是,计数;否则跳过本次循环。


                                                   


图9.11上机练习6的运行结果


参考代码示范


package cn.jbit.array;
import java.util.Scanner;
/**
 * 统计打折商品数量
 */
public class Demo {
    public static void main(String[] args) {
        int count = 0;    //记录打折商品数量
        Scanner input = new Scanner(System.in);
        double price=0.0; //商品价格
        for(int i = 0; i < 3; i++){
            System.out.println("请输入第"+(i+1) +"个人所购的三件商品的价格:");
            for(int j = 0; j < 3; j++){
                price=input.nextDouble();
                if(price<300)
                    continue;
                count++ ; //累计
            }
            System.out.println("第"+(i+1) +"个人共有" +count + "件商品享受8折优惠!");
            count=0;//重置count值
        }
    }
}


本章总结


二重循环就是一个循环体内又包含另一个完整的循环结构的循环。

在二重循环中可以使用break、continue语句控制程序的执行。


相关文章
|
4月前
|
Java C语言
|
5月前
|
Java Perl
Java进阶之正则表达式
【7月更文挑战第17天】正则表达式(RegEx)是一种模式匹配工具,用于在字符串中执行搜索、替换等操作。它由普通字符和特殊元字符组成,后者定义匹配规则。
34 4
|
5月前
|
设计模式 Java
Java进阶之代理
Java进阶之代理
27 4
|
5月前
|
设计模式 Java
Java进阶之代理
Java进阶之代理
30 3
|
5月前
|
设计模式 Java
Java进阶之代理
【7月更文挑战第16天】Java动态代理通过`java.lang.reflect.Proxy`和`InvocationHandler`实现,无需编译期定义代理类。与静态代理相比,它更灵活,代码更简洁,适用于方法数量变化或未知接口代理。
31 2
|
5月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
40 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