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