Day3 : Scanner对象 / 顺序结构 / 选择结构 / 循环结构 / break&continue / 练习

1.Scanner对象

Scanner s = new Scanner(System.in);

通过Scanner类的next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要使用hasNext() 与 hasNextLine() 判断是否还有输入的数据。

next():

  1. 一定要读取到有效字符后才可以结束输入

  2. 对输入有效字符之前遇到的空白,next()方法会自动将其去掉

  3. 只有输入有效字符后才将其后面输入的空白作为分隔符或这结束符

  4. next()不能得到带有空格的字符串。

nextLine();

  1. 以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符

  2. 可以获得空白

使用 next 方法:

import java.util.Scanner;

public class ScannerDemo {
    public static void main(String[] args) {
        //首先创建一个扫描器,用于接收键盘数据
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入数据:");
        if (scanner.hasNext()) {
            //使用next方式接收
            String str = scanner.next();
            System.out.println("收到的数据为:" + str);
        }
        //凡是属于IO流的类,如果不关闭,会一直占用资源。
        scanner.close();
    }
}

结果

请输入数据:
hello world
收到的数据为:hello

使用 nextLine 方法:

import java.util.Scanner;

public class ScannerNextLine {
    public static void main(String[] args) {
        //从键盘接收数据
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入数据:");
        //判断是否还有输入
        if (sc.hasNextLine()) {
            String str = sc.nextLine();
            System.out.println("收到的数据为:" + str);
        }
        sc.close();
    }
}

结果

请输入数据:
hello world
收到的数据为:hello world

Scanner进阶用法(输入基本数据类型)

如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,

但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:

比如输入int类型的数据

if (sc.hasNextInt()) {
    int i = sc.nextInt();
    System.out.println("收到的数据为:" + i);
}

练习

输入多个数字,并求其总和与平均数,通过输入非数字来结束输入并输出执行结果:

import java.util.Scanner;

public class Sum {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int sum = 0;
        int count = 0;
        while (sc.hasNextInt()) {
            int num = sc.nextInt();
            sum += num;
            count++;
        }
        System.out.println("总和:" + sum);
        System.out.println("平均:" + (1.0 * sum / count));

        sc.close();
    }
}

结果·

1 2 3 4 5 q
总和:15
平均:3.0

注意

当使用nextLine()方法之前,使用过其他的方法,需要多使用一次nextLine()方法

如下代码,先输入一个年龄,再输入姓名

import java.util.Scanner;

public class ScannerBug {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = 0;
        String str = null;
        if (sc.hasNextInt()) {
            num = sc.nextInt();
        }
        if (sc.hasNextLine()) {
            str = sc.nextLine();
        }
        System.out.println("---------输出结果-------");
        System.out.println("年龄" + num);
        System.out.println("姓名" + str);

        sc.close();
    }
}

结果

18
---------输出结果-------
年龄18
姓名

分析

在输入18按下回车之后,直接打印结果。跳过了姓名的输入,不妨试试使用空格分离输入的参数。

18 ljh
---------输出结果-------
年龄18
姓名 ljh

发现姓名后面多了个空格才打印输入的名字,说明nextInt()方法只读取到18。

18往后的数据都被nextLine()接收,正好nextLine()方法可以接收空白,所以包含了空格。

如果将nextLine()方法改成next()方法,不包含空白,可以解决以上问题。

package com.study.scanner;

import java.util.Scanner;

public class ScannerBug {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int num = 0;
        String str = null;
        if (sc.hasNextInt()) {
            num = sc.nextInt();
        }

        if (sc.hasNext()) {
            str = sc.next();
        }

        System.out.println("---------输出结果-------");
        System.out.println("年龄" + num);
        System.out.println("姓名" + str);

        sc.close();
    }
}

结果

18 ljh
---------输出结果-------
年龄18
姓名ljh


18
ljh
---------输出结果-------
年龄18
姓名ljh

那么就是要求nextLine()读取下一行数据怎么办呢?

如新增一个需求再读取一个电话号码,要求区号和尾号用空格隔开

public class ScannerBug {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int num = 0;
        String str = null;
        String phone = null;
        if (sc.hasNextInt()) {
            num = sc.nextInt();
        }
        if (sc.hasNext()) {
            str = sc.next();
        }
        if (sc.hasNextLine()) {
            phone = sc.nextLine();
        }
        System.out.println("---------输出结果-------");
        System.out.println("年龄" + num);
        System.out.println("姓名" + str);
        System.out.println("电话" + phone);

        sc.close();
    }
}

结果

18
ljh
---------输出结果-------
年龄18
姓名ljh
电话


