• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(循环语句、while语句、for语句)

开发技术 开发技术 3周前 (09-07) 21次浏览

3.8.2循环语句

3.8.2.1while语句

       最近这些年买彩票只能去投注站买,早些年,笔者经常是在网上买。在网上买有个功能:追号。就是假如你想一直买同一组号码,直到中大奖为止。你可以设置一个条件,比如中了头奖就不继续买了,如果没有中头奖,下一期继续买同样的号码。对于这样的功能,在程序中可以采用while循环来实现:

《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(循环语句、while语句、for语句)

代码如下:

while(n<5000000) {  
    System.out.println("下一期继续买同一组号码");  
} 

但是事实上,我们先要买第一期,然后才能判断是否中头奖,循环才能继续:

 《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(循环语句、while语句、for语句)

代码如下:

do {  
    System.out.println("买一组号码");  
} while (n < 5000000);  

下面我们再用一个示例来解决我们儿子最近学奥数的一个数学问题,计算1+2+3+…+100;

int sum = 0;// 最终结果,初始为0  
int add = 1;// 加数,初始为1  
while (add <= 100) {  
    sum = sum + add;  
    add++;// 加完后,自增1  
}  
System.out.println(sum);//最终结果是5050  

通过上面实例我们知道,当while的条件为真,则执行循环语句。如果这个条件一直为真的话,程序就会进入一个死循环了。因此在实际程序编写的时候,一定要保证这个条件随着程序的运行,会在某一个时刻变为假,避免程序进入死循环。比如上面这个例子变量add会自增,所以一定大于100。

3.8.2.2for语句

       对于上面这个数学问题,我们可以看出来,它的循环次数是固定的,对于这种循环问题,Java还有一种更加简洁的语句来实现,就是for循环。代码可以写成这样:

int sum = 0;// 最终结果,初始为0  
for (int add = 1; add <= 100; add++) {  
    sum += add;  
}  
System.out.println(sum);// 最终结果是5050 

我们可以看到,代码的第2行,把加数add的初始化、循环条件和add的自增都放到一行了,显得更加简洁。它的通用结构如下:

for(表达式1 ; 表达式2 ; 表达式3)

  • 表达式1:一般用来初始化循环迭代计数器
  • 表达式2:必须是一个结果为boolean的表达式,一般用作循环条件
  • 表达式3:一般用来迭代循环计数器

       其实对于for循环中括号内,是分成3个部分,每个部分之间用分号(;)隔开。Java允许这3个部分放置任何表达式,并且都是可以省略不写的。示意图如下:

 《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(循环语句、while语句、for语句)

另外,对于在表达式1中声明的变量,它的作用域是整个for循环的循环体。对于在循环语句中定义的变量,作用域只能在循环体{}内。

       有的时候,在一个for循环中,会有多个计数器,例如前面追号买彩票的例子,可以设置追号10期,但是有的时候你的账户余额不足了,彩票站不会给你垫钱追号的,代码可以写成这样:

for (int balance = 10, count = 1; balance >= 2 && count <= 10; count++, balance -= 2) {  
    System.out.println("余额还剩" + balance + "元,购买第" + count + "期彩票");  
} 

balance:账户余额;count:追号期数

运行结果:

余额还剩10元,购买第1期彩票  
余额还剩8元,购买第2期彩票  
余额还剩6元,购买第3期彩票  
余额还剩4元,购买第4期彩票  
余额还剩2元,购买第5期彩票  

我们可以看到:

  • 表达式1可以同时定义多个同类型的变量(balance和count)
  • 表达式2循环条件是余额大于等于2(够一张彩票钱)并且追号期数小于等于10(我们设置的期数)
  • 表达式3可以同时对balance和count进行更新

虽然Java的语法规则对for循环的表达式1、表达式2、表达式3的限制非常少,但是笔者不建议编写晦涩难懂的语句,尽量保证代码的可读性。

3.8.2.3break

       在上面这个例子中,代码其实写的就有点晦涩,不易阅读。对于余额不足的情况,其实可以认为是中止循环的一个条件。我们可以用break来中止循环,代码可以改写:

int balance = 10;  
for (int count = 1; count <= 10; count++) {  
    System.out.println("余额还剩" + balance + "元,购买第" + count + "期彩票");  
    balance -= 2;  
    // 当余额不足2元的时候,中止循环  
    if (balance < 2) {  
        break;  
    }  
}  

while中同样可以使用break,我们将上面代码改写成while版本:

int balance = 10;  
int count = 1;  
while (count <= 10) {  
    System.out.println("余额还剩" + balance + "元,购买第" + count + "期彩票");  
    count++;  
    balance -= 2;  
    // 当余额不足2元的时候,中止循环  
    if (balance < 2) {  
        break;  
    }  
}  

这2段代码的运行结果都是:

余额还剩10元,购买第1期彩票  
余额还剩8元,购买第2期彩票  
余额还剩6元,购买第3期彩票  
余额还剩4元,购买第4期彩票  
余额还剩2元,购买第5期彩票  

break关键字,只能中止当前循环,当有多个循环嵌套使用的时候,有时候想要直接中止最外层循环,对于这种需求,在C++中是使用goto关键字来实现的。我们在学习关键字的时候,发现Java将goto作为保留字了,但是却没有使用它,而是用了另外一种方法来实现。叫做带标签的break语句。

       首先我们得想一个多层嵌套的例子,正当我冥思苦想的时候,突然发我儿子床头的一张乘法口诀表:

 《Java从入门到失业》第三章:基础语法及基本程序结构(3.8):流程控制(循环语句、while语句、for语句)

