循环结构

概述和目标

  介绍循环语句的应用场景,学会用“循环”思想解决实际问题;介绍java中的三种循环语句,掌握循环语句的结构,学会for语句、while语句及do-while的使用,掌握各循环语句的区别及实际开发中的取舍,理解嵌套循环的应用场景,掌握嵌套循环的使用,掌握break、continue、return语句在循环语句中的使用。

一、引言

  重要提示:循环可以用于让一个程序重复地执行语句

  汝有田舍翁,家资殷盛,而累世不识"之""乎".一岁,聘楚士训其子.楚士始训之搦管临朱.书一画训曰:一字;书二画,训曰:二字;
书三画,训曰:三字.其子辄欣欣然,掷笔归告其父,曰:儿得矣,儿得矣;可无烦先生,重费馆谷也,请谢去.其父喜,从之,具币谢遗楚士.

逾时,其父拟征召姻友万氏者饮,令子晨起治状,久之不成.父趣之,其子恚曰:"天下姓氏夥矣,奈何姓万!至晨起至今,才完五百画也."

呜呼!世之学者偶一解,辄自矜有得,贻类是也.

  如果用循环这种结构来输出1万画还是很轻松的

 

二、循环的结构:

1、while循环

  ①初始化部分:只做一次初始化

while(②循环条件部分:如果循环条件满足(即该条件表达式为true),则执行循环体部分){

       ③循环体部分

       ④迭代部分:当循环体部分执行一次以后,执行迭代部分

}

 案例1、我们前面的加法测试题无论对错只能回答一次,下面这个程序提示用户输入两个个位数相加的问题给出答案:让用户重复输入新的答案,直到答案正确为止。

 1 import java.util.Scanner;
 2 
 3 public class RepeatAdditionQuiz {
 4     public static void main(String[] args) {
 5         int number1 = (int)(Math.random() * 10);
 6         int number2 = (int)(Math.random() * 10);
 7         Scanner input = new Scanner(System.in);
 8         System.out.println(number1 + " + " + number2 + " = ?");
 9         int answer = input.nextInt();
10         while(number1 + number2 != answer) {
11             System.out.println("回答错误,请再试一次," + number1 + " + " + number2 + " = ?");
12             answer = input.nextInt();
13         }
14         input.close();
15     }
16 }

案例2、猜数字,程序随机给出一个0至99(包括0和99)之间的数字,然后让你猜是什么数字。可以随便猜一个数字,游戏会提示太大还是太小,从而缩小结果范围。经过几次猜测与提示后,最终推出答案

import java.util.Random;
import java.util.Scanner;

public class GuessNumber {
    public static void main(String[] args) {
        //3.通过JDK提供给我们的随机类来生成一个随机整数
        Random random = new Random();
        int number = random.nextInt(100);//生成100以内的随机整数
        System.out.println("请猜一个100以内的数字......");
        Scanner input = new Scanner(System.in);
        int answer = -1;
        while(answer != number) {
            answer = input.nextInt();
            if(answer == number)
                System.out.println("猜对了");
            else if(answer > number)
                System.out.println("大了");
            else
                System.out.println("小了");
        }
        input.close();
    }
}

2、循环设计策略:

    step1:确定需要重复的语句

    step2:将这些语句放在一个循环体中,如下所示:

while(true){

语句组;

}

step3: 为循环继续条件编码,并为控制循环添加适合的语句。

while(循环继续条件){

语句组;

用于控制循环的附件语句;

}

示例:多个减法测试题

       遵循循环设计策略,首先,需要确定重复的语句。这些语句包括:获取两个随机数,提示用户对两数做减法然后给试题打分。然后,将这些语句放在一个循环里。最后,增加一个循环控制变量和循环继续条件,然后执行循环5次。

import java.util.Scanner;