18 ljh 0771 1234
---------输出结果-------
年龄18
姓名ljh
电话 0771 1234

两种输入方式,第一种 nextLine()方法又读取了ljh后面的数据,导致第三个数据不能输入。

第二种输入方式多了个空格

考虑应该把ljh后面的数据给吃掉。再接收第三个数据

import java.util.Scanner;

public class ScannerBug {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int num = 0;
        String str = null;
        String phone = null;
        if (sc.hasNextInt()) {
            num = sc.nextInt();
        }

        if (sc.hasNext()) {
            str = sc.next();
        }

        if (sc.hasNextLine()) {
            sc.nextLine();// 去除前一行多余的数据
            phone = sc.nextLine();
        }

        System.out.println("---------输出结果-------");
        System.out.println("年龄" + num);
        System.out.println("姓名" + str);
        System.out.println("电话" + phone);

        sc.close();
    }
}

结果

18
ljh
0771 1234
---------输出结果-------
年龄18
姓名ljh
电话0771 1234

最终达到想要的效果。

总结

nextXxx()方法只读取到相应的数值就停止,不含换行操作。

nextLine()方法在后面使用时,注意前面的方法是否含有换行处理。

2.顺序结构

java的基本结构,除非特别指明,否则按照顺序一句一句执行。

最简单的算法结构

image-20200506120342289

它是任何一个算法都离不开的一种基本算法结构

public class SequenceFlow {
    public static void main(String[] args) {
        System.out.println("从上到下执行");
        System.out.println("先输出1");
        System.out.println("2");
        System.out.println("3");
        System.out.println("4");
        System.out.println("最后输出5");
        System.out.println("结束");
    }
}

3.选择结构

  1. if单选择结构

    if(布尔表达式){
        //如果布尔表达式为true将执行语句
    }

    image-20200916103022231

    public class IfDemo01{
        public stati void main(String[] args){;
            Scanner scanner = new Scanner(System.in);
                                              
            System.out.println("请输入内容:");
            String s = scanner.nextLine();
            
            //equals: 判断字符串是否想等
            If(s.equals("Hello")){
                System.out.println(s);
            }            
                                              
            System.out.println("End");
            scanner.close();    
        }
    }

     

  2. if双选择结构

    if(布尔表达式){
        //如果布尔表达式为true将执行语句
    }else{
        //如果布尔表达式为false将执行语句
    }

    image-20200916104740946

  3. if多选择结构

    if(布尔表达式 1){
        如果布尔表达式 1的值为true执行代码
    }else if(布尔表达式 2){
        如果布尔表达式 2的值为true执行代码
    }else if(布尔表达式 3){
        如果布尔表达式 3的值为true执行代码
    }else{
        如果以上布尔表达式都不为true执行代码
    }

    image-20200506122701636

  4. 嵌套的if结构

    if(布尔表达式 1){
        //如果布尔表达式 1的值为true执行代码
        if(布尔表达式 2){
            //如果布尔表达式 2的值为true执行代码
        }
    }

    image-20200506123202595

  5. switch多选择结构

    switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。

    switch语句中的变量类型可以是:

    1. byte、short、int或者char

    2. 从Java SE 7 开始switch支持字符串String 类型了

    3. 同时 case 标签必须为字符串常量字面量

      switch(expression){
          case value:
              //语句
              break;//可选
          case value:
              //语句
              break;//可选
          //可以有任意数量的case语句
          default://可选
              //语句
      }

  switch case 语句有如下规则:

  • switch 语句中的变量类型可以是: byte、short、int 或者 char。

    从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。

  • switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。

  • case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。

  • 当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。

  • 当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。

  • switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。

switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断。

SwitchDemo.java

import javax.sound.midi.Soundbank;

public class SwitchDemo {
    public static void main(String[] args) {
        char grade = 'A';
        switch (grade) {
            case 'A':
                System.out.println("优秀");
                break;
            case 'B':
                System.out.println("良好");
                break;
            case 'C':
                System.out.println("及格");
                break;
            case 'D':
                System.out.println("难顶");
                break;
            default:
                System.out.println("GG");
        }

        System.out.println("---------Java7之后支持字符串判断-----------");
        String evaluate  = "良好";
        switch (evaluate) {
            case "优秀":
                System.out.println('A');
                break;
            case "良好":
                System.out.println('B');
                break;
            case "及格":
                System.out.println('C');
                break;
            case "难顶":
                System.out.println('D');
                break;
            default:
                System.out.println("GG");
        }
    }
}

结果

优秀
---------Java7之后支持字符串判断-----------
B

*反编译

通过IDEA查看.class文件

image-20200506125440204

