<style> html, body, .ui-content { background-color: #333; color: #ddd; } body > .ui-infobar { display: none; } .ui-view-area > .ui-infobar { display: block; } .markdown-body h1{ color: #9CCEF2; } .markdown-body h2, .markdown-body h3{ color: #B1D6CA; } .markdown-body h4, .markdown-body h5, .markdown-body h6 { color: #ddd; } .markdown-body h1, .markdown-body h2 { border-bottom-color: #ffffff69; } .markdown-body h1 .octicon-link, .markdown-body h2 .octicon-link, .markdown-body h3 .octicon-link, .markdown-body h4 .octicon-link, .markdown-body h5 .octicon-link, .markdown-body h6 .octicon-link { color: #fff; } .markdown-body img { background-color: transparent; } .ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a { color: white; border-left: 2px solid white; } .expand-toggle:hover, .expand-toggle:focus, .back-to-top:hover, .back-to-top:focus, .go-to-bottom:hover, .go-to-bottom:focus { color: white; } .ui-toc-dropdown { background-color: #333; } .ui-toc-label.btn { background-color: #191919; color: white; } .ui-toc-dropdown .nav>li>a:focus, .ui-toc-dropdown .nav>li>a:hover { color: white; border-left: 1px solid white; } .markdown-body blockquote { color: #bcbcbc; } .markdown-body table tr { background-color: #5f5f5f; } .markdown-body table tr:nth-child(2n) { background-color: #4f4f4f; } .markdown-body code, .markdown-body tt { color: #eee; background-color: rgba(230, 230, 230, 0.36); } a, .open-files-container li.selected a { color: #5EB7E0; } </style> ###### tags: `tgirc早修book` # 巢狀迴圈 有些時候會需要在迴圈中再放一層迴圈,分成彼此有關聯以及彼此沒關聯兩種 ## 內外層不相干 <font color="F5F6B6">**試著透過 for 畫出一個邊長為 n 的正方形吧**</font> ![](https://i.imgur.com/ejeJUeW.png) 想輸出這樣的矩形,可以分成兩部分,輸出 n 個 \* 的寬,再輸出 n 排,又可以說是分成一個會重複輸出 n 個 * 的迴圈跟一個會反覆輸出 n 排有 n 個 * 的迴圈 一個個步驟來看,先做出一層輸出寬的迴圈 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; int i; for(int i=0;i<n;i++){ cout<<'*'; } return 0; } ``` 現在做好了寬,接著重複輸出 n 排寬 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin >> n; int i,j; for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ cout<<"*"; } } return 0; } ``` 最後放入換行,因為換行要等寬都輸出完,所以只能放在外層的迴圈,當然也可以放在內層中看看最後輸出會變怎樣 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin >> n; int i,j; for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 迴圈沒有必要一定要塞在一層內,像這樣的多層迴圈反而能更好閱讀以及更輕易的抓出錯誤 ## 內外層相干 知道了該如何做出三角形,接著<font color="F5F6B6">**試著輸出邊長為 n 的直角三角形吧**</font> ![](https://i.imgur.com/pinTZzx.png) 透過觀察,我們可以知道三角形在第一層時輸出一個 * 第二層兩個,以此類推,這次我們先建好一個高,長為 n ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=0;i<n;i++){ } return 0; } ``` 和輸出矩形的步驟一樣,放入內層的迴圈與換行 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 從前面的觀察可以知道三角形在第一層時輸出一個 \*,第二層兩個,以此類推,因此把這個邏輯套到程式內,i 跟三角形每層輸出的 * 一樣,每次都加一,所以可以把內層的 n 替換成 i ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=0;i<n;i++){ for(int j=0;j<i;j++){ //n 換成 i cout<<"*"; } cout<<"\n"; } return 0; } ``` 但現在又有個問題, i 一開始是 0,如果這樣的話,內層的迴圈就達不到設定的條件,如果要解決這個問題,那就讓 i 直接變成從 1 開始就搞定了 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ //令 i == 1 for(int j=0;j<i;j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 只是當 i 是 1 時,使用 i < n 的話,會少掉一次,這時的條件要變成 i <= n,當然如果要改成 i < n+1 也可以 接下來試試該如何輸出倒過來且底和高長度是 n 的直角三角形,以及高是 n 的等腰三角形,輸出圖案如下圖所示: 高度長 n 的倒直角三角形 ![](https://i.imgur.com/uWtce8P.png) ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<=n-i;j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 高是 n 的等腰三角形 ![](https://i.imgur.com/lFrH3JJ.png) ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<i;j++){ cout<<"*"; } cout<<"\n"; } for(int i=1;i<=n;i++){ for(int j=0;j<n-i;j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` ## 更複雜的巢狀迴圈 <font color="F5F6B6">**輸出一個邊長為 n 的平行四邊形**</font> ![](https://i.imgur.com/wNVICOi.png) 透過這張圖,我們可以分析出,它是由一個倒直角三角形加上一個正方形所組成的 ![](https://i.imgur.com/rKLbElT.png) 運用輸出正方形的程式碼(在練習時請自己重新打一個,不要用複製貼上的方式,否則無法增加熟練度) ```cpp= #include <iostream> using namespace std; int main(){ int n; cin >> n; int i,j; for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 和倒直角三角形的程式碼 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<=n-i;j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 將它們結合起來即可得到一個邊長為 n 的平行四邊形,由於會先輸出倒直角三角形,把輸出的指令放在上方 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<=n-i;j++){ //輸出倒三角 cout<<" "; } cout<<"\n"; } return 0; } ``` 接著放入正方形的指令 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<=n-i;j++){ cout<<" "; } for(int j=0;j<=n-i;j++){ //輸出正方形 cout<<"*"; } cout<<"\n"; } return 0; } ``` 但很重要的一點是,倒三角形的高是 n-1,可是平行四邊形是 n,因此要修改一下倒三角形的條件式 ```cpp= #include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<n-i;j++){ //修改成 j < n-1 cout<<" "; } for(int j=0;j<n;j++){ cout<<"*"; } cout<<"\n"; } return 0; } ``` 將倒直角三角形中的 `j <= n-i` 的部分,修改成 `j < n-i`,這樣就能只輸出邊長為 n-1 的倒直角三角形了