假如我们用程序打印这张表,可以用到2层嵌套的循环语句。第一层循环打印每一行的所有算式,然后我们把打印每一行的功能也用一个循环来实现即第二层循环。代码如下:

// row是行号,一共需要打印9行  
for (int row = 1; row <= 9; row++) {  
    // column是列号,对于第row行,一共需要打印row列  
    for (int column = 1; column <= row; column++) {  
        System.out.print(column + "×" + row + "=" + column * row + " ");  
    }  
    System.out.println();// 打印完一行,需要换行  
} 

运行结果如下:

1×1=1   
1×2=2 2×2=4   
1×3=3 2×3=6 3×3=9   
1×4=4 2×4=8 3×4=12 4×4=16   
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25   
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36   
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49   
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64   
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81

Perfect!完美的打印出来了。假如我们想在打印到第8行第5列的时候,不想打印了,代码改成下面这样:

// row是行号,一共需要打印9行  
for (int row = 1; row <= 9; row++) {  
    // column是列号,对于第row行,一共需要打印row列  
    for (int column = 1; column <= row; column++) {  
        System.out.print(column + "×" + row + "=" + column * row + " ");  
        if (row == 8 && column == 5) {  
            break;  
        }  
    }  
  System.out.println();// 打印完一行,需要换行
}

但是这样的结果如下:

1×1=1   
1×2=2 2×2=4   
1×3=3 2×3=6 3×3=9   
1×4=4 2×4=8 3×4=12 4×4=16   
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25   
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36   
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49   
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40   
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81   

虽然第8行第5列之后的没有打印,但是第9行又打印出来了。我们再改成带标签的break。

 1 print_row: // 这是一个标签  
 2 for (int row = 1; row <= 9; row++) {  
 3     // column是列号,对于第row行,一共需要打印row列  
 4     for (int column = 1; column <= row; column++) {  
 5         System.out.print(column + "×" + row + "=" + column * row + " ");  
 6         if (row == 8 && column == 5) {  
 7             break print_row;// 中止标签print_row  
 8         }  
 9     }  
10     System.out.println();// 打印完一行,需要换行  
11 }  
 

运行结果:

1×1=1   
1×2=2 2×2=4   
1×3=3 2×3=6 3×3=9   
1×4=4 2×4=8 3×4=12 4×4=16   
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25   
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36   
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49   
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40   

这一次结果正确。我们在第1行添加一个标签“print_row”,然后在第7行中止该标签。这样做相当于跳转到标签“print_row”标记的代码块的末尾即第11行。需要注意的是,标签后面需要紧跟一个冒号(:)。

3.8.2.4c++ontinue

       在上面打印乘法口诀表的例子,假如我们不想打印第4行和第4列,想想有啥办法吗?我们可以想到,当打印到第4行的时候,直接换一行去打印第5行。当打印到第4列的时候,也跳过,然后去打印第5列。对于这种需求,我们可以用到continue语句。continue的作用就是跳过当前循环体中剩余的部分,回到当前循环的首部。代码如下:

 1 for (int row = 1; row <= 9; row++) {  
 2     /*第4行,打印换行,然后继续打印下一行*/  
 3     if (row == 4) {  
 4         System.out.println();  
 5         continue;  
 6     }  
 7     for (int column = 1; column <= row; column++) {  
 8         /*第4列,打6个空格,然后继续打印下一列*/  
 9         if (column == 4) {  
10             System.out.print("      ");  
11             continue;  
12         }  
13         System.out.print(column + "×" + row + "=" + column * row + " ");  
14     }  
15     System.out.println();  
16 }  

运行结果如下:

1×1=1   
1×2=2 2×2=4   
1×3=3 2×3=6 3×3=9   
  
1×5=5 2×5=10 3×5=15       5×5=25   
1×6=6 2×6=12 3×6=18       5×6=30 6×6=36   
1×7=7 2×7=14 3×7=21       5×7=35 6×7=42 7×7=49   
1×8=8 2×8=16 3×8=24       5×8=40 6×8=48 7×8=56 8×8=64   
1×9=9 2×9=18 3×9=27       5×9=45 6×9=54 7×9=63 8×9=72 9×9=81   

我们看到,结果第4行和第4列都空出来了。需要注意的是,continue只是跳过当前循环体的剩余部分,如果是for循环,表达式3部分还是会执行的。

       continue语句也可以带标签,作用是跳到与标签匹配的循环首部(如果是for循环,则是表达式3)。我们看代码和结果:

print_row:  
for (int row = 1; row <= 9; row++) {  
    for (int column = 1; column <= row; column++) {  
        /*第4列,则直接打印下一行*/  
        if (column == 4) {  
            System.out.println();  
            continue print_row;  
        }  
        System.out.print(column + "×" + row + "=" + column * row + " ");  
    }  
    System.out.println();  
}  
 

结果:

1×1=1   
1×2=2 2×2=4   
1×3=3 2×3=6 3×3=9   
1×4=4 2×4=8 3×4=12   
1×5=5 2×5=10 3×5=15   
1×6=6 2×6=12 3×6=18   
1×7=7 2×7=14 3×7=21   
1×8=8 2×8=16 3×8=24   
1×9=9 2×9=18 3×9=27 

喜欢 (0)