# 4.5 巢狀迴圈

## 多層迴圈

如同 if ... else 可以有多層結構，迴圈也可以有多層結構。多層迴圈是什麼樣子呢？我們以時鐘的時針、分針為例來說明。

分針和時針各是一個迴圈，分針 0~59，時針 0~11。

分針會由 0 分 轉到 59 分，接下來轉到 60 分時，時針會前進一格，分針則歸零重新開始新的一圈。

<div drawio-diagram="106"><img src="https://nlmoodle.ddns.net/uploads/images/drawio/2024-03/drawing-1-1711353232.png"></div>

```C++
for(int hour=0; hour<12; hour++)  // 外圈是時針
{
    for(int minute=0; minute<60; minute++)  // 內圈是分針
    {
        cout << hour << ":" << minute << endl;
    }
}
```

1. 一開始外圈的 hour 是 0
2. 進入迴圈的主體 (3~6行)
    1. 內圈的 minute 一開始是 0
    2. 進入迴圈的主體 (第5行)
        1. minute 一邊遞增，一邊把第 5 行執行 60 次
    3. 內圈執行完畢
3. hour 遞增 1
4. 再次進入迴圈的主體 (3~6行)
    1. 內圈的 minute 一開始是 0
    2. 進入迴圈的主體 (第5行)
        1. minute 一邊遞增，一邊把第 5 行執行 60 次
    3. 內圈執行完畢
5. ......

程式執行後的輸出如下：

<div class="coutput">
0:0
0:1
0:2
0:3
.
.
.
0:59
1:0
1:1
1:2
.
.
.
11:57
11:58
11:59
</div>

###### 練習：3x6 星號矩陣　
<div class="coutputw">
******
******
******
</div>
---

在這個練習中，我們要輸出如上的一個 3x6 星號矩陣

看到「重覆」的部分，我們很直覺的會想用迴圈來簡化程式碼。如果只會單層迴圈，可能這樣處理。
```C++
for(int i=0; i<3; i++)
{
    cout << "******" << endl;
}
```

迴圈內的 6 個星號，依然是「重覆」的狀態，所以它也可以使用迴圈來輸出。於是我們再加一個內層迴圈，讓它來輸出那 6 顆星號。

```C++
for(int i=0; i<3; i++)
{
    for(int j=0; j<6; j++)
    {
        cout << "*";
    }
    cout << endl;
}
```

請注意換行的 `cout << endl;` 放在什麼位置。想想看為什麼要放在這裡，而不是放在內層迴圈裡。

在這個例子裡，使用迴圈來處理重覆的工作，同時也讓程式變得有彈性。如果今天我們要輸入任意正整數 m, n 指定的 m x n 星號矩陣，只要將 3, 6 替換成變數 m, n 即可，其他程式碼都無需更動。

###### 練習：m x n 星號矩陣　
<div class="coutputw">
m = 2
n = 5
*****
*****
</div>

---

```C++
int m, n;

cout << "m=";
cin >> m;
cout << "n=";
cin >> n;

// 以下修改之前的雙層迴圈程式碼
for(int i=0; i<m; i++)
{
    for(int j=0; j<n; j++)
    {
        cout << "*";
    }
    cout << endl;
}
```

###### 練習：輸出 n 階數字方陣

**n=3**
<div class="coutputw">
111
222
333
</div>

**n=5**
<div class="coutputw">
11111
22222
33333
44444
55555
</div>

———

有時候 for 敘述首行的變數不是單純只當計數器，也會參與到迴圈內的運算或輸出。所以在設計起迄數值時，我們會花點心思考量。

```C++
int n;
cin >> n;

for(int i=1; i<=n; i++)  // 一共有 n 列資料要輸出。(為什麼 i 由 1~n，而非如之前用 0~n-1？)
{
    for(int j=0; j<n; j++)  // 每列要輸出 n 個數字
    {
        cout << i;      // 要輸出的數字為當下的 i 值
    }
    cout << endl;
}
```
###### 練習：n 階星號階梯

**n=3**
<div class="coutputw">
*
**
***
</div>

**n=5**
<div class="coutputw">
*
**
***
****
*****
</div>

———

在這個例子裡，外層迴圈的 i 除了幫外層計數，同時也是內層計數的終點值。

```C++
int n;
cin >> n;

for(int i=1; i<=n; i++)  // 一共有 n 列資料要輸出。(為什麼 i 由 1~n，而非如之前用 0~n-1？)
{
    for(int j=0; j<i; j++)  // 每列要輸出 i 個 *
    {
        cout << "*";
    }
    cout << endl;
}
```

下面這題給大家自己挑戰一下。

###### 練習：n 階數字階梯

**n=3**
<div class="coutputw">
1
22
333
</div>

**n=5**
<div class="coutputw">
1
22
333
4444
55555
</div>

———

### 可以有的組合

多層迴圈可以由 while, do...while, for 迴圈任意組成。例如：外圈是 while，內圈是 for......等等。

至於迴圈的結構也可以有多種變化，例如以下這幾種。

<div drawio-diagram="107"><img src="https://nlmoodle.ddns.net/uploads/images/drawio/2024-03/drawing-1-1711894063.png"></div>

<link rel=stylesheet type="text/css" href="https://nlmoodle.ddns.net/css/h.css?v=20240325001">