public class SubstractionQuizLoop {
    public static void main(String[] args) {
        final int NUMBER_OF_QUESTION = 5;
        int count = 0;
        int correctCount = 0;
        Scanner input = new Scanner(System.in);
        long startTime = System.currentTimeMillis();
        while(count < NUMBER_OF_QUESTION) {
            int number1 = (int)(Math.random() * 10);
            int number2 = (int)(Math.random() * 10);
            /**
             * 交换最大数作为被减数
             */
            if(number2 > number1) {
                int temp = number1;
                number1 = number2;
                number2 = temp;
            }
            
            System.out.println(number1 + " - " + number2 + " = ");
            int answer = input.nextInt();
            if(answer == (number1 - number2)) {
                System.out.println("回答正确");
                correctCount++;
            }else {
                System.out.println("回答错误");
            }
            count++;
        }
        System.out.println("测试所化时间:" + ( (System.currentTimeMillis() - startTime)) / 1000);
        System.out.println("你回答正确数目:" + correctCount);
        System.out.println("你回答错误数目:" + (NUMBER_OF_QUESTION - correctCount));
        input.close();
    }
}

使用标记值控制循环

  读取和计算个数不确定的整数之和。

public class SentineValue {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入你要计算求和的数,0退出");
        int num = input.nextInt();
        int sum = 0;
        while(num != 0) {
            sum += num;
            System.out.println("请输入你要计算求和的数,0退出");
            num = input.nextInt();
        }
        System.out.println(sum);
        input.close();
    }
}

输入和输出重定向(了解)

  java SentineValue < input.txt > output.txt

案例:预测未来学费,假设电子科技大学今年的学费是10000元,每年以5%的速度进行增长,多少年后学费会翻倍

public class FutureTuition {
    public static void main(String[] args) {
        double tuition = 10000;
        int year = 0;
        while(tuition < 20000) {
            tuition = tuition + tuition * 0.05;// tuition * (1 + 0.05);
            year++;
        }
        System.out.println(year);
    }
}

for循环

①初始化部分:只做一次初始化

②循环条件部分:如果循环条件满足(即该条件表达式为true),则执行循环体部分

③循环体部分

④迭代部分:当循环体部分执行一次以后,执行迭代部分

for(①;②;④){

       ③

}

for循环的执行顺序:①->②->③->④->②->③->④->②如果条件不满足,循环结束...

 案例:使用穷举法求最大公约数(k(k=2,3,4,...)是否是num1和num2的公约数,直到k大于num1或num2)

public class GreatestCommonDivisor {
    public static void main(String[] args) {
        System.out.println("请输入两个整数:");
        Scanner input = new Scanner(System.in);
        int num1 = input.nextInt();
        int num2 = input.nextInt();
        if(num1 < num2) {
            int temp = num1;
            num1 = num2;
            num2 = temp;
        }
        int gcd = 1;
        for(int k = 2;k <= num1 && k <= num2;k++) {
            if(num1 % k == 0 && num2 % k == 0) {
                gcd = k;
            }
        }
        System.out.println(num1 + "," + num2 + "的最大公约数为:" + gcd);
        input.close();
    }
}

显然,该算法的复杂度为O(num2),即O(n),如果不从1开始往上找,而是从num2往下找,这样会更高效,一旦找到这个数,该除数就是最大公约数。因此可以使用下面的循环改进

for(int k = num2; k >= 1; k--) {
    if(num1 % k == 0 && num2 % k == 0) {
        gcd = k;
    //找到就退出循环
    break;
    }
}    

这个算法比前一个更高效,但是它在最坏情况下的时间复杂度依旧是O(n).

数字num2的除数不可能比num2/2大,因此,可以使用下面的循环进一步改进算法

for(int k = num2 / 2; k >= 1; k--) {
    if(num1 % k == 0 && num2 % k == 0) {
        gcd = k;
        //找到就退出循环
        break;
    }
}

但是,该算法是不正确的,因为num2有可能是num1的除数。这种情况必须考虑到。,正确的算法如下

public class GCD{
    public static void main(String[] args) {
        System.out.println("请输入两个整数:");
        Scanner input = new Scanner(System.in);
        int num1 = input.nextInt();
        int num2 = input.nextInt();
        if(num1 < num2) {
            int temp = num1;
            num1 = num2;
            num2 = temp;
        }
        int gcd = 1;

        if(num1 % num2 == 0) return num2;
        for(int k = num2 / 2; k >= 1; k--) {
            if(num1 % k == 0 && num2 % k == 0) {
                gcd = k;
                //找到就退出循环
                break;
            }
        }
        System.out.println(num1 + "," + num2 + "的最大公约数为:" + gcd);
        input.close();
    }
}

