如果需要在控制台输出如图3.7和图3.8所示的两组图形,如何输出呢?

    图3.7 输出图形1

    3.3 循环语句 - 图2
    图3.8 输出图形2

    用之前学过的知识,可以输出这些图形,逐行输出每行的内容即可。但是,如果要输出100、1000行,怎么办?接下来,使用循环语句解决这个问题。

      while循环的语法形式如下。

      其语义是:如果循环条件的值为true,则执行循环代码块,否则跳出循环,其执行过程如图3.9所示。

    图3.9 while循环执行过程

      使用while循环,输出图3.7中的图形,代码如下。

    1. {
    2. public static void main(String[] args)
    3. {
    4. int i=0; //声明循环参数
    5. //循环20次,每次输出20个*
    6. while(i < 20){ //循环条件为i<20
    7. System.out.println("********************");
    8. i++; //循环参数+1
    9. }
    10. }
    11. }

      在使用while循环以及下面介绍的do…while循环时,必须要注意,在循环体中要改变循环条件中的参数(例如本例中的i++)或者有其他跳出循环的语句,这样才能跳出循环,否则就会出现死循环。

      下面使用while循环再完成一个案例,这个案例的需求如下。

      程序的主界面:

      1.输入数据

      2.输出数据

      3.退出程序

      当用户输入1时,执行模块1的功能,执行完毕之后,继续输出主界面;当用户输入2时,执行模块2的功能,执行完毕之后,继续输出主界面;当用户输入3时,则退出程序。具体代码如下所示,在“蓝桥系统”中也会使用类似的代码结构,需要注意。

    1. import java.util.Scanner;
    2. class TestWhile2
    3. {
    4. public static void main(String[] args)
    5. {
    6. int userSel = -1; //用户选择输入的参数
    7. while(true){//使用while(true),在单个模块功能执行结束后,重新输出主界面,继续循环
    8. System.out.println("1. 输入数据");
    9. System.out.println("2. 输出数据");
    10. System.out.println("3. 退出程序");
    11. System.out.print("请选择你的输入(只能输入1、2、3):");
    12. Scanner input = new Scanner(System.in);
    13. userSel = input.nextInt(); //从控制台获取用户输入的选择
    14. switch(userSel){
    15. case 1:
    16. System.out.println("执行1.输入数据模块");
    17. System.out.println("******************");
    18. System.out.println("******************");
    19. break;
    20. case 2:
    21. System.out.println("执行2.输出数据模块");
    22. System.out.println("******************");
    23. System.out.println("******************");
    24. break;
    25. case 3:
    26. System.out.println("结束程序!");
    27. default:
    28. System.out.println("输入数据不正确!");
    29. break;
    30. }
    31. if (userSel == 3) //当用户输入3时,退出while循环,结束程序
    32. {
    33. break;
    34. }
    35. }
    36. }
    37. }

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

    3.3 循环语句 - 图4
    图3.10 使用while循环输出主界面

      如图3.10所示,当用户输入2时,执行case 2后面的代码并跳出switch语句,之后再通过if语句判断用户输入的是否是3,如果是3,则跳出while循环,结束程序,如果不是3,则继续执行while循环,输出主界面。

      do…while循环的语法形式如下。

      do…while循环和while循环类似,不同点在于do…while循环以do开头,先执行循环代码块,然后再判断循环条件,如果循环条件满足,则继续循环。由此可见,do…while循环中的循环代码块至少会被执行一次。

      下面完成一个案例,这个案例的需求是让用户输入正确的程序密码之后,才可以执行下面的代码,否则继续让用户输入,直到输入正确为止,具体代码实现如下。

    1. import java.util.Scanner;
    2. class TestWhile3
    3. {
    4. public static void main(String[] args)
    5. {
    6. //使用字符串String存储密码,后面课程会详细介绍String类
    7. String userPass = ""; //用户输入的密码
    8. final String PASSWORD = "123456"; //正确密码为123456
    9. Scanner input = new Scanner(System.in);
    10. do{
    11. System.out.print("请输入程序密码:");
    12. userPass = input.nextLine(); //从控制台获取用户输入的密码
    13. System.out.println();
    14. //字符串的equals()方法用于判断两个字符串的值是否相同
    15. }while(!userPass.equals(PASSWORD)); //密码输入不正确,继续循环,重新输入
    16. System.out.println("程序密码正确,继续执行!");
    17. }
    18. }

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

    图3.11 do…while循环

      上面介绍了while循环和do…while循环,其实程序员在编程过程中,使用最多的循环结构是for循环。for循环主要的特点是结构清晰,易于理解,在解决能确定循环次数的问题时,首选for循环。for循环的语法形式如下。

    1. for(表达式1;表达式2;表达式3){
    2. 循环代码块
    3. }

      前面通过while循环完成了图3.7中图形的输出,下面使用for循环完成同样的功能,具体代码如下。

      for循环的重点在于其3个表达式,其中:

    • 表达式1通常是赋值语句,一般是循环语句的初始部分,为循环参数赋初值。表达式1可以省略,但需要在for语句前给循环参数先赋值。

    • 表达式 3 通常也是赋值语句,属于循环结构的迭代部分,当一次循环代码块执行完毕以后,程序执行表达式3,然后再去判断表达式2的循环条件是否满足。表达式3通常用来更改循环参数的值。表达式3也可以省略,如果省略,通常需要在循环代码块中添加修改循环参数的语句。

      综上,可以发现for循环的执行顺序如图3.12所示。

    3.3 循环语句 - 图6
    图3.12 for循环的执行顺序

      如果需要求出1~1000之间所有奇数的和,实现代码如下。

    1. class TestFor3
    2. {
    3. public static void main(String[] args)
    4. {
    5. int sum = 0;//存放和
    6. //循环参数从1开始,步长为2(奇数和),循环条件为i<=1000
    7. for(int i = 1;i <= 1000;i = i + 2 ){
    8. }
    9. System.out.println("1~1000之间所有奇数的和为:" + sum);
    10. }
    11. }

      假设“蓝桥系统”中可以存放10个Java工程师信息,现在需要分别输入这10个Java工程师的底薪,并计算出底薪大于等于6000的高薪人员比例以及这些高薪人员的底薪平均值,程序运行结果如图3.13所示。

    图3.13 计算高薪人员比例及平均底薪

      具体代码如下。

    1. import java.util.Scanner;
    2. class TestFor4
    3. {
    4. public static void main(String[] args)
    5. {
    6. int highNum = 0; //底薪大于等于6000的Java工程师人数
    7. int sumBasSalary = 0; //高薪人员底薪总和
    8. Scanner input = new Scanner(System.in);
    9. for(int i = 1;i <= 10 ; i++ )
    10. {
    11. System.out.print("请输入第" + i + "个工程师底薪:");
    12. int basSalary = input.nextInt();
    13. if(basSalary >= 6000)
    14. {
    15. highNum = highNum + 1; //高薪人员计数
    16. sumBasSalary = sumBasSalary + basSalary; //高薪人员底薪求和
    17. }
    18. }
    19. System.out.println("10个Java工程师中,高薪人员比例为:" + highNum/10.0*100 + "%");
    20. System.out.println("高薪人员平均底薪为:" + sumBasSalary/highNum);
    21. }
    22. }

      细心的读者会发现,该程序在计算过程中有一个缺陷。sumBasSalary是一个int型的整数,存放的是高薪人员底薪之和,highNum也是一个int型的整数,存放的是高薪人员人数,两个int型的数相除,结果还是int型的数,会丢失小数点后面的精度。

      前面的课程在介绍if语句的时候,提到了嵌套的if语句。同样,在for循环里,也可以嵌套for循环,如果只嵌套一次,就构成双重for循环。

      图3.7需要在控制台输出20行,每行输出20个,采用for循环20次,每次输出20个,即输出图3.7中的图形。图3.8也是需要在控制台输出20行,不过每行输出的的个数不同,第i行输出i个,所以采用单次循环无法解决这个问题。接下来,通过双重for循环,输出图3.8中的图形,具体代码如下。

      双重for循环的重点在于,内循环的循环条件往往和外循环的循环参数有关,例如本例中内循环的循环条件为j <= i,其中i是外循环的循环参数。

      下面使用双重for循环再完成一个案例,这个案例的需求很简单,输出1至100之间的质数,具体实现代码如下,程序逻辑参考代码中的注释,其中continue语句后面会详细介绍。

    1. class TestFor5
    2. {
    3. //输出1~100间质数
    4. public static void main(String[] args)
    5. {
    6. int i,j; //声明循环参数
    7. outer:for(i = 2;i < 100;i++){ //从2开始,逐个递增进行判断
    8. //Math.sqrt(i)方法是求i的平方根
    9. for(j = 2;j <= Math.sqrt(i);j++){ //从2开始,逐个递增到外循环的平方根
    10. if(i%j == 0) //外循环数除以内循环数,余0则非质数,跳出内循环
    11. continue outer; //跳出内循环,跳到outer标识的位置继续循环
    12. }
    13. System.out.println(i); //否则显示质数
    14. }
    15. }
    16. }

      在介绍switch语句的时候,首次接触了break语句,其作用是跳出switch代码块,执行switch语句后面的代码。在介绍双重for循环时,用到了continue语句,continue语句的主要作用为跳出当次循环,继续执行下一次循环。其中break、continue以及后面要学到的return语句,都是让程序从一部分跳转到另一部分,习惯上都称为跳转语句。