入門篇-其之十-流程式控制制之迴圈結構

来源:https://www.cnblogs.com/iCode504/archive/2023/12/16/17904506.html
-Advertisement-
Play Games

本文介紹了流程式控制制中的迴圈結構,包括while迴圈、do-while迴圈和普通for迴圈。同時,還介紹了在Intellij IDEA中使用迴圈的快捷鍵,以提高編程效率。 ...


本文中使用到的工具是Intellij IDEA和JDK 8,需要安裝兩款工具的請查看這兩篇教程:點我查看安裝JDK8/11/17教程點我查看安裝Intellij IDEA教程

假設輸出1~100之間的所有整數,正常情況下我們需要寫100行代碼才能對所有數字輸出。

System.out.println(1);
System.out.println(2);
System.out.println(3);
System.out.println(4);
// 其他數字輸出省略...
System.out.println(100);

雖然這種辦法能達到預期的效果,但是代碼量屬實有點大(ᇂ_ᇂ|||)

為瞭解決上述問題,Java為我們提供了一個強大的控制結構——迴圈結構。

迴圈結構是一種常用的程式控制結構,它允許程式在執行的過程中反覆執行一段代碼,直到滿足特定條件為止。迴圈結構可以大大簡化重覆性任務的編寫,提高代碼編寫效率和可讀性。

在Java中,迴圈結構主要由while迴圈、do-while迴圈、for迴圈組成。

一、while迴圈

while迴圈的語法格式如下:

while (條件表達式) {
    執行代碼...
}

執行流程:如果條件表達式結果為true,此時進入while迴圈內部執行代碼,直到while迴圈的條件表達式的結果為false為止。

while結構如下圖所示:

案例1:使用while迴圈解決1~100的輸出和1~100的和

我們先解決1~100的輸出,使用while需要迴圈100次,我們可以在while迴圈外定義一個變數number並賦值為1,由於是1~100是遞增輸出,條件表達式需要設定為number <= 100

在迴圈體中,我們先將number的值進行輸出。但是此時number的值並沒有增加,因此每次在輸出後需要對number進行自增1的操作,即number++,部分代碼如下:

int number = 1;
while (number <= 100) {
    System.out.println("number = " + number);
    number++;
}

這樣就完成了1~100的輸出,但是我們還需要輸出它們相加的和,我們可以對上述的代碼進行進一步改造:

while迴圈外部再定義一個變數sum,預設值為0,用於存儲數字相加的和。

在迴圈體中,輸出語句後面實現兩數相加的操作:sum = sum + number;(簡寫為sum += number;

  • 第一次迴圈:sum = 0 + 1 = 1
  • 第二次迴圈:sum = 1 + 2 = 3
  • 第三次迴圈:sum = 3 + 3 = 6
  • 以此類推......

while迴圈內部即可完成1~100的計算,最終sum的結果直接到while迴圈外部進行輸出即可,完整代碼如下:

/**
 * while迴圈--輸出1~100並求和
 *
 * @author iCode504
 * @date 2023-11-30
 */
public class WhileLoop1 {
    public static void main(String[] args) {
        // 1. 定義一個變數number用於輸出數字
        int number = 1;
        // 2. 定義一個變數sum用於存儲1~100相加的和
        int sum = 0;
        // 3. 定義while迴圈,條件表達式為number <= 100,需要保證number在while迴圈內相加
        while (number <= 100) {
            sum += number;
            System.out.println("number = " + number);
            number++;
        }
        System.out.println("sum = " + sum);
    }
}

運行結果符合我們的預期:

案例2:斐波那契數列

已知每對兔子(一雌一雄)每個月能生殖一對小兔子,每對兔子前兩個月沒有生育能力,從第三個月每個月能生一對小兔子,假設兔子不存在死亡現象,那麼從第一對剛出生兔子開始,第n個月以後會有多少只兔子?

數學解法可以看這位老師的文章:點我查看,我只能說一句:太強了,膜拜大佬!

根據上述題意可以得出:

  • 第1個月兔子無生育能力,因此兔子只有1對;
  • 第2個月兔子無生育能力,此時兔子仍為1對;
  • 第3個月兔子生育了一對兔子,此時兔子為2對;
  • 第4個月最開始的兔子又生育了一對兔子,此時兔子為3對;
  • 第5個月,最開始的兔子又生育了一對兔子,第三個月的兔子也生育了一對兔子,此時兔子為5對;

由此我們可以得出一個數列:

\[1,1,2,3,5…… \]

可以看出,從第三個數起,每個數都是前1個數和前兩個數相加得到的和。由此,我們可以得到一個通用公式:

\[f(n)=f(n-1)+f(n-2), n\geqslant3 \]

我們可以定義三個變數:number1number2totalNumber。其中number1number2存儲前兩個月兔子的數量,totalNumber存儲前兩月兔子數量的和(也就是上述公式的實現),具體實現代碼如下:

import java.util.Scanner;

/**
 * while迴圈解決斐波那契數列
 *
 * @author iCode504
 * @date 2023-12-11
 */
public class FibonacciSequence {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("請輸入月數: ");
        int monthNumber = scanner.nextInt();

        // number1和number2代表前兩個月兔子的數量
        int number1 = 1, number2 = 1;
        // i的含義是從第三個月開始繁殖。totalNumber用於計算前兩個月兔子的數量
        // totalNumber初始化值為1的目的:如果用戶輸入的月數為1或2,此時兔子對數為1
        int i = 3, totalNumber = 1;
        // 限制條件:從第三個月開始計算到第monthNumber個月
        while (monthNumber > 2 && i <= monthNumber) {
            // 計算前兩個月兔子總數
            totalNumber = number1 + number2;
            // number1存儲i-2個月兔子數量,用於下一輪迴圈的運算
            number1 = number2;
            // number2存儲i-1個月兔子數量,用於下一輪迴圈的運算
            number2 = totalNumber;
            i++;
        }
        System.out.println("第" + monthNumber + "個月兔子的數量是" + totalNumber + "對");
    }
}

