Java流程控制

287 阅读10分钟

用户交互Scanner

可以通过Scanner类来获取用户的输入

语法格式:

Scanner sc = new Scanner(System.in);
// 凡是属于IO流的类如果不关闭会一直占用资源。
sc.close(); //关闭

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

//创建一个扫描器对象,用于接收键盘数据
Scanner scanner = new Scanner(System.in);

System.out.println("使用next方式接收");
//判断用户有没有输入字符串
if(scanner.hasNext()){    //使用next方式接收
    String str = scanner.next();   //程序在这一步暂时中止,直到用户输入完毕点击回车
    System.out.println("输入的内容为:"+str);
    //键盘输入: hello word
    //输入的内容为:hello
    //使用hasNextLie()会接收一行 "hello word"
}
//凡是属于IO流的类如果不关闭会一直占用资源
scanner.close();

next()

  • 一定要读取到有效字符后才可以结束输入
  • 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
  • 输入有效字符后 才将其后面输入的空白作为结束符
  • next()不能得到带有空格的字符串

nextLine()

  • 以Enter为结束符,即nextLine()方法返回的是输入回车之前的所有字符
  • nextLine()方法可以获得空白

以对应接收数据类型的形式(nextInt,nextFloat)的方式接收

 public static void main(String[] args){

    Scanner scanner = new Scanner(System.in);
    int i = 0;
    float f = 0.0f;

    System.out.println("请输入整数:");  //判断
    if(scanner.hasNextInt()){
        i = scanner.nextInt();
        System.out.println("输入的整数为:" + i);
    } else{
        System.out.println("输入的不是整数");
    }

    System.out.println("请输入小数:");  //判断
    if(scanner.hasNextFloat()){
        f = scanner.nextFloat();
        System.out.println("输入的小数为:" + f);
    } else{
        System.out.println("输入的不是小数");
    }
    scanner.close();
    }
    
    
    控制台:
情况一:
    请输入整数:
    25.0   //键盘输入
    输入的不是整数
    请输入小数:
    输入的小数为:25.0
    
    第二次判断不会暂停等待输入的原因
    Java Scanner类的工作机制:
    由于第一次判断的过程中并没有成功获取一个整数输入,
    第二次判断依然可以继续尝试获取浮点数输入,会检查输入流中是否存在一个浮点数,而不会暂停等待。
    如果存在,则scanner.nextFloat()会读取该浮点数;
    否则,程序将执行 System.out.println("输入的不是小数"); 

情况二:
    请输入整数:
    25     //键盘输入
    输入的整数为:25
    请输入小数:
    25.0   //键盘输入
    输入的小数为:25.0

应用实例

输入多个数字求平均数和总数,并统计输入数的个数,要求输入一个数用回车键确认,输入非数字时结束

代码如下(示例):

public static void main(String[] arg){
        Scanner scanner = new Scanner(System.in);      //统计总个数
        int m = 0;      //和
        double sum = 0;      //判断并确认输入数的类型
        System.out.println("请输入数字:");
        while (scanner.hasNextDouble()){   //通过循环 确认输入数的类型 判断是否还有输入 并且对每一次输入进行求和与统计次数
            double n = scanner.nextDouble();
            m += 1;
            sum += n;
        }
        System.out.println("个数为:"+m);
        System.out.println("总数为:"+sum);
        System.out.println("平均数为:"+(sum/m));
        scanner.close();
    }
    
    控制台
    请输入数字:
    25
    15
    36
    14
    36
    *
    个数为:5
    总数为:126.0
    平均数为:25.2

结构

顺序结构

Java的基本结构就是顺序结构,除非特别指明,否则就按语句从上到下一条一条执行

选择结构

  • if 单选择结构
if(布尔表达式){  
   //如果布尔表达式为true将执行的语句  
}
  • if 双选择结构
if(布尔表达式){
   //如果布尔表达式为true将执行的语句
}else{
   //如果布尔表达式为false将执行的语句
}
  • if 多选择结构
    一旦其中一个 else if 语句检测为 true ,其它的else if 、else 语句都将跳过
if(布尔表达式 1){
   //如果布尔表达式 1为true将执行的语句
}else if(布尔表达式 2){
   //如果布尔表达式 2为true将执行的语句
}else if(布尔表达式 3){
   //如果布尔表达式 3为true将执行的语句
}else{
   //如果以上布尔表达式都为false将执行的语句
}
  • 嵌套的 if 结构
if(布尔表达式 1){
   //如果布尔表达式 1为true执行的语句
     if(布尔表达式 2){
   //如果布尔表达式 2为true执行的语句
      }
}
  • switch 多选择结构
    switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
switch(表达式)
{
case 常量1:语句1;
case 常量2:语句2;
…
case 常量n:语句n;
default:语句n+1;
break;
}

switch 语句可以替代多个 if 判断。

switch语句通过 将表达式的值常量值进行比对

  • 如果相等,则将当前case语句以及后面所有的case语句全部执行,或者遇到break跳出switch 结构
  • 如果不相等,则跳到下一个case语句

default语句的作用是当没有相匹配的case时,执行default,且default不会受到顺序的影响,default 语句也可以省略不用

  • switch表达式 中的变量类型可以是:byte、short、int 或者 char
  • 从Java SE7开始(JDK7),switch表达式 支持字符串String类型
  • 同时case标签必须为字符串常量或者字面量(字面量:即数据,是由字母、数字等构成的字符串或者数值)

循环结构

while循环

语义:计算表达式的值,当值为true时, 执行循环体代码块。

while(布尔表达式){
    //循环内容
}
  • while语句中的表达式一般是关系逻辑表达式,当表达式的值为假时不执行循环体,反之则循环体一直执行
  • 一定要记着在循环体中改变循环变量的值,否则会出现死循环(无休止的执行)
  • 循环内容中如果包括有一个以上的语句,则必须用 {} 括起来,组成复合语句

