入门篇-其之十-流程控制之循环结构
本文中使用到的工具是Intellij IDEA和JDK 8,需要安裝兩款工具的請(qǐng)查看這兩篇教程:點(diǎn)我查看安裝JDK8/11/17教程、點(diǎn)我查看安裝Intellij IDEA教程。
假設(shè)輸出1~100之間的所有整數(shù),正常情況下我們需要寫(xiě)100行代碼才能對(duì)所有數(shù)字輸出。
System.out.println(1);
System.out.println(2);
System.out.println(3);
System.out.println(4);
// 其他數(shù)字輸出省略...
System.out.println(100);
雖然這種辦法能達(dá)到預(yù)期的效果,但是代碼量屬實(shí)有點(diǎn)大(?_?|||)
為了解決上述問(wèn)題,Java為我們提供了一個(gè)強(qiáng)大的控制結(jié)構(gòu)——循環(huán)結(jié)構(gòu)。
循環(huán)結(jié)構(gòu)是一種常用的程序控制結(jié)構(gòu),它允許程序在執(zhí)行的過(guò)程中反復(fù)執(zhí)行一段代碼,直到滿足特定條件為止。循環(huán)結(jié)構(gòu)可以大大簡(jiǎn)化重復(fù)性任務(wù)的編寫(xiě),提高代碼編寫(xiě)效率和可讀性。
在Java中,循環(huán)結(jié)構(gòu)主要由while循環(huán)、do-while循環(huán)、for循環(huán)組成。
一、while循環(huán)
while循環(huán)的語(yǔ)法格式如下:
while (條件表達(dá)式) {
執(zhí)行代碼...
}
執(zhí)行流程:如果條件表達(dá)式結(jié)果為true,此時(shí)進(jìn)入while循環(huán)內(nèi)部執(zhí)行代碼,直到while循環(huán)的條件表達(dá)式的結(jié)果為false為止。
while結(jié)構(gòu)如下圖所示:
案例1:使用
while循環(huán)解決1~100的輸出和1~100的和
我們先解決1~100的輸出,使用while需要循環(huán)100次,我們可以在while循環(huán)外定義一個(gè)變量number并賦值為1,由于是1~100是遞增輸出,條件表達(dá)式需要設(shè)定為number <= 100。
在循環(huán)體中,我們先將number的值進(jìn)行輸出。但是此時(shí)number的值并沒(méi)有增加,因此每次在輸出后需要對(duì)number進(jìn)行自增1的操作,即number++,部分代碼如下:
int number = 1;
while (number <= 100) {
System.out.println("number = " + number);
number++;
}
這樣就完成了1~100的輸出,但是我們還需要輸出它們相加的和,我們可以對(duì)上述的代碼進(jìn)行進(jìn)一步改造:
在while循環(huán)外部再定義一個(gè)變量sum,默認(rèn)值為0,用于存儲(chǔ)數(shù)字相加的和。
在循環(huán)體中,輸出語(yǔ)句后面實(shí)現(xiàn)兩數(shù)相加的操作:sum = sum + number;(簡(jiǎn)寫(xiě)為sum += number;)
- 第一次循環(huán):sum = 0 + 1 = 1
- 第二次循環(huán):sum = 1 + 2 = 3
- 第三次循環(huán):sum = 3 + 3 = 6
- 以此類(lèi)推......
在while循環(huán)內(nèi)部即可完成1~100的計(jì)算,最終sum的結(jié)果直接到while循環(huán)外部進(jìn)行輸出即可,完整代碼如下:
/**
* while循環(huán)--輸出1~100并求和
*
* @author iCode504
* @date 2023-11-30
*/
public class WhileLoop1 {
public static void main(String[] args) {
// 1. 定義一個(gè)變量number用于輸出數(shù)字
int number = 1;
// 2. 定義一個(gè)變量sum用于存儲(chǔ)1~100相加的和
int sum = 0;
// 3. 定義while循環(huán),條件表達(dá)式為number <= 100,需要保證number在while循環(huán)內(nèi)相加
while (number <= 100) {
sum += number;
System.out.println("number = " + number);
number++;
}
System.out.println("sum = " + sum);
}
}
運(yùn)行結(jié)果符合我們的預(yù)期:
案例2:斐波那契數(shù)列
已知每對(duì)兔子(一雌一雄)每個(gè)月能生殖一對(duì)小兔子,每對(duì)兔子前兩個(gè)月沒(méi)有生育能力,從第三個(gè)月每個(gè)月能生一對(duì)小兔子,假設(shè)兔子不存在死亡現(xiàn)象,那么從第一對(duì)剛出生兔子開(kāi)始,第n個(gè)月以后會(huì)有多少只兔子?
數(shù)學(xué)解法可以看這位老師的文章:點(diǎn)我查看,我只能說(shuō)一句:太強(qiáng)了,膜拜大佬!
根據(jù)上述題意可以得出:
- 第1個(gè)月兔子無(wú)生育能力,因此兔子只有1對(duì);
- 第2個(gè)月兔子無(wú)生育能力,此時(shí)兔子仍為1對(duì);
- 第3個(gè)月兔子生育了一對(duì)兔子,此時(shí)兔子為2對(duì);
- 第4個(gè)月最開(kāi)始的兔子又生育了一對(duì)兔子,此時(shí)兔子為3對(duì);
- 第5個(gè)月,最開(kāi)始的兔子又生育了一對(duì)兔子,第三個(gè)月的兔子也生育了一對(duì)兔子,此時(shí)兔子為5對(duì);
由此我們可以得出一個(gè)數(shù)列:
\[1,1,2,3,5…… \]可以看出,從第三個(gè)數(shù)起,每個(gè)數(shù)都是前1個(gè)數(shù)和前兩個(gè)數(shù)相加得到的和。由此,我們可以得到一個(gè)通用公式:
\[f(n)=f(n-1)+f(n-2), n\geqslant3 \]我們可以定義三個(gè)變量:number1、number2和totalNumber。其中number1和number2存儲(chǔ)前兩個(gè)月兔子的數(shù)量,totalNumber存儲(chǔ)前兩月兔子數(shù)量的和(也就是上述公式的實(shí)現(xiàn)),具體實(shí)現(xiàn)代碼如下:
import java.util.Scanner;
/**
* while循環(huán)解決斐波那契數(shù)列
*
* @author iCode504
* @date 2023-12-11
*/
public class FibonacciSequence {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請(qǐng)輸入月數(shù): ");
int monthNumber = scanner.nextInt();
// number1和number2代表前兩個(gè)月兔子的數(shù)量
int number1 = 1, number2 = 1;
// i的含義是從第三個(gè)月開(kāi)始繁殖。totalNumber用于計(jì)算前兩個(gè)月兔子的數(shù)量
// totalNumber初始化值為1的目的:如果用戶輸入的月數(shù)為1或2,此時(shí)兔子對(duì)數(shù)為1
int i = 3, totalNumber = 1;
// 限制條件:從第三個(gè)月開(kāi)始計(jì)算到第monthNumber個(gè)月
while (monthNumber > 2 && i <= monthNumber) {
// 計(jì)算前兩個(gè)月兔子總數(shù)
totalNumber = number1 + number2;
// number1存儲(chǔ)i-2個(gè)月兔子數(shù)量,用于下一輪循環(huán)的運(yùn)算
number1 = number2;
// number2存儲(chǔ)i-1個(gè)月兔子數(shù)量,用于下一輪循環(huán)的運(yùn)算
number2 = totalNumber;
i++;
}
System.out.println("第" + monthNumber + "個(gè)月兔子的數(shù)量是" + totalNumber + "對(duì)");
}
}
運(yùn)行結(jié)果:
當(dāng)然,循環(huán)只是解決斐波那契數(shù)列的一種方式,它還可以使用遞歸的方式解決。后續(xù)講到方法的時(shí)候還會(huì)講到這個(gè)問(wèn)題的遞歸解法。
二、do-while循環(huán)
do-while循環(huán)的語(yǔ)法格式如下:
do {
執(zhí)行代碼...
} while (條件表達(dá)式);
執(zhí)行流程:先執(zhí)行do內(nèi)部的代碼,內(nèi)部代碼執(zhí)行完畢以后,再對(duì)while中的條件表達(dá)式進(jìn)行判斷,如果條件表達(dá)式為true,再次進(jìn)入do內(nèi)部執(zhí)行代碼;如果條件表達(dá)式為false,此時(shí)就跳出do-while循環(huán)。
和while循環(huán)相比,do-while循環(huán)即使其條件表達(dá)式為false,也會(huì)執(zhí)行一次do內(nèi)部的代碼,因?yàn)樗鼤?huì)先執(zhí)行do內(nèi)部的代碼再進(jìn)行條件判斷。
do-while循環(huán)的執(zhí)行流程如下圖所示:
案例:計(jì)算一個(gè)數(shù)的所有因子之和(不包括1和自身)。輸入一個(gè)正整數(shù),輸出其所有因子之和。
例如:
- 正整數(shù)6的所有因子是:2,3。因此所有的因子的和是\(2 + 3 = 5\)
- 正整數(shù)20的所有因子是:2,4,5,10。所有因子的和是\(2+4+5+10=21\)
如果使用do-while循環(huán)來(lái)解決這個(gè)問(wèn)題,我們首先需要確定循環(huán)的范圍是什么?
其實(shí)題目中已經(jīng)告訴我們了一個(gè)關(guān)鍵點(diǎn):不包括1和自身。那么由此可以確定循環(huán)的范圍是:\([2, number)\)。
如何確定上述區(qū)間的數(shù)字是正整數(shù)number的因子呢?其實(shí)很簡(jiǎn)單,只需要判斷這個(gè)數(shù)字能否被number整除即可。
由于我們輸入的是正整數(shù),需要在執(zhí)行循環(huán)做一手判斷,如果不是正整數(shù),需要給出一個(gè)提示。
綜合上述內(nèi)容,代碼如下:
import java.util.Scanner;
/**
* do-while解決一個(gè)數(shù)所有因子的和
*
* @author iCode504
* @date 2023-12-15
*/
public class DoWhileDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請(qǐng)輸入一個(gè)正整數(shù): ");
int number = scanner.nextInt();
// 正整數(shù)判斷
if (number > 0) {
// 定義一個(gè)變量sum,用于存儲(chǔ)所有因子的和
int sum = 0;
// 由于正整數(shù)中因子不包含1和數(shù)字本身,因此循環(huán)需要從2開(kāi)始,計(jì)算到number - 1
int i = 2;
do {
// 判斷條件:i能被number整除的,那么i就是number的因子
if (number % i == 0) {
sum += i;
}
i++;
} while (i < number);
System.out.println("正整數(shù)" + number + "所有因子的和是: " + sum);
} else {
System.out.println("您輸入的不是正整數(shù)!!!");
}
}
}
運(yùn)行結(jié)果:
在開(kāi)發(fā)中,使用do-while循環(huán)的頻率要比while循環(huán)少很多。這主要是因?yàn)?code>do-while循環(huán)本身是先執(zhí)行循環(huán)體,然后再進(jìn)行條件判斷。即使條件判斷結(jié)果是false,do-while也執(zhí)行了一次循環(huán)體,這可能會(huì)導(dǎo)致不必要的計(jì)算和操作。
三、普通for循環(huán)
普通for循環(huán)的語(yǔ)法格式如下:
for (初始化表達(dá)式; 條件表達(dá)式; 迭代表達(dá)式) {
執(zhí)行代碼...
}
for循環(huán)的執(zhí)行流程如下圖所示:
這里解釋一下for內(nèi)部的三個(gè)表達(dá)式:
1. 初始化表達(dá)式,指的是初始化Java變量表達(dá)式,即數(shù)據(jù)類(lèi)型 變量名 = 變量值
例如:int i = 0;,或者把int i寫(xiě)到for循環(huán)之前,然后在for循環(huán)第一個(gè)位置將i = 0補(bǔ)齊即可。
當(dāng)然,初始化表達(dá)式也可以同時(shí)定義多個(gè)變量,例如:int i = 0, j = 0;
2. 條件表達(dá)式,如果計(jì)算結(jié)果為true,就進(jìn)入for循環(huán)內(nèi)部執(zhí)行代碼,如果條件表達(dá)式為false,就會(huì)跳出for循環(huán)。
一般而言,條件表達(dá)式和初始化表達(dá)式中定義的變量有關(guān)。例如:i < 100、i > -30等等。
3. 迭代表達(dá)式,絕大多數(shù)情況下針對(duì)初始化表達(dá)式定義的變量進(jìn)行增加或減少的操作。
以前面定義的初始化表達(dá)式int i = 0;為例,假設(shè)讓變量的值增加,我們可以使用如下方式:
i++; // 自增1
++i; // 自增1
i += number; // 讓i每次增加number
4. 一般在寫(xiě)for循環(huán)代碼時(shí),推薦將初始化表達(dá)式、條件表達(dá)式、迭代表達(dá)式都寫(xiě)上。
事實(shí)上,不寫(xiě)上述三個(gè)表達(dá)式也會(huì)執(zhí)行for循環(huán)代碼,但是如果在for循環(huán)內(nèi)部不寫(xiě)合理的條件判斷的話,很容易造成死循環(huán)的情況的發(fā)生。
那么for循環(huán)的執(zhí)行流程是怎么樣的呢?
- 在首次執(zhí)行
for循環(huán)的時(shí)候,先執(zhí)行初始化表達(dá)式,然后根據(jù)條件表達(dá)式結(jié)果進(jìn)行判斷,如果條件表達(dá)式為true,則進(jìn)入for循環(huán)內(nèi)部執(zhí)行代碼,如果條件表達(dá)式為false就跳出for循環(huán)。在執(zhí)行完for循環(huán)內(nèi)部代碼以后,會(huì)針對(duì)前面初始化表達(dá)式的變量進(jìn)行迭代操作(常見(jiàn)的是變量相加/相減操作)。 - 后續(xù)執(zhí)行
for循環(huán)的時(shí)候,就會(huì)根據(jù)for循環(huán)迭代表達(dá)式的計(jì)算結(jié)果到條件表達(dá)式中進(jìn)行比較,如果比較結(jié)果為true執(zhí)行for內(nèi)部代碼,反之就會(huì)跳出for循環(huán)。
這里舉兩個(gè)案例來(lái)說(shuō)明一下for循環(huán)的使用:
案例1:求1~100(包含100)所有的偶數(shù)和
解決本題的關(guān)鍵點(diǎn)是偶數(shù)的獲取,判斷一個(gè)數(shù)是否是偶數(shù),即數(shù)字對(duì)2求余等于0,再定義一個(gè)變量sum對(duì)所有符合條件的偶數(shù)累加即可。
/**
* for計(jì)算1~100所有偶數(shù)和
*
* @author iCode504
* @date 2023-12-15
*/
public class NumberPrint {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
// 偶數(shù)判斷條件:對(duì)2求余是否等于0
if (i % 2 == 0) {
// 偶數(shù)累加
sum += i;
}
}
System.out.println("1~100之間所有的和: " + sum);
}
}
運(yùn)行結(jié)果:
案例2:水仙花數(shù)是指一個(gè)3位數(shù),它的每個(gè)數(shù)位上的數(shù)字的3次冪之和等于這個(gè)數(shù)的本身。例如:
\[1^3 + 5^3+3^3 = 153 \]請(qǐng)使用
for循環(huán)列舉所有的水仙花數(shù)。
1. 確定范圍:水仙花是一個(gè)三位數(shù),三位數(shù)的數(shù)字范圍在\([100, 999]\)區(qū)間內(nèi)
2. 個(gè)位、十位、百位數(shù)的獲取:
\[百位數(shù) = 數(shù)字 / 100 \] \[十位數(shù) = 數(shù)字/10\%10 \] \[個(gè)位數(shù)=數(shù)字\%10 \]3. 符合水仙花數(shù)的條件:
\[數(shù)字 = 百位數(shù)^3+十位數(shù)^3+個(gè)位數(shù)^3 \]綜合以上的分析,使用for循環(huán)的代碼如下圖所示:
/**
* for循環(huán)列舉水仙花數(shù)
*
* @author iCode504
* @date 2023-12-15
*/
public class NarcissisticNumber {
public static void main(String[] args) {
// 定義三個(gè)變量a, b, c分別存儲(chǔ)百位數(shù)、十位數(shù)、個(gè)位數(shù)
int a, b, c;
// 循環(huán)范圍設(shè)定在[100, 999] --> [100, 1000)
for (int i = 100; i < 1000; i++) {
// 百位數(shù)、十位數(shù)、個(gè)位數(shù)的獲取
a = i / 100;
b = i / 10 % 10;
c = i % 10;
// 水仙花數(shù)的判斷條件
if (i == a * a * a + b * b * b + c * c * c) {
System.out.println(i);
}
}
}
}
運(yùn)行結(jié)果即\([100, 999]\)以內(nèi)的所有水仙花數(shù):
正如這節(jié)標(biāo)題:“普通for循環(huán)”,其實(shí)JDK 5還為我們?cè)O(shè)計(jì)了foreach循環(huán)(也稱(chēng)作增強(qiáng)for循環(huán)),這類(lèi)循環(huán)主要用于遍歷數(shù)組和列表等結(jié)構(gòu),使用foreach循環(huán)會(huì)簡(jiǎn)化代碼結(jié)構(gòu),在后續(xù)學(xué)習(xí)數(shù)組是我們會(huì)用到它,敬請(qǐng)期待°??'?'??°
四、死循環(huán)
死循環(huán),即條件表達(dá)式計(jì)算結(jié)果恒定為true而不斷執(zhí)行循環(huán)內(nèi)部的代碼。是一種無(wú)法自行終止的循環(huán)。在死循環(huán)中,程序會(huì)反復(fù)執(zhí)行同一段代碼,而且永遠(yuǎn)無(wú)法跳出這個(gè)循環(huán),除非手動(dòng)中斷程序或者遇到未處理的異常。
下面使用上述三種循環(huán)演示以下死循環(huán):
// while形式的死循環(huán)
while (true) {
System.out.println("我是死循環(huán)");
}
// do-while形式的死循環(huán)
do {
System.out.println("我是死循環(huán)");
} while (true);
// for形式的死循環(huán):不寫(xiě)初始化表達(dá)式和迭代表達(dá)式,條件表達(dá)式為true
for (; true; ) {
System.out.println("我是死循環(huán)");
}
運(yùn)行代碼的過(guò)程中,如果不進(jìn)行人為停止程序,它們就會(huì)不停輸出“我是死循環(huán)”:
死循環(huán)會(huì)導(dǎo)致程序無(wú)法正常執(zhí)行其他任務(wù),并且可能會(huì)占用大量資源。在編寫(xiě)循環(huán)結(jié)構(gòu)時(shí),務(wù)必要保證正確設(shè)置循環(huán)條件和提供適當(dāng)?shù)奶鰴C(jī)制,以避免死循環(huán)的發(fā)生。
五、Intellij IDEA關(guān)于循環(huán)的快捷鍵
1. 在Intellij IDEA中,如果快捷生成一個(gè)循環(huán)結(jié)構(gòu),可以輸入fori,然后會(huì)出現(xiàn)一個(gè)提示,按回車(chē)即可生成一個(gè)for循環(huán)結(jié)構(gòu)。這個(gè)for循環(huán)是從0開(kāi)始的:
2. 如果想生成一個(gè)從0~n的for循環(huán),可以使用n.for快捷生成。例如:如果我想生成0~100之間的循環(huán),可以直接按100.for,出現(xiàn)提示后直接按回車(chē)即可生成這個(gè)區(qū)間的for循環(huán):
3. 輸入n.forr可以生成一個(gè)從n到0依次遞減的for循環(huán),還是以100.forr為例,生成的效果如下圖所示:
4. 在編寫(xiě)代碼的過(guò)程中,如果條件表達(dá)式可以確定的話,可以直接使用條件表達(dá)式.while快捷生成一個(gè)while循環(huán),例如:
總結(jié)
以上是生活随笔為你收集整理的入门篇-其之十-流程控制之循环结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 人工智能安全(一)——初识人工智能
- 下一篇: 我的zsh简单设置