運行結果:

當然,迴圈只是解決斐波那契數列的一種方式,它還可以使用遞歸的方式解決。後續講到方法的時候還會講到這個問題的遞歸解法。

二、do-while迴圈

do-while迴圈的語法格式如下:

do {
    執行代碼...
} while (條件表達式);

執行流程:先執行do內部的代碼,內部代碼執行完畢以後,再對while中的條件表達式進行判斷,如果條件表達式為true,再次進入do內部執行代碼;如果條件表達式為false,此時就跳出do-while迴圈。

while迴圈相比,do-while迴圈即使其條件表達式為false,也會執行一次do內部的代碼,因為它會先執行do內部的代碼再進行條件判斷。

do-while迴圈的執行流程如下圖所示:

案例:計算一個數的所有因數之和(不包括1和自身)。輸入一個正整數,輸出其所有因數之和。

例如:

  • 正整數6的所有因數是:2,3。因此所有的因數的和是\(2 + 3 = 5\)
  • 正整數20的所有因數是:2,4,5,10。所有因數的和是\(2+4+5+10=21\)

如果使用do-while迴圈來解決這個問題,我們首先需要確定迴圈的範圍是什麼?

其實題目中已經告訴我們了一個關鍵點:不包括1和自身。那麼由此可以確定迴圈的範圍是:\([2, number)\)

如何確定上述區間的數字是正整數number的因數呢?其實很簡單,只需要判斷這個數字能否被number整除即可。

由於我們輸入的是正整數,需要在執行迴圈做一手判斷,如果不是正整數,需要給出一個提示。

綜合上述內容,代碼如下:

import java.util.Scanner;

/**
 * do-while解決一個數所有因數的和
 *
 * @author iCode504
 * @date 2023-12-15
 */
public class DoWhileDemo1 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("請輸入一個正整數: ");
        int number = scanner.nextInt();
        // 正整數判斷
        if (number > 0) {
            // 定義一個變數sum,用於存儲所有因數的和
            int sum = 0;
            // 由於正整數中因數不包含1和數字本身,因此迴圈需要從2開始,計算到number - 1
            int i = 2;
            do {
                // 判斷條件:i能被number整除的,那麼i就是number的因數
                if (number % i == 0) {
                    sum += i;
                }
                i++;
            } while (i < number);
            System.out.println("正整數" + number + "所有因數的和是: " + sum);
        } else {
            System.out.println("您輸入的不是正整數!!!");
        }
    }
}

運行結果:

在開發中,使用do-while迴圈的頻率要比while迴圈少很多。這主要是因為do-while迴圈本身是先執行迴圈體,然後再進行條件判斷。即使條件判斷結果是falsedo-while也執行了一次迴圈體,這可能會導致不必要的計算和操作。

三、普通for迴圈

普通for迴圈的語法格式如下:

for (初始化表達式; 條件表達式; 迭代表達式) {
    執行代碼...
}

for迴圈的執行流程如下圖所示:

這裡解釋一下for內部的三個表達式:

1. 初始化表達式,指的是初始化Java變數表達式,即數據類型 變數名 = 變數值

例如:int i = 0;,或者把int i寫到for迴圈之前,然後在for迴圈第一個位置將i = 0補齊即可。

當然,初始化表達式也可以同時定義多個變數,例如:int i = 0, j = 0;

2. 條件表達式,如果計算結果為true,就進入for迴圈內部執行代碼,如果條件表達式為false,就會跳出for迴圈。

一般而言,條件表達式和初始化表達式中定義的變數有關。例如:i < 100i > -30等等。

3. 迭代表達式,絕大多數情況下針對初始化表達式定義的變數進行增加或減少的操作。

以前面定義的初始化表達式int i = 0;為例,假設讓變數的值增加,我們可以使用如下方式:

i++;	// 自增1
++i;	// 自增1
i += number;	// 讓i每次增加number

4. 一般在寫for迴圈代碼時,推薦將初始化表達式、條件表達式、迭代表達式都寫上。

事實上,不寫上述三個表達式也會執行for迴圈代碼,但是如果在for迴圈內部不寫合理的條件判斷的話,很容易造成死迴圈的情況的發生。

那麼for迴圈的執行流程是怎麼樣的呢?

  • 在首次執行for迴圈的時候,先執行初始化表達式,然後根據條件表達式結果進行判斷,如果條件表達式為true,則進入for迴圈內部執行代碼,如果條件表達式為false就跳出for迴圈。在執行完for迴圈內部代碼以後,會針對前面初始化表達式的變數進行迭代操作(常見的是變數相加/相減操作)。
  • 後續執行for迴圈的時候,就會根據for迴圈迭代表達式的計算結果到條件表達式中進行比較,如果比較結果為true執行for內部代碼,反之就會跳出for迴圈。

這裡舉兩個案例來說明一下for迴圈的使用:

案例1:求1~100(包含100)所有的偶數和

解決本題的關鍵點是偶數的獲取,判斷一個數是否是偶數,即數字對2求餘等於0,再定義一個變數sum對所有符合條件的偶數累加即可。

/**
 * for計算1~100所有偶數和
 *
 * @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++) {
            // 偶數判斷條件:對2求餘是否等於0
            if (i % 2 == 0) {
                // 偶數累加
                sum += i;
            }
        }
        System.out.println("1~100之間所有的和: " + sum);
    }
}

運行結果:

案例2:水仙花數是指一個3位數,它的每個數位上的數字的3次冪之和等於這個數的本身。例如:

\[1^3 + 5^3+3^3 = 153 \]

請使用for迴圈列舉所有的水仙花數。

1. 確定範圍:水仙花是一個三位數,三位數的數字範圍在\([100, 999]\)區間內

2. 個位、十位、百位數的獲取:

\[百位數 = 數字 / 100 \]

\[十位數 = 數字/10\%10 \]

\[個位數=數字\%10 \]

3. 符合水仙花數的條件:

\[數字 = 百位數^3+十位數^3+個位數^3 \]

綜合以上的分析,使用for迴圈的代碼如下圖所示:

/**
 * for迴圈列舉水仙花數
 *
 * @author iCode504
 * @date 2023-12-15
 */
public class NarcissisticNumber {
    public static void main(String[] args) {
        // 定義三個變數a, b, c分別存儲百位數、十位數、個位數
        int a, b, c;
        // 迴圈範圍設定在[100, 999] --> [100, 1000)
        for (int i = 100; i < 1000; i++) {
            // 百位數、十位數、個位數的獲取
            a = i / 100;
            b = i / 10 % 10;
            c = i % 10;
            // 水仙花數的判斷條件
            if (i == a * a * a + b * b * b + c * c * c) {
                System.out.println(i);
            }
        }
    }
}

運行結果即\([100, 999]\)以內的所有水仙花數:

正如這節標題:“普通for迴圈”,其實JDK 5還為我們設計了foreach迴圈(也稱作增強for迴圈),這類迴圈主要用於遍曆數組和列表等結構,使用foreach迴圈會簡化代碼結構,在後續學習數組是我們會用到它,敬請期待°꒰๑'ꀾ'๑꒱°

四、死迴圈

死迴圈,即條件表達式計算結果恆定為true而不斷執行迴圈內部的代碼。是一種無法自行終止的迴圈。在死迴圈中,程式會反覆執行同一段代碼,而且永遠無法跳出這個迴圈,除非手動中斷程式或者遇到未處理的異常。

下麵使用上述三種迴圈演示以下死迴圈:

// while形式的死迴圈
while (true) {
    System.out.println("我是死迴圈");
}
// do-while形式的死迴圈
do {
    System.out.println("我是死迴圈");
} while (true);
// for形式的死迴圈:不寫初始化表達式和迭代表達式,條件表達式為true
for (; true; ) {
    System.out.println("我是死迴圈");
}

運行代碼的過程中,如果不進行人為停止程式,它們就會不停輸出“我是死迴圈”:

死迴圈會導致程式無法正常執行其他任務,並且可能會占用大量資源。在編寫迴圈結構時,務必要保證正確設置迴圈條件和提供適當的跳出機制,以避免死迴圈的發生。

五、Intellij IDEA關於迴圈的快捷鍵

1. 在Intellij IDEA中,如果快捷生成一個迴圈結構,可以輸入fori,然後會出現一個提示,按回車即可生成一個for迴圈結構。這個for迴圈是從0開始的:

2. 如果想生成一個從0~n的for迴圈,可以使用n.for快捷生成。例如:如果我想生成0~100之間的迴圈,可以直接按100.for,出現提示後直接按回車即可生成這個區間的for迴圈:

3. 輸入n.forr可以生成一個從n到0依次遞減的for迴圈,還是以100.forr為例,生成的效果如下圖所示:

4. 在編寫代碼的過程中,如果條件表達式可以確定的話,可以直接使用條件表達式.while快捷生成一個while迴圈,例如:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近開始體驗FastGPT或Dify等開源知識庫問答系統,用他們試著開發調試一些小助手。這中間需要使用到PostgreSQL,就在自己伺服器上進行了安裝,特此記錄下。 環境說明:阿裡雲ECS,2核8G,X86架構,CentOS 7.9操作系統。 選擇版本 1.打開PostgreSQL官網下載頁面,選 ...
  • 大家好,我是 dom 哥。這是我關於 Chrome 擴展開發的系列文章,感興趣的可以 點個小星星。 在上篇和中篇中已經完成了對 manifest 文件中以下欄位的解釋: "manifest_version" "name" "version" "description" "icons" "conten ...
  • 單例模式(Singleton Pattern)是最簡單的設計模式之一。這種類型的設計模式屬於創建型模式,提供了一種創建對象的最佳方式。主要在想控制實例數目,節省系統資源的時候應用。 ...
  • 這個問題也可以是如何選專業、職業? 1 程式員的優勢 1.1 早期可以拿到相對不錯的薪資,確保前期發育穩定 發育這個事情,一步快則步步快。你快別人一步,領先的不止是一個身位,你發育的速度也更快。就像打游戲,你比別人先升級、先解鎖科技樹了,你就比別人發育都快很多。別人還在造農民呢,你已經出了步兵了。吃 ...
  • C 語言中的數據類型 C 中的變數必須是指定的數據類型,並且您必須在 printf() 函數中使用格式說明符來顯示它: // 創建變數 int myNum = 5; // 整數(沒有小數點) float myFloatNum = 5.99; // 浮點數 char myLetter = 'D'; / ...
  • Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹`tabWidget`選擇夾組件與`TreeWidget`樹形選擇組件,的常用方法及靈活運用。 ...
  • 二二、函數(五) 1、static和inline 1)靜態變數 利用static可以聲明一個靜態變數,static變數如果沒有指定初始化的值,那麼會初始化為0,無論有沒有指定初始值,都只會初始化一次,靜態變數的值不會因函數大括弧結束而消失。語法如下 //static語法 static 類型 變數名稱 ...
  • Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹`ToolBar`工具欄組件以及與之類似的`MenuBar`菜單欄組件的常用方法及靈活運用。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...