流程控制:嵌套循環、break與continue
尚硅谷JavaSE筆記-05

嵌套循環

就是for中有for,有時候需要多花點時間理解

  • 內層循環整個遍歷完,外層循環才執行一次
  • 假設外層循環要執行m次,內層循環要執行n次。整個跑完內層循環一共執行了m*n次

練習題-印菱形

Scanner scan = new Scanner(System.in);
System.out.println("輸入想印的菱形邊長n=...");
int n = scan.nextInt();
// 上半部分(含中間最長邊)
for (int i = 1; i <= n; i++) {
    for (int j = 0; j < n - i; j++) {
        System.out.print(" ");
    }
    for (int k = 0; k < i; k++) {
        System.out.print("* ");
    }
    System.out.println();
}
// 下半部分(從最長-1開始)
for (int i = 1; i <= n; i++) {
    for (int j = 0; j < i; j++) {
        System.out.print(" ");
    }
    for (int k = 0; k < n - i; k++) {
        System.out.print("* ");
    }
    System.out.println();
}

練習題-乘法表

for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= 9; j++) {
        System.out.print(i + "*" + j + "=" + i * j + "\t");
    }
    System.out.println();
}
// 只想要半邊則第二行j<=9改成j<=i

練習題-找完全數

完全數(Perfect number),又稱完美數或完備數,是一些特殊的自然數:它所有的真因子(即除了自身以外的因數)的和,恰好等於它本身。例如6,它有因數1、2、3、6,除去它本身6外,其餘3個數相加,{1}+{2}+{3}=6

for (int i = 1; i <= 1000; i++) {
    int sum = 0;
    for (int j = 1; j < i; j++) {
        if (i % j == 0) {
            sum += j;
        }
    }
    if (sum == i) {
        System.out.println(i + "為完全數");
    }
}

練習題-找質數

  1. 直觀版

    boolean flag = true; // 若把這行放在第一個循環中,則會聲明99次,占資源
    for (int i = 2; i <= 10000; i++) {
        for (int j = 2; j < i; j++) {
            if (i % j == 0) { // i被某數(2~自己-1)除盡
                flag = false; // 不是質數
            }
        }
        if (flag) {
            System.out.println(i + "是質數");
        }
        flag = true; // 重置flag
    }
    
  2. 小優化版

    boolean flag = true; // 若把這行放在第一個循環中,則會聲明99次,占資源
    for (int i = 2; i <= 10000; i ++) {
        for (int j = 2; j < Math.sqrt(i); j++) { // 優化1.開平方
            if (i % j == 0) { // i被某數(2~自己-1)除盡
                flag = false; // 不是質數
                break; // 優化2.找到一個因數就停
            }
        }
        if (flag) {
            System.out.println(i + "是質數");
        }
        flag = true; // 重置flag
    }
    
  3. label簡潔版

    label:
    for (int i = 2; i <= 10000; i++) {
        for (int j = 2; j < Math.sqrt(i); j++) { // 優化1.開平方
            if (i % j == 0) { // i被某數(2~自己-1)除盡
                continue label; // 找到任何因數就跳出(這裡要連跳出兩層,所以用label)
            }
        }
        System.out.println(i + "是質數");
    }
    

補充-計算運行耗時

學到單元測試之前先用耗時當作運行效率的參考

long start = System.currentTimeMillis();
// ...待測程式碼
long end = System.currentTimeMillis();
System.out.println("耗時為" + (end - start) + "毫秒");

break與continue

  • break跳出循環體,舉例:

    for (int i = 1; i <= 10; i++) {
        if (i % 5 == 0) {
            break;
        }
        System.out.print(i);
    }
    // 結果為1234
    
  • continue跳過該次循環體語句,舉例:

    for (int i = 1; i <= 10; i++) {
        if (i % 5 == 0) {
            continue;
        }
        System.out.print(i);
    }
    // 結果為12346789
    
  • 共通點:breakcontinue之下都不能再聲明執行語句,否則報錯

  • breakcontinue都只會跳過一層(就近原則)

  • 可以在breakcontinue後面接label使用達成跳轉,強烈不推薦

實作練習-家庭收支系統

import java.util.Objects;
import java.util.Scanner;

public class FamilyAccount {
    public static void main(String[] args) {
        int money = 10000;
        String detail = "收支\t變動\t餘額\t說明\n初始\t金額\t" + money + "\t系統給你的";
        Scanner scan = new Scanner(System.in);
        boolean flag = true;
        while (flag) {
            System.out.println("===家庭收支系統===");
            System.out.println("===1.查看明細===");
            System.out.println("===2.登記收入===");
            System.out.println("===3.登記支出===");
            System.out.println("===4.退    出===");
            System.out.println("請輸入<1-4>...");
            String input = scan.next(); // 獲取使用者輸入
            switch (input) {
                case "1":
                    System.out.println("===1.查看明細===");
                    System.out.println(detail);
                    System.out.println("明細結束!");
                    break;
                case "2":
                    System.out.println("===2.登記收入===");
                    System.out.println("輸入金額...");
                    String moneyInStr = scan.next();
                    int moneyIn = Integer.parseInt(moneyInStr);
                    money += moneyIn;
                    System.out.println("輸入說明...");
                    String infoIn = scan.next();
                    detail += "\n收入\t" + moneyInStr + "\t\t" + money + "\t" + infoIn;
                    System.out.println("登記成功!");
                    break;
                case "3":
                    System.out.println("===3.登記支出===");
                    System.out.println("輸入金額...");
                    String moneyOutStr = scan.next();
                    int moneyOut = Integer.parseInt(moneyOutStr);
                    money -= moneyOut;
                    System.out.println("輸入說明...");
                    String infoOut = scan.next();
                    detail += "\n支出\t" + moneyOutStr + "\t\t" + money + "\t" + infoOut;
                    System.out.println("登記成功!");
                    break;
                case "4":
                    System.out.println("確認退出?<Y/N>不分大小寫...");
                    String confirmExit = scan.next(); // 獲取使用者輸入
                    if (Objects.equals(confirmExit, "y") || Objects.equals(confirmExit, "Y")) {
                        flag = false;
                        System.out.println("歡迎下次使用!");
                        break;
                    } else if (Objects.equals(confirmExit, "n") || Objects.equals(confirmExit, "N")) {
                        System.out.println("繼續使用");
                        break;
                    }
                default:
                    System.out.println("輸入有誤,請重新輸入");
            }
        }
    }
}

知識點

  • scan.next()收到空白內容(\t、\n、" “)它當作啥事都沒發生,比如我想接收"Y”,輸入" Y"竟然也符合

  • 比對string使用Objects.equals(目標string物件, "內容")

  • stringint使用int int_val = Integer.parseInt(str);

  • 關於中英數字混合使用\t對不齊的原因與解法

    \t是補全(8-前面字元的位元數%8)的距離,
    也就是說前面有1個字元那麼在1個字元後輸出一個\t,則\t的長度為7個字元長度
    輸出結果對不齊是因為輸出的資料有些大於8個字元,有些小於8個字元
    解法:" \t"(前面加一個空格),或直接用\t\t來對齊
    

上次修改於 2021-11-20