打印出101年到2100年之间所有的闰年,每行打印10个,每个以制表符进行分割

public class PrintLeapYear {
    public static void main(String[] args) {
        for(int year = 101,line = 0;year <= 2100; year++) {
            if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
                System.out.print(year + "\t");
                line++;
            }
            if(line == 10) {
                System.out.println(); 
                line = 0;
            }
        }
    }
}

do-while循环

①初始化部分:只做一次初始化

②循环条件部分:如果循环条件满足(即该条件表达式为true),则执行循环体部分

③循环体部分

④迭代部分:当循环体部分执行一次以后,执行迭代部分

do-while循环的组成

do{

       ③

       ④

}while(②);

public class DoWhileDemo {
    public static void main(String[] args) {
        int sum = 0;
        int num;
        Scanner input = new Scanner(System.in);
        do {
            num = input.nextInt();
            sum += num;
        }while(num != 0);
        System.out.println(sum);
        input.close();
    }
}

while和do-while的区别:

       while循环是先进行循环条件的判断,如果满足则执行循环体。

       do-while循环是先执行一次do后语句块的内容(循环体和迭代部分),再执行循环条件的判断。

注意事项

    1.理解“循环”思想是学习循环结构的前提,结合多个生活中的例子理清循环的组成部分,尤其是循环条件的作用;

    2.讲解for循环、while循环和do-while循环时,先讲循环结构各组成部分的声明位置,再讲各组成部分的执行顺序;

    3. 嵌套循环是本次课程的重点和难点,应多画图来分析每一次循环过程;

    4. break、continue、return的区别以及标签的使用;

    5. 同一语句块中break、continue、return后的语句不再执行。

三、嵌套循环:

循环体内包含循环。内层的循环作为外层循环的循环体。

外层循环:控制着行数

内层循环:控制着列数

public class MultiLoop {
    public static void main(String[] args) {
        for(int i = 1; i <= 9; i++) {
            for(int j = 1; j <= i;j++) {
                System.out.print(i + " * " + j + " = " + (i * j) + "\t");
            }
            System.out.println();
        }
    }
}

四、break、continue、return的使用

1.break:结束(跳出)当前循环,不再进入下一次循环。注意:“当前”指的是break所在的循环。

了解“标记”的使用:1)用于给break、continue指明要结束的循环。

                      2)只能用在循环语句前面

                      3)标记的命名遵循标识符的命名规则和规范

示例:判断回文数(课堂练习)

import java.util.Scanner;

/**
 * 判断一个字符串是否是回文
 *
 */
public class Palindrome {
    /**
     * 从前往后以及从后往前都是一样的,它就是一个回文串,比如“1001”,“dad”,“mom”
     * 解决方案
     *         判断字符串的第一个字符(“1001“.charAt(0))和最后一个字符(“1001”.charAt(“1001”.length() - 1)),如果相等
     * 继续判断第二个字符及倒数第二个字符是否相等,这个过程一直持续找到不匹配,或者字符串中的每个字符都进行判断
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("请输入一个字符串:");
        Scanner input = new Scanner(System.in);
        String str = input.nextLine();
        int low = 0;
        int high = str.length() - 1;
        boolean isPalindrome = true;
        while(low < high) {
            if(str.charAt(low) != str.charAt(high)) {
                isPalindrome = false;
                break;
            }
            low++;
            high--;
        }
        
        if(isPalindrome)System.out.println(str + "是一个回文串");
        else System.out.println(str + "不是一个回文串");
        
        input.close();
    }
}

示例:显示素数(课堂练习)

/**
 * 显示前50个素数,每行显示10个
 * 素数:大于1的整数,只能被1和它自身整除的数即是素数
 * 1.判断给定的一个数十不是素数
 * 2.number=2,3,4,5,,,,
 * 3.统计素数个数
 * 4.打印
 * @author Adan
 * 测试一个数是不是一个素数:
 *     检测这个数能否被2,3,4一直到number/2整除,如果能被任意一个整除,就不是素数,break
 *
 */
public class PrimeNumber {
    