do...while循环

语义:先执行循环中的执行代码块,然后再判断while中表达式是否为真,如果为真则继续循环;如果为假则终止循环。即,先执行do{},不符合while()就退出。do-while循环至少要执行一次循环语句

do{
    //循环内容
}while(布尔表达式);

for循环

for (执行表达式1;判断表达式2; 执行表达式3) {
// ……循环体……
}

它的固定执行过程如下:

  1. 执行表达式1:一个或多个 赋值语句,对循环变量赋予初始值。
  2. 判断表达式2:一个 关系表达式, 在每次循环迭代之前检查,如果为 false,结束循环;
  3. 执行表达式3:循环变量的步进值,利用(i++)等对于循环变量进行操作的语句,定义控制循环变量每循环一次后按什么方式变化;
  4. for循环中执行代码块执行结束后继续执行第二步(判断表达式);第一步初始化只执行一次。
  5. 循环结束,程序继续向下执行。

使用for语句应该注意

  1. for循环中的“表达式1、2、3”均可不写为空,但两个分号 (;;) 不能缺省
    1. 省略“表达式1(循环变量赋初值)”,表示 不对循环变量赋初始值。
    2. 省略“表达式2(循环条件)”,不做其它处理,循环一直执行( 死循环
    3. 省略“表达式3( 循环变量增减量 )”,不做其他处理,循环一直执行(死循环)
int i = 0; // 我们已经声明了 i 并对它进行了赋值

//可以移除执行表达式1
for (; i < 3; i++) { // 不再需要 "begin" 语句段
  System.out.println(i); // 0, 1, 2
}
//也可以移除执行表达式3
for (; i < 3;) {
  System.out.println(i++);
}
//还可以删除所有内容
for (;;) {
  // 无限循环
}
  1. 表达式1可以是设置循环变量的初值的赋值表达式, 也可以是其他表达式
  2. 表达式1和表达式3可以是一个简单表达式也可以是多个表达式以逗号分割。
  3. 表达式2一般是 关系表达式逻辑表达式 ,但也可是数值表达式或字符表达式, 只要其值非零 ,就执行循环体。
  4. 各表达式中的变量一定要在for循环 之前定义
    1. 执行表达式1中的变量 i 可在for语句中定义let i = 0;,此时i是“内联”变量声明。这样的变量只在循环中有效。
    2. 变量 i也可在for循环前定义,这样可以对最后的i进行操作:
int i = 0;
for (i = 0; i < 3; i++) { // 使用现有的变量
System.out.println(i); // 0, 1, 2
}
System.out.println(i); //3,有效,因为是在循环之外声明的
//练习:输出九九乘法表
for(int i=1;i<=9;i++){
    for(int j=1;j<=i;j++){
        System.out.print(j+"*"+i+"="+i*j+"\t");
    }
    System.out.println();
}

增强for循环——for-each循环

在java5中引入了一种主要用于数组的增强型for循环,用于遍历数组集合

语法格式:

//集合或数组的数据类型 变量名:[集合名/数组名]
for(ElementType element: arrayName) 
{ 
	System.out.println(变量名);
};
int [] numbers = {10,20,30,40,50}; //定义一个数组
for (int x:numbers){
    System.out.println(x); //遍历数组的元素 10 20 30 40 50
}
//相当于
for(int i=0;i<5;i++){
    System.out.println(numbers[i]);
}

三种循环比较

while, do-while和for三种循环在具体的使用场合上是有区别的,如下:

  • 知道循环次数 的情况下更适合使用for循环;
  • 不知道循环次数 的情况下适合使用while或者do-while循环:
  • 如果 有可能一次都不循环 应考虑使用while循环
  • 如果 至少循环一次 应考虑使用do-while循环。

但是从本质上讲,while,do-while和for循环之间是可以相互转换的。

break & continue

break可用于任何循环的主体部分,强行退出当前循环

continue可用于循环语句中,中止某次循环过程,跳过剩余语句,直接进行下一次循环条件判断

标签

标签 是在循环之前带有冒号的标识符

labelName: for (...) {
  ...
}

break [labelName] 语句会中断当前循环,并跳出标签下面的循环,标签应放在 要跳出的循环语句 前,之间不应有其他语句([labelName]为标签名)

public void testBreakFor() {
    inner:
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                if(i == 1 && j == 1) break inner;
                System.out.println(i + ", " + j);
            }
        }
        System.out.println("结尾");
}

上述代码中, break inner 向上寻找名为 inner 的标签并跳出其后的 for(int i = 0; i < 3; i++) 循环

continue [labelName] 语句会跳转到达标签的位置,重新进入标签下面的循环;

//打印101-150之间所有的质数
int count = 0;
outer:for(int i=101;i<=150;i++){
    for (int j=2;j<i/2;j++){
        if(i%j==0)
            continue outer; //其实这个不建议使用标签实现
    }
    System.out.print(i+" ");
}

流程控制练习

//打印等腰空心三角形
/*  例如:输入为4时
          *
         * *
        *   *
       * * * *
*/
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); //n为三角形高
for(int i=1;i<=n;i++){
    for(int j=1;j<=2*n-1;j++){
        if(i!=n){ //若不为最后一行
            if(i+j==n+1)
                System.out.print("*"); //三角形左腰边
            else if(i+j==n+2*i-1)
                System.out.print("*"); //三角形右腰边
            else System.out.print(" ");
        }
        else if(j%2!=0){  //最后一行,底边
            System.out.print("*");
        }else {
            System.out.print(" ");
        }
    }
    System.out.println(); //换行
}

Debug

Debug可以把程序的每一个细节和每一次变化展现在我们面前