将该文件复制到源码文件目录下

image-20200506125554857

SwitchDemo.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.study.control;

public class SwitchDemo {
    public SwitchDemo() {
    }

    public static void main(String[] args) {
        char grade = 65;
        switch(grade) {
        case 65:
            System.out.println("优秀");
            break;
        case 66:
            System.out.println("良好");
            break;
        case 67:
            System.out.println("及格");
            break;
        case 68:
            System.out.println("难顶");
            break;
        default:
            System.out.println("GG");
        }

        System.out.println("---------Java7之后支持字符串判断-----------");
        String evaluate = "良好";
        byte var4 = -1;
        switch(evaluate.hashCode()) {
        case 658856:
            if (evaluate.equals("优秀")) {
                var4 = 0;
            }
            break;
        case 691634:
            if (evaluate.equals("及格")) {
                var4 = 2;
            }
            break;
        case 1058030:
            if (evaluate.equals("良好")) {
                var4 = 1;
            }
            break;
        case 1235320:
            if (evaluate.equals("难顶")) {
                var4 = 3;
            }
        }

        switch(var4) {
        case 0:
            System.out.println('A');
            break;
        case 1:
            System.out.println('B');
            break;
        case 2:
            System.out.println('C');
            break;
        case 3:
            System.out.println('D');
            break;
        default:
            System.out.println("GG");
        }

    }
}

可以看到class文件自动生成了一个无参构造器

public SwitchDemo() {}

进行String匹配时,先用hasCode进行比较,再通过第二轮常规的switch匹配。

反编译以后再深入。

4.循环结构

 1.while循环

//while是最基本的循环

while(布尔表达式){
    //循环的内容
}
//- 只要布尔表达式为true,循环就会一直执行下去。我们大所属情况是会让循环停下来,我们需要一个让表达式失效的方式来结束循环。

//- 少部分情况需要循环一直执行,如服务器的请求相应监听等。

//- 循环条件为true就会造成无限循环【死循环】,一般情况下需避免死循环

//- 思考:1+2+3+...+100=?

  public class WhileDemo{
      public static void main(String[] args){
        int i=0;
        int sum=0;
        while(i<=100){
            sum = sum + i;
            i++;
        }
        System.out.println("sum:"+sum);
      }
  }

 2.do...while循环

do{
        //代码语句
}while(布尔表达式);

while 和 do...while 的区别

    • 对于while语句而言,如果不满足条件,则不能进入循环。而do...while循环和while循环相似,不同的是,do...while循环至少会执行一次。

    • while是先判断后执行;do...while 是先执行后判断。do...while总是保证循环体会被至少执行一次!这是他们的主要区别。

注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。

如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。

最后的分号不要忘记!

do...while适用于先输入再判断的情况。

如输入一串数据,遇到‘-1’结束

//输入一串数字,遇到 -1 结束
Scanner sc = new Scanner(System.in);
int num = 0;
do {
    num = sc.nextInt();
    System.out.println(num);
} while (num != -1);

结果

1 2 3 4 -1 5 6 7
1
2
3
4
-1

 3.for循环

for(初始化;布尔表达式;更新){
    //代码语句
}

/*
最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。    
然后,检测布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。     
执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)再次检测布尔表达式。循环执行上面的过程。
*/

//死循环
for(; ; ){
}

for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。

关于 for 循环有以下几点说明:

  • 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
  • 然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
  • 执行一次循环后,更新循环控制变量。
  • 再次检测布尔表达式。循环执行上面的过程。

image-20200506134203881

 

 4.在java5中引入了一种主要用于数组的增强型for循环

主要用于数组或集合的增强型for循环

for(声明语句 : 表达式){
    //代码语句
}

  声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。

  表达式:表达式是要访问的数组名,或者是返回值为数组的方法。

public class EnhanceFor {
    public static void main(String[] args) {
        int[] numArray = {1, 2, 3, 4, 5, 6, 7, 8};
        // numArray.for  tab键
        for (int i : numArray) {
            System.out.println(i);
        }
    }
}

5.break&continue

  1. break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(breakl语句也在switch语句中使用)

  2. continue语句用在循环语句体中,用于终止某次循环过程,及跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。

  3. break在任何循环语句的主体部分,均可用break

1.break关键字

break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。

break 跳出最里层的循环,并且继续执行该循环下面的语句。

语法

break 的用法很简单,就是循环结构中的一条语句:

break;
public class BreakDemo {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            if (i > 50) {
                break;//i=51时就跳出循环,结束
            }
            System.out.println(i);
        }
    }
}

2.continue 关键字

continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。

在 for 循环中,continue 语句使程序立即跳转到更新语句。

