Semorphe

重複

一段程式跑很多次,而你只寫一次。 · ⏱ 約 25 分鐘

你會學到三件事

  1. while 怎麼讓一段程式重複
  2. 一個迴圈一定要有的三樣東西,少一樣就停不下來
  3. 怎麼從一串數字看出公式

開始之前

想印出 1 到 5,用現在會的東西只能這樣:

cout << 1 << endl;
cout << 2 << endl;
cout << 3 << endl;
cout << 4 << endl;
cout << 5 << endl;

那印到 100 呢?印到 n 呢——而 n 是使用者輸入的?

寫不出來。 這一課解決它。

一、while

int n = 1;
while (n <= 5) {
    cout << n << endl;
    n = n + 1;
}

讀法:「只要 n <= 5 還成立,就一直做大括號裡面的事。」

積木盤上這一顆寫著「當 … 持續執行」——那個「持續」就是它會回去再問一次。

它和 if 長得幾乎一樣,只差一個字——而行為差很多:

條件成立時 做完之後
if 做一次 往下走
while 做一次 回去再問一次條件

二、一個迴圈一定要有三樣東西

int n = 1;          // ① 起點   ——從哪裡開始
while (n <= 5) {    // ② 條件   ——什麼時候還要繼續
    cout << n << endl;
    n = n + 1;      // ③ 變動   ——每一圈讓它往終點靠近
}

三樣缺一不可,而漏掉的通常是第三樣。

三、少了「變動」會怎樣

int n = 1;
while (n <= 5) {
    cout << n << endl;
    // ← 忘了 n = n + 1;
}

n 永遠是 1,條件永遠成立,於是它永遠不會停

這叫無窮迴圈。畫面會一直印 1,直到你按停止。

🟢 畫面會幫你數圈數:跑完之後,迴圈那一塊旁邊會出現一個 ×5 ——它重複了 5 圈。⚠️ 你以為是 5 而看到 4,那就是差一錯誤 (少跑或多跑一圈),而它是迴圈最常見的那一種錯。

每次寫完一個 while,回頭看一眼:那個條件裡的東西, 有沒有在迴圈裡被改? 沒有的話它就停不下來。

⚠️ 而「變動」不一定是加一。它可以是 n = n * 2、可以是讀下一筆輸入—— 只要那件事會讓條件遲早變成不成立就行。

四、觀察前後的變化,把它寫成公式

很多題目給你的不是「從 1 印到 5」,而是一串數字,要你接下去:

2, 5, 10, 17, 26, ...

怎麼寫成迴圈?先做一件事:把前後兩項的變化寫下來

第幾項 i     1    2    3    4    5
這一項 n     2    5   10   17   26
前後的差        3    5    7    9

差不是固定的(3、5、7、9),所以「每一圈加一個固定的數」行不通。 但差本身很規律——它每次多 2。

這時候換另一個角度:不看前一項,直接看編號

i = 1  →  n = 2        1×1 + 1 = 2
i = 2  →  n = 5        2×2 + 1 = 5
i = 3  →  n = 10       3×3 + 1 = 10

公式是 n = i × i + 1。寫成程式就只有一行:

int i = 1;
while (i <= 5) {
    cout << i * i + 1 << endl;
    i = i + 1;
}

兩種角度都要會: 「這一項跟前一項的關係」——那是變動; 「這一項跟編號的關係」——那是公式

⚠️ 有些數列只有第一種寫得出來(例如「上一項乘 3 再加 1」), 而有些兩種都行。先看差,差不規律再去看編號。

🔴 而「用編號來寫」這件事,下一課會變成一個專門的迴圈寫法。

五、do ... while(補充,看過就好)

還有一種寫法,它先做一次再問

do {
    cout << n << endl;
    n = n + 1;
} while (n <= 5);

差別只有一個:do while 保證至少跑一次,即使條件一開始就不成立。

積木盤上它寫著「先執行 … 再看 … 決定要不要繼續重複」 ——那個「先執行」就是它與 while 的全部差別。

它用得比 while 少很多,而這一課不會考它。 知道有這個東西、之後在別人的程式裡看到不會嚇到就夠了。 ⚠️ 注意它的結尾有分號

完成的樣子

這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。

1#include <iostream>2using namespace std;3int main() {4    int n = 1;5    while (n <= 5) {6        cout << n << endl;7        n = n + 1;8    }9    return 0;10}
1變數n5變數n換行變數n變數n1+設成印出0回傳持續執行宣告int(整數)變數n=定義函式 回傳型別int(整數)main使用命名空間std引入函式庫iostream(輸入輸出)12345679

到編輯器照著做一次:跟著做

換你了

改成印出 1 到 5 的總和(答案是 15)。

提示:多一個變數 sum 從 0 開始,每一圈 sum = sum + n;。 ⚠️ sum 要宣告在迴圈外面——宣告在裡面的話它每一圈都重新開始。

再一個:找出公式

印出這串數字的前五項:

1, 3, 5, 7, 9

先把「差」寫下來,再決定你要用變動寫還是用編號寫。 🔴 兩種都寫一次,然後跟旁邊的人比一下——你們選的不一定一樣,而兩種都對。

到編輯器做這一題:練習:找出公式,印出前五項

做一個

規則只有兩條:偶數就除以 2,奇數就乘 3 加 1。一直做到變成 1 為止。 讀進一個數字,印出它走了幾步。⚠️ 裁判用的是 27

🔴 這個規則看起來很簡單,而**「是不是每一個數字最後都會到 1」至今沒有人證明出來**。 你可以試幾個數字,看誰找到走最久的那一個。

到編輯器做這一題:做一個:這個數字要走幾步才到 1

這一課你做了什麼

如果卡住了

你看到 多半是因為
一直印同一個數字停不下來 少了「變動」那一行
一次都沒印 條件一開始就不成立(例如 n 從 10 開始)
印到 6 才停 條件用了 <= 而你想要 <(或反過來)
總和每次都一樣 sum 宣告在迴圈裡面了
在編輯器打開這一課 →