书接上文,说控制流程有三,顺序、分支和循环,顺序一撸到底,分支百里挑一,那循环是个什么东西,若想知晓,须看下文。
(3)循环结构
如果一个事情,我们想要重复
做好几次,那我们就需要用到循环。
假设说你的舍友是一个枯燥且无聊的人,没有女朋友,也没有钱。自从上了大学以后,每天的日子,就是在宿舍打游戏。突然一天你一时兴起,你决定帮他以一个新的面目面对生活,你要让他每天健身、学习、参加活动,坚持60天。
显然你有两种办法可以达成这一目的,其一:你可以每天告诉他说,“哎,Dawson,健身、学习、参加活动!”,如此六十天;其二:你也可以告诉他,“Dawson,往后60天,你每天要健身、学习、参加活动!”
显然第二种办法更省事儿,这就是循环的思路。首先有初始化操作(比如这里你要求Dawson苦干60天),给出一个循环条件(比如这里60天为止),只要符合这一条件,那就一直进行一个动作(比如这里的健身、学习、参加活动)。除此以外,你还需要一个控制条件(比如这里的天数)。整理一下,就是下面这种图中的内容。
这里每个什么部分什么部分的,就是个名字,一个代号。其本身没有意义,你也不必要求自己写个循环体要分清那里是哪个部分,最主要的目的是,解决你的问题,至于这些部分,你觉得用得到就写,用不到就不写,只要能达成你的目的就可以。
实现循环的方式有三种,while、do-while和for。我们依次学习。
一、while
while的格式最为简单。
格式:
初始化语句;
while(条件语句) {
循环体
控制语句
}
我们用while实现一下我们的例子
package com.daw.test1;
public class Test1 {
public static void main(String[] args) {
//初始化语句----结束日子订到60天后
int day = 60;
while(day > 0) { //条件语句----结束的日子还没到
//循环体
System.out.println("Dawson健身");
System.out.println("Dawson学习参加活动");
System.out.println("Dawson参加活动");
System.out.println("----一天结束----");
//控制语句----一天结束后,我们减少一天
day--;
}
}
}
当然啦,我们这是倒数日子,看什么时候结束的。这样就不太好,显得Dawson积极性不高,天天盼着啥时候结束。而且我们也不好确定他每天在干什么。那我们不如反过来再练一遍,我们让今天是第一天,练习六十天,并且每天显示这是第几天。
package com.daw.test1;
public class Test1 {
public static void main(String[] args) {
//初始化语句----今天是第一天
int day = 0; //在计算机中,我们多用0作为开始,而不是1
while(day < 60) { //条件语句----以0作为开始,此处不是写<=,而是<
//循环体
System.out.println("Dawson健身");
System.out.println("Dawson学习参加活动");
System.out.println("Dawson参加活动");
System.out.println("----" + (day+1) + "天结束----"); //此操作为:字符串的拼接,字符串与任何基本类型进行+操作时,都会把该类型转化为字符串
//控制语句----一天结束后,我们增加一天
day++;
}
}
}
二、do-while
do-while与while的最大区别在于:while如果一开始就不满足条件,那么循环体的内容就一次也不执行;但do-while就很仁慈,不管你条件如何,先执行一遍循环体,然后再判断你的条件是否满足。
格式:
do {
循环体
} while(条件语句);
这就有点像你去某场所玩,别管你有没有钱,先让你免费试玩一局。玩完以后,如果你有钱够,可以接着玩;钱不够,就不玩了。
这里我们用while和do-while对比一下。
package com.daw.test1;
public class Test1 {
public static void main(String[] args) {
//假如你身无分文
int money = 0;
//你去了while那儿玩
while(money >= 5) { //假设五块钱玩一次
System.out.println("整一次");
money -= 5;
}
System.out.println("离开while,此时还有" + money + "块钱");
//你去了do-while那儿玩
do {
System.out.println("整一次");
money -= 5;
} while (money >=5);
money += 5; //第一次免费
System.out.println("离开do-while,此时还有" + money + "块钱");
}
}
运行结果:
可见,我们没有钱的时候,去while那里,一次也玩不了;去了do-while那里,do-while就让我们玩了一次。
程序是为了满足我假设的设定而写的,不代表你也得这么写,总之,解决问题就可以。
三、for
for与while基本相同,相当于是结构更加规范化的while。while和for可以相互转换。
格式:
for(初始化语句; 条件语句; 控制语句) {
循环体
}
1)初始化语句----只会运行一次
2)条件语句
|---真:运行`循环体`,然后执行`控制语句`
|---假:循环结束
3)控制语句,执行完后执行`条件语句`
我们把我们写的while转成for:
package com.daw.test1;
public class Test1 {
public static void main(String[] args) {
for (int day = 0; day < 60; day++) {
System.out.println("Dawson健身");
System.out.println("Dawson学习参加活动");
System.out.println("Dawson参加活动");
System.out.println("----" + (day+1) + "天结束----");
}
}
}
四、死循环
初始化语句、条件语句、控制语句,这三部分的语句重要性并不在循环体之下,假如此三部分语句书写不当,就有可能导致循环次数出现错误,甚至导致循环根本无法结束,也就是死循环。
但死循环并一定是要避免的坏事,正确的使用死循环,也能让我们解决很多的问题。
死循环在三种循环中的实现如下:
//注意一次测试一个
//for
for(;;){
System.out.println("***********");
}
//while
while(true){
System.out.println("***********");
}
//do-while
do{
System.out.println("***********");
}while(true)
可见控制台不停打印星花。
那么死循环有什么用呢,比如我们设计一个让用户登陆的程序。我们肯定不能说让用户输错了密码,就得重新打开程序吧,那么我们可以设计一个死循环,只有写对了密码,才能进入程序中后面的操作,如果错了,就再次输入密码。
代码实现:
package com.daw.test1;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("******************");
System.out.println("-----登录系统----");
System.out.print("请输入密码:");
String pwd = null;
while(true){
//假设密码为123
pwd = sc.next();
if(pwd.equals("admin")){ //不能写成 pwd == "admin"
break; //结束循环
}else{
System.out.println("密码错误!");
System.out.print("请重新输入:");
}
}
System.out.println("登录成功!");
System.out.println("******************");
}
}
这里在验证密码的时候不可以,不可以用==。基础不好的同学可以先记住,比较字符串类型(或基础类型以外的其他类型)时要用.equals()来判断。下次我们讲数组时再深入讲解为什么。
五、嵌套循环
循环中包着循环,称之为嵌套循环。
比如我们想要打印一个m行n列的*,mn均让用户来输入,我们就可以使用嵌套循环来实现。
代码:
package com.daw.test1;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
//m行n列星花
Scanner sc = new Scanner(System.in);
System.out.print("请输入行数:");
int m = sc.nextInt();
System.out.print("请输入列数:");
int n = sc.nextInt();
//m行
for(int i = 0; i < m; i++){
//n列
for(int j = 0; j < n; j++){
System.out.print("*");
}
System.out.println();
}
}
}
加大难度,我们打印一个九九乘法表:
package com.daw.test1;
public class Test1 {
public static void main(String[] args){
//九九乘法表
//m行
for(int i = 1; i <= 9; i++){
//n列
for(int j = 1; j <= i; j++){
System.out.print(j + "x" + i + "=" + i*j + "\t");
// '\t'表示缩进,可用于对齐
}
System.out.println();
}
}
}
六、特殊流程控制
1)break
有两种用法:
- 在switch-case中,用于跳出整个switch结构
- 在循环中,用于跳出当前循环(当前是指,如果你在嵌套循环中使用break,它只会跳出它所在的那层循环)
2)continue
在循环中,用于结束此次循环,进行下一次循环
3)return
用于从方法返回(同时跳出整个方法)。(在后面学到方法的时候,再详细讲解)
学习了break和continue后,我们就可以做一些有点难度的东西了。
比如我们设计这样一个登陆的程序,要求:
1.输入密码正确,提示登录成功。
2.输入密码错误,提示密码错误。
3.输入密码错误达到三次,提示登录失败,并结束程序。
可以自己做一下,熟悉一些所学内容。
参考代码如下:
package com.daw.test1;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("******************");
System.out.println("登录系统");
System.out.print("请输入密码:");
String pwd = null;
int count = 0; //错误计数器:记录错误的次数
while(true){
//假设密码为123
pwd = sc.next();
if(pwd.equals("admin")){ //不能写成 pwd == "admin"
break; //结束循环
}else{
count++;
if(count == 3){
System.out.println("登录失败!");
return; //return语句直接结束整个程序
}else{
System.out.println("密码错误!");
System.out.println("你还有" + (3-count) + "次机会");
System.out.print("请重新输入:");
continue; //结束此次循环,进入下一层循环
}
}
}
System.out.println("登录成功!");
System.out.println("******************");
}
}
七、关于在循环中定义的变量
值得注意的是,在循环中声明的变量,只在一次循环中存在,当此次循环结束时,该变量也不复存在
比如:
int i = 0;
int i = 1;
或者:
int i = 0;
for(int i = 0; i < 5; i++){
System.out.println("*");
}
当你程序中出现这样两条语句时,就会报错,告诉你变量 i 重复。
但如果是这样:
for(int i = 0; i < 5; i++){
System.out.println("*");
}
int i = 0;
或者是:
for(int i = 0; i < 5; i++){
int num = 6;
System.out.println(num);
}
int num = 0;
System.out.println(num);
你的程序就变得没有错误了。
当你写成下面这样:
for(int i = 0; i < 5; i++){
int num = 6;
System.out.println(num);
}
System.out.println(num);
你会发现for循环外面的num不存在,这也就是说明,在循环内部(包括for的初始化语句)内定义的变量,只在这一次循环中存在;当到了下次循环中,它就没有了,你就又可以再次定义它了。这个地方有点点绕,可能以后学了方法的时候,和方法那里还容易搞混,可以多自己试试,慢慢去理解。