# Ch6 for迴圈 > 搭配[green judge解題系統](http://www.tcgs.tc.edu.tw:1218/) > Special thanks to [台中女中sagit老師](http://www.tcgs.tc.edu.tw/~sagit/index.htm) \<\(\_ \_\)\> ## > 上一章:[while迴圈](https://hackmd.io/s/Sk3nDNsiZ) > 下一章:[雜項:其他資料型態、函式庫、格式化輸出](https://hackmd.io/s/r1QbUam6b) > 回目錄:[國立科學園區實驗中學C++程式語言自學講義](https://hackmd.io/s/B18yT_i5Z) ## <font color='darkblue'>For迴圈的用途</font> 在上一單元 我們學會了while迴圈 再次複習一次while迴圈的使用時機 1.某段程式要一直**重複執行** 2.預先不知道要重複幾次,而是藉由**判斷某個條件**來決定該結束了沒 for迴圈則跟while迴圈非常相似 它的使用時機為 1.某段程式要一直**重複執行** 2.一開始就已知要重複幾次,所以只要**判斷執行幾次了**就知道該結束了沒 例如: 印出100個"Hello" 算出某個數字的某次方 算出某個數字的階乘...等等 ## <font color='darkblue'>For迴圈的寫法</font> 由於在使用for迴圈時需要計算「迴圈執行幾次了」 所以需要另外使用一個變數來作為「計數器」 通常我們習慣將這個計數器的名稱取作 i 或 j 或 k 而這個計數器主要有三件任務 1.一開始先設定一個起始值 2.設一個檢查條件,每執行一次迴圈就檢查它還符合條件嗎(還符合才能繼續跑迴圈) 3.每執行一次迴圈就將計數器變動一下,例如加一 舉例來說,想要一個迴圈總共執行10次(i從0跑到9)的話 1. i 的起始值是0 2. 檢查條件為 i<10 (或i<=9) 3. 每次迴圈都將i加一 而這三件任務就分別被寫在for迴圈的三個格子裡 像是 ```cpp= int i; //宣告一個計數器 for ( i=0 ; i<10 ; i=i+1 ) //i從0開始;檢查是否還<10;每次加1 { //要重複執行的程式 } ``` for迴圈的架構如下: 先寫一個for,並且在後面接上一個小括弧() 小括弧內用分號分成3格,分別寫上(計數器=初始值;檢查計數器是否符合條件;改變計數器的值) 接著一個大括號 裡面放入的就是要重複執行的程式 註:`i=i+1`可以簡化成`i++` `i=i-1`也可以簡化成`i--` 因為for迴圈實在是太常寫到`i=i+1`或`i=i-1`了 為了方便,以下的範例程式皆會將它寫成`i++`以及`i--` <font color='darkorange'>【例題】</font> >輸入一個n,輸出n個"Hello" >例如n為3時,輸出 >Hello >Hello >Hello 本題的範例程式如下 ```cpp= int n, i; cin>>n; for(i=0;i<n;i++) //歸零;檢查到n次了沒;每次+1 { cout<<"Hello"<<endl; } cout<<endl; //最後加個換行符號 ``` 這樣的程式其實等效於 ```cpp= int n, i; cin>>n; i=0; //歸零 while(i<n) //檢查到n次了沒 { cout<<"Hello"<<endl; i=i+1; //每次+1 } cout<<endl; ``` for迴圈和while迴圈完全是可以等效轉換的 如果你忘記其中一種怎麼寫,改寫另一種也是可以的 但因為各自有適合的用途 所以還是建議在適合的情況下使用適合的迴圈 > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a026: 一千遍我愛你 ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a026) ## <font color='darkblue'>將計數器的值印出來</font> 當然,計數器本身的值也可以拿來用 <font color='darkorange'>【例題】</font> >輸入一個n,輸出從1到n的數字 這題可以寫成 ```cpp= int n, i; cin>>n; for(i=1;i<=n;i++){ cout<<i<<endl; } ``` 計數器不只可以順著數,當然也可以倒著數 <font color='darkorange'>【例題】</font> >輸入一個n,輸出從n到1的數字 這題可以寫成 ```cpp= int n, i; cin>>n; for(i=n;i>=1;i--){ cout<<i<<" "; } ``` > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a027: 倒數計時 ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a027) > 注意:它是要印完一個數字空一格,不是換行喔 ## <font color='darkblue'>將計數器的值拿來加減乘除</font> 計數器的值除了可以被印出來 也可以拿來當成運算時的材料 例如每次都把答案加上或乘上目前計數器的值 注意:計數器的值可以拿來當成別的變數運算時的材料 但是最好不要在運算時改動到計數器的值 否則會造成邏輯混亂 <font color='darkorange'>【例題】</font> >輸入一個n,輸出1至n的和 我們已經知道和的公式是 $\frac{n(n+1)}{2}$ 那麼就來試試看用迴圈算平方和是不是和用公式算的一模一樣 既然要算"和" 可以用一個變數來代表目前的和是多少 每次都將目前的和去加上目前計數器平方的值 ```cpp= int n, i, answer; cin>>n; answer = 0; //和一開始為0 for(i=1;i<=n;i++) { answer = answer+i; //加上計數器的值 } cout<<answer<<endl; //可以檢查是不是跟用公式算的一樣 if(answer == n*(n+1)/2) cout<<"YA!"<<endl; ``` <font color='darkorange'>【例題】</font> >輸入一個n,輸出n的階乘 既然要算階乘 可以先用一個變數來當成目前的積 然後每次都將目前的積乘上目前計數器的值 ```cpp= int n, i, answer; cin>>n; answer = 1; //積一開始為1 (為什麼?) for(i=1;i<=n;i++){ answer = answer*i; } cout<<answer<<endl; ``` ## <font color='darkblue'>計數器從特定數字開始計</font> 在以上的例子中 我們所用到的計數器,要不就是先歸零,要不就是從1開始 但其實它不管想從幾開始計都是可以的 <font color='darkorange'>【例題】</font> >輸入n和m,輸出從n至m的所有整數(包含n與m) 這題可以讓計數器從n開始,到m結束 範例程式如下 ```cpp= int n,m,i; cin>>n; cin>>m; for(i=n;i<=m;i++) //i從n開始;檢查i超過m了沒;i每次都+1 { cout<<i<<endl; } ``` <font color='darkorange'>【例題】</font> > 輸入兩個數字a, b > 輸出$a*(a+1)*(a+2)*(a+3)*...*(b-2)*(b-1)*b$ 的值 ```cpp= int a, b, i, ans; cin >> a >> b; ans=1; for(i=a;i<=b;i++){ ans = ans*i; } cout << ans; ``` > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a028: P(N,R) ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a028) <font color='darkorange'>【例題】</font> >輸入n和m,輸出從n至m的所有整數,兩兩整數間請用\"\~\"來連接 >例如n為2,m為5時,即輸出2\~3\~4\~5 這個題目有一個小麻煩 就是每個數字前面都要加上一個飄號\~ 但唯獨第一個數字前面不能加 這邊提供其中一種解決方法:把第一個數字(n)獨立出來,而迴圈的計數器則從n+1開始 ```cpp= int n, m, i; cin>>n; cin>>m; cout<<n; //先單獨印出第一個數字n for(i=n+1;i<=m;i++) //計數器從n+1開始 { cout<<"~"<<i; //印出飄號跟i } ``` > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a029: 連續整數相加(一) ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a029) ## <font color='darkblue'>組合技:for與if搭配使用</font> 迴圈裡面還可以再做條件判斷 寫法就和一般的條件判斷相同 <font color='darkorange'>【例題】</font> >輸入n,輸出n所有的因數 要判斷一個數字i是否為n的因數,可以判斷n除以i的餘數是否為零,即`n%i==0` ```cpp= int n, i; cin>>n; for(i=1;i<=n;i++) { if(n%i==0) cout<<i<<endl; } ``` > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a044: 盈數、虧數和完全數 ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a044) 相同的程式也可以拿來判斷n是不是質數 可以再用一個變數來計算n有幾個因數 如果因數的數量為0,就可以確定n是質數 (1與n除外,因為一定有這兩個因數) 不過i的範圍要注意: 1.i要從2開始,因為1不用檢查 2.i超過根號n時就可以停了 <font color='red'>(為什麼?)</font> 不過根號n的寫法有點麻煩(下一章會教到) 因此你可以不要判斷 $i\le\sqrt n$ 而是改成判斷 $i*i\le n$ ```cpp= int n, i, cnt; cin>>n; cnt=0; for(i=2;i*i<=n;i++) { if(n%i==0) cnt++; } if(cnt>0) cout<<"Not Prime"<<endl; else cout<<"Prime"<<endl; ``` > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a045: 質數判斷 ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a045) ## <font color='darkblue'>組合技:迴圈裡面還有迴圈</font> <font color='darkorange'>【例題】</font> >輸入n和m,輸出n行的m個飄號 >例如n為3,m為5時,輸出 >\~~~~~ >\~~~~~ >\~~~~~ 我們已經知道印出一行m個飄號可以這樣寫 ```cpp= for(i=0;i<m;i++) { cout<<"~"; } cout<<endl; ``` 而現在需要將這樣的飄號印出n行來 也就是上面那一段程式要被執行n次才夠 因此可以把上面那一整段程式 再包進一個會被執行n次的迴圈裡 由於i已經被拿去當成剛才的迴圈的計數器了 為了避免衝突 我們要再宣告一個新的計數器:j 因此程式可以寫成 ```cpp= for(j=1;j<=n;j++) { for(i=1;i<=m;i++) { cout<<"~"; } cout<<endl; } ``` (不過通常i會放在外圈,j會放在內圈,通用習慣問題而已) 請記得,像這樣的「迴圈包迴圈」,並不是一個新的語法概念 就只是單純把一個迴圈寫在另一個迴圈裡而已 寫法規則都沒什麼差別 > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a046: 巧克力工廠 ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a046) <font color='darkorange'>【例題】</font> >輸入n,輸出高和寬為n的等腰直角三角形 >例如n為4時,輸出 >\~ >\~~ >\~~~ >\~~~~ 這題可以直接拿上一題的程式來用 唯一不一樣的地方是 內層迴圈的計數器,並非數到n,而是改成數到**外層計數器**的值 ```cpp= for(j=1;j<=n;j++) { for(i=1;i<=j;i++) //注意,這邊的檢查值改成i<=j囉 { cout<<"~"; } cout<<endl; } ``` > <font color="darkgreen"> 【學生練習題】</font> > - [ ] [Green Judge a047: 數字三角形 ](http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=a047) ## <font color='darkblue'>補充語法</font> ### break 在迴圈內遇到`break`時,不管怎樣,直接離開迴圈 <font color='darkorange'>【例題】</font> >輸入n,輸出大於等於n的第一個5的倍數 (這例子舉得不好,但為了淺顯易懂,還是用這個例子吧) 計數器從n開始數到n+5 (因為這之間一定有5的倍數) 一旦遇到5的倍數並輸出它之後 迴圈就可以直接結束,不用再繼續往下跑了 因此可以使用`break` ```cpp= for(i=n;i<=n+5;i++) { if(i%5==0){ cout << i <<endl; break; } } ``` 雖然i不一定有超過n+5 不過一旦它遇到break,還是會直接結束迴圈 ### continue 在迴圈內遇到`continue`時,不管怎樣,直接進入下一圈 <font color='darkorange'>【例題】</font> >輸入n,輸出1至n之間所有5的倍數 這題你可以使用if來檢查i是否為5的倍數,如果是,則輸出 但你也可以不使用if,而利用continue來控制流程 比方說 在印出i之前,先檢查i是不是5的倍數 如果不是,那就直接continue進入下一輪迴圈 ```cpp= for(i=1;i<=n;i++) { if(i%5!=0) continue; cout<<i<<endl; } ``` break和continue都不是絕對必要的語法 都可以用其他的寫法來代替 但是在適合的情況下若能善用break和continue 可以讓你寫程式更有效率、有邏輯 ## > 上一章:[while迴圈](https://hackmd.io/s/Sk3nDNsiZ) > 下一章:[雜項:其他資料型態、函式庫、格式化輸出](https://hackmd.io/s/r1QbUam6b) > 回目錄:[國立科學園區實驗中學C++程式語言自學講義](https://hackmd.io/s/B18yT_i5Z)