在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。

语法

continue 就是循环体中一条简单的语句:

continue;
public class ContinueDemo {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            if (i % 10 == 0) {
                System.out.println();
                continue;
            }
            // 每次遇到整除10的数就换行,同时跳出循环继续下一轮,略过整10的打印
            System.out.print(i + "\t");
        }
    }
}

*GOTO语句(了解)

goto 关键字很早就在程序设计语言中出现。

事实上,goto 是汇编语言的程序控制结构的始祖:“若条件 A,则跳到这里;否则跳到那里”。

若阅读由几乎所有编译器生成的汇编代码,就会发现程序控制里包含了许多跳转。

然而,goto 是在源码的级别跳转的,所以招致了不好的声誉。

若程序总是从一个地方跳到另一个地方,还有什么办法能识别代码的流程呢?

随着 Edsger Dijkstra 著名的“Goto 有害”论的问世,goto 便从此失宠。

事实上,真正的问题并不在于使用 goto ,而在于 goto 的滥用。而且在一些少见的情况下,goto 是组织控制流程的最佳手段。

尽管 goto 仍是 Java 的一个保留字,但并未在语言中得到正式使用;Java 没有 goto 。

然而,在 break 和continue 这两个关键字的身上,我们仍然能看出一些 goto 的影子。

它并不属于一次跳转,而是中断循环语句的一种方法。之所以把它们纳入 goto 问题中一起讨论,是由于它们使用了相同的机制:标签。

“标签”是后面跟一个冒号的标识符,就象下面这样:

label1:

对 Java 来说,唯一用到标签的地方是在循环语句之前。进一步说,它实际需要紧靠在循环语句的前方——在
标签和循环之间置入任何语句都是不明智的。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另
一个循环或者一个开关。这是由于 break 和 continue 关键字通常只中断当前循环,但若随同标签使用,它们
就会中断到存在标签的地方。

下面是 for 循环的一个例子:

LabelDemo.java

package com.study.control;

/**
 * 求100-1000的质素
 */
public class LabelDemo {
    public static void main(String[] args) {
        label:for (int i = 100; i <= 1000; i++) {
            for (int j = 2; j <= i / 2; j++) {
                if (i % j == 0) {
                    continue label; // 如果不是质素,跑到外层循环继续下一个数的判断
                }
            }
            System.out.println(i);

        }
    }
}

6.练习

1.计算:1+2+3+...+100=?

publilc class WhileDemo03{
    public static void main(String[] args){
        int i=0;
        int sum=0;
        while(i<=100){
            sum= i + sum;           //这句和i++顺序问题
            i++;
        }
        System.out.println("sum="+sum);
    }
}

2.分别计算0~100之间的奇数和偶数的和

public class ForDemo02{
    public static void main(String[] args){
        int oddSum = 0;
        int evenSum = 0;
        
        for(int i=0; i<=100; i++){
            if(i%2!=0){
                //oddSum = i + oddSum;
                oddSum+=i;
            }else {
                //evenSum = i + evenSum;
                evenSum+=i;
            }
        }
        System.out.println("oddSum="+oddSum);
        System.out.print("evenSum="+evenSum);
    }
}

3.用while或for循环输出1~1000之间能被5整除的数,且每行输出10个

public class ForDemo03{
    public static void main(String[] args){
        for(int i=1; i<=1000; i++){
            if(i%5==0){
                System.out.print(i+" ");
            }
            if(i%(5*10)==0){
                System.out.print("\n");
            }
        }
    }
}
publlic class ForDemo03{
    public static void main(String[] args){
        int i=0;
        while(i<=1000){
            i++;
            if(i%5==0){
                System.out.print(i+" ");
            }
            if(i%(5*10)==0){
                System.out.print("\n");
            }
        }
    }
}

4.打印九九乘法表

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

5.打印三角形,5行

public class TestDemo{
    public static void main(String[] args){
        //1 3 5 7 9
        /*for(int i=1; i<=5; i++){
            for(int j=5; j>=i; j--){
                System.out.print(" ");
            }
            for(int j=1; j<=i; j++){
                System.out.print("*");
            }
            for(int j=1; j<i; j++){
                System.out.print("*");
            }
            System.out.println();
        }*/
        
        //1 2 3 4 5
        for (int i=1; i<=5; i++) {
            for (int j=5; j>=i; j--){
                System.out.print(" ");
            }
            for (int j=1; j<=i; j++){
                System.out.print("* ");
            }
            System.out.println();
        }
    }
}
 
posted @ 2023-01-03 20:37  uilufz  阅读(23)  评论(0编辑  收藏  举报