---
# System prepended metadata

title: 迴圈loop
tags: [初階班]

---

---
tags: 初階班
---
迴圈的目的是**重複**進行運算
基本上所有程式都會用到迴圈，因此**非常重要!!!一定要熟練**
# for
## 語法
```cpp=
for(初始執行; 判斷式; 迴圈控制變數) {
    迴圈內容
}
```
## 流程
1.`初始執行`
2.`判斷式`判斷是否執行
3.執行`迴圈內容`
4.`迴圈控制變數`改變
5.重複`3, 4`直到`2.`判斷式不成立
![](https://hackmd.io/_uploads/Hyi0JbyKh.png =80%x)

:::info
可以想像成類似 一個工廠要製造100個玩具
一開始有0個玩具，工廠就會不斷執行"製造一個玩具"直到玩具數量 $\ge$ 100
套在`for`迴圈的語法就是
```cpp
for(玩具數量 = 0; 玩具數量 <= 100; 玩具數量++) {
    生產一個玩具;
}
```
:::
## 舉例
1.sigma連加
$ex:簡單的\displaystyle\sum\limits_{i=1}^{5}i\ (等同1+2+3+4+5)$
```cpp=
int sum = 0;
for(int i = 1; i <= 5; i++) {
    sum += i;
}
```
:::info
:::spoiler 執行過程
$sum=0,\ i=1$

$i\leq5所以執行迴圈$

$\Rightarrow sum=0+1=1,\ i$++$等於2$

$i\leq5所以繼續$

$\Rightarrow sum=1+2=3,\ i$++等於$3$

$i\leq5所以繼續$

$\Rightarrow sum=3+3=6,\ i$++等於$4$

$i\leq5所以繼續$

$\Rightarrow sum=6+4=10,\ i$++等於$5$

$i\leq5所以繼續$

$\Rightarrow sum=10+5=15,\ i$++等於$6$

$i=6>5所以結束\Rightarrow 答案sum=15$
:::
2.階乘
$ex:4! = 1\times 2\times 3\times 4$
```cpp=
int ans = 1;
for(int i = 1; i <= 4; i++) {
    ans *= i;
}
```
:::warning
:::spoiler 也可以這樣寫
括號內可以放各種東西(甚至不放)，只要記得用分號隔開就好
像舉例的sigma可以用下面的方法改寫
1.`初始執行`寫在外面
```cpp=
int i = 1, sum = 0;
for(; i <= 5; i++) {
    sum += i;
}
```
2.`判斷式`寫在迴圈內部
```cpp=
int sum = 0;
for(int i = 1;;i++) {
    if(i > 5) {
        break; //break跳出迴圈，可看下面介紹
    }
    sum += i;
}
```
3.`迴圈變數控制`寫在迴圈內部
```cpp=
int sum = 0;
for(int i = 1; i <= 5;) {
    sum += i;
    i++;
}
```
4.全部寫在括弧外
```cpp=
int sum = 0, i = 1;
for(;;) {
    if(i > 5) {
        break;
    }
    sum += i;
    i++;
}
```
另外若有多個想執行的指令，可用`,`隔開
$ex:$
```cpp=
int sum = 0, time = 0;
for(int i = 1; i<= 5; i++, time++) {
    sum += i;
}
//結果：sum = 15, time = 5
```
:::
:::info
:::spoiler 例題：[a038:我不說髒話](https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a038)

題目：給定n，輸出n行"I don't say swear words!"
```cpp=
#include <iostream>
using namespace std;
int main(){
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) { //0~n-1，也可以寫for(int i = 1; i <= n; i++)
        cout << "I don't say swear words!\n";
    }
}
```
:::
# while
## 語法
```cpp=
while(判斷式) {
    迴圈內容
}
```
## 流程
邏輯跟`for`一樣，但括號內只有`判斷式`
`判斷式`$\Rightarrow$`迴圈內容`$\Rightarrow$`判斷式`$\Rightarrow\cdots\Rightarrow$`判斷式不成立`$\Rightarrow$`結束`
## 舉例
一樣用sigma的例子
```cpp=
int i = 1, sum = 0;
while(i <= 5) {
    sum += i;
    i++;
}
```
:::info
:::spoiler 同一個例題，while版
```cpp=
#include <iostream>
using namespace std;
int main(){
    int n;
    cin >> n;
    while(n > 0) {
        cout << "I don't say swear words!\n";
        n--;
    }
    /**
    也可以寫成
    while(n--)
        cout << "I don't say swear words!\n";
    原理是直接將'n'當作判斷條件 等同於：判斷他是否等於0(可以看變數--bool)
    其實就是上面寫法的省略版而已
    **/
}
```
:::
# do while
先執行再判斷
```cpp=
do{
    //迴圈內容
}while(判斷式);
```
較少用 但還是可以學一下
# 無限迴圈
`for`版
```cpp=
for(;;) {
    //迴圈內容
}
```
`while`版
```cpp=
while(1) { //while(true)
    //迴圈內容
}
```
# 雙層迴圈
迴圈裡面再包迴圈
$ex:$輸出長4高3、由`*`組成的矩形
```cpp=
for(int i = 1; i <= 3; i++) {
    for(int j = 1; j <= 4; j++) {
        cout << "*";
    }
    cout << endl;
}
```
執行結果
```
****
****
****
```
$ex:$輸出靠左、高為3、由`*`組成的三角形
```cpp=
for(int i = 1; i <= 3; i++) {
    for(int j = 1; j <= i; j++) {
        cout << "*";
    }
    cout << endl;
}
```
執行結果
```
*
**
***
```
理解雙層之後，更多層的迴圈也都是一樣的
# 其他控制迴圈進行的方法
## continue
直接跳到**迴圈最底部**(等於略過迴圈剩下的內容)
$ex:$輸出1~10的奇數
```cpp=
for(int i = 1; i <= 10; i++){
    if(i % 2 == 0){
        continue;
    }
    cout << i << ' '; //輸出1 3 5 7 9
}
```
## break
跳出**一層迴圈**
$ex:$用無限迴圈但只輸出1~5
```cpp=
int i = 1;
while(1){
    if(i > 5){
        break;
    }
    cout << i << ' '; //輸出1 2 3 4 5
}
```
# 補充
## 變數存活範圍
如果是在迴圈內宣告的變數，那他的存活範圍就只有這個迴圈
所以：
```cpp=
for(int i = 0; i < 5; i++){
    int k = 3;
}
cout << i; //error: i was not declared in this scope
cout << k; //error: k was not declared in this scope
```
## 不用大括號
如果執行只有一行可以不用加那個大括號，甚至可以不用換行
不論if、for、while等都一樣
```cpp=
for(int i = 0; i < 3; i++)
    cout << i << ' ';
```
```cpp=
int n = 10;
for(int i = 1; i <= n; i++) {
    if(i % 2 == 0) cout << i << ' ';
}
```
## DDJ的測資形式
測資筆數與測資點無關，每個測資點都有不同的測資，會講你的程式整個重跑一遍
下面講各種測資常用的輸入方式
基本上有下面四種：
### 單筆測資
只有一筆，最簡單，直接輸入就好
```cpp=
cin >> n;
```
```cpp=
cin >> n >> m;
```
### T筆測資
題目會在第一行先輸入一數$T$代表有$T$筆測資
有兩種寫法，第一種就是用$for$迴圈跑$T$次
```cpp=
int T;
cin >> T;
for(int t = 1; t <= T; t++) {
    //解題
}
```
(因為$i$可能在解題過程中常用到所以這裡不用$i$，但變數名稱可自行選擇)
或
```cpp=
int T;
cin >> T;
for(; T > 0; t--) {
    //解題
}
```
第二種用$while$
```cpp=
int T;
cin >> T;
while(T--) {
    
}
```
這種也比較常用，因為好寫
而他可以執行$T$次的原因是：
1.我們知道判斷式看的是0/1
2.對於後置-\-，會先作判斷再減
接著就可以發現，這種寫法的意義和上面$for$的第二個一樣
### 多筆測資(EOF結束)
EOF指的是End Of File，就是檔案結束
這種情況可以這樣寫：
```cpp=
int n;
while(cin >> n) {
    //解題
}
```
原理是`cin`會返回一個bool值，在EOF時會是false，其他時候都是true，而有bool就能作判斷
### 多筆測資(以0結尾)
其實不一定是以0結尾，看題目敘述
寫法跟上一個差不多
```cpp=
int n;
while(cin >> n) {
    if(n == 0) {
        break;
    }
    //解題
}
```
或
```cpp=
int n;
while(cin >> n && n) {
    //解題
}
```

以上四種情況，除了單筆測資應該是沒問題之外，其他的可以試著在迴圈中輸出變數觀察他的變化以方便理解
:::success
:::spoiler while(T-\-)
下面程式碼
```cpp=
int T = 5;
while(T--) {
    cout << T << ' ';
}
```
會輸出什麼呢？
:::