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

:::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 << ' ';
}
```
會輸出什麼呢?
:::