    public static void main(String[] args) {
        final int NUMBER_OF_PRIMES = 50;
        final int NUMBER_OF_LINES = 10;
        int count = 0;//定义一个计数器,统计素数的个数
        int number = 2;
        while(count < NUMBER_OF_PRIMES) {
            boolean isPrime = true;
            //判断number是不是一个素数
            for(int divisor  = 2; divisor <= number / 2; divisor++) {
                if(number % divisor == 0) {
                    isPrime = false;
                    break;
                }
            }
            if(isPrime) {
                count++;
                if(count % NUMBER_OF_LINES == 0)
                    System.out.println(number);
                else System.out.print( number+ " ");
            }
            number++;
        }
    }
}

2.continue的用法:跳过所在(指定)循环的当次循环,进入下一次循环。

public class ContinueDemo {
    public static void main(String[] args) {
        for(int i = 1; i <= 100; i++) {
            if(i % 2 != 0)
                continue;//结束本次循环,判断下次循环条件,继续下一次循环
            System.out.print(i + " ");
        }
    }
}

注意:当发生跳过或结束循环时,break、continue后的语句不再执行

3.return的用法(后续):

1)当return用在方法里,表示将return 语句中return后的值返回给方法的调用者(了解),然后方法结束。因此,return语句后不能再跟着其他语句

       2)return用在循环里,会终止循环,并且结束return所在的方法。因此后面的语句不执行。

作业

1.求1至1000之间满足“用3除余2;用5除余3;用7除余2”的数,且一行只打印5个数

2.求1-3+5-7+ …… -99+101的值

3.打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身

4.输入两个正整数m和n,求其最大公约数和最小公倍数

5.百元百鸡问题:公鸡5元一只,母鸡3元一只,3只小鸡1元,如果用100元钱,买100只鸡,不佘不欠,可以买公鸡,母鸡,小鸡,各多少只。

6.编写一个Java应用程序,用循环结构打印如下的数值列表:

N                 10*N                 100*N               1000*N

1                  10                    100                 1000

2                  20                    200                 2000

3                  30                    300                 3000

4                  40                    400                 4000

5                  50                    500                 5000

7.打印2到10000的所有素数,每行显示8个素数

8.3000米长的绳子,每天减一半,问,需要多少天,绳子会小于5米?

9.显示从1012100期间所有的闰年,每行显示10,之间用制表符分割

10.猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第十天早上在想吃时,就只剩一个桃子了。求第一天共摘了多少个桃子?

11.养老无忧计划:以目前的生活水平想要无忧养老需要存够600万养老金,假设你每年可以存N万,年利率为3%,问需要做牛做马多少年?

12.鸡兔同笼:今有雉(鸡)兔同笼,上有三十五头,下有九十四足。问雉兔各几何。

13.5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?

14.有1234四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

15.一个数恰好等于它的因子之和,这个数就被称为完数。例如,6的因子为123,而61+2+3,因此6完数。编程找出1~n之内的所有完数。

16.有一对兔子,从出生第三个月起每个月都生一对兔子,小兔子长到第三个月后,每个月又生一对兔子,假如兔子都不死,每个月的兔子总数。

17.一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高?

18.啤酒瓶。买了100瓶啤酒,每三个空瓶可以兑换一瓶啤酒,问最多可以喝多少瓶啤酒

19.打印下列图形(方框忽略)

1.

2.

3.

4.

5.

6.

20.验收手机号码是否输入正确(1、 必须是11位数字;2、 前三位必须是130-139,158-159,186)

21、验收用户名是否输入正确(不可以用正则表达式),要求:

1、        必须是数字、大写字母、小写字母、下划线中的三种组成

2、        首字母必须是字母或下划线开头

3、        字符长度4-10

 

 

面试常见问题

1. 什么时候用for循环,什么时候用while循环

2. while循环和do-while循环的区别

3. break、continue、return的区别

验收手机号码是否输入正确

posted @ 2020-04-16 23:04  Tiger-Adan  阅读(1869)  评论(0编辑  收藏  举报