tags: tgirc早修book

巢狀迴圈

有些時候會需要在迴圈中再放一層迴圈,分成彼此有關聯以及彼此沒關聯兩種

內外層不相干

試著透過 for 畫出一個邊長為 n 的正方形吧

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

想輸出這樣的矩形,可以分成兩部分,輸出 n 個 * 的寬,再輸出 n 排,又可以說是分成一個會重複輸出 n 個 * 的迴圈跟一個會反覆輸出 n 排有 n 個 * 的迴圈

一個個步驟來看,先做出一層輸出寬的迴圈

#include <iostream> using namespace std; int main(){ int n; cin>>n; int i; for(int i=0;i<n;i++){ cout<<'*'; } return 0; }

現在做好了寬,接著重複輸出 n 排寬

#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; }

最後放入換行,因為換行要等寬都輸出完,所以只能放在外層的迴圈,當然也可以放在內層中看看最後輸出會變怎樣

#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; }

迴圈沒有必要一定要塞在一層內,像這樣的多層迴圈反而能更好閱讀以及更輕易的抓出錯誤

內外層相干

知道了該如何做出三角形,接著試著輸出邊長為 n 的直角三角形吧

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

透過觀察,我們可以知道三角形在第一層時輸出一個 * 第二層兩個,以此類推,這次我們先建好一個高,長為 n

#include <iostream> using namespace std; int main(){ int n; cin>>n; for(int i=0;i<n;i++){ } return 0; }

和輸出矩形的步驟一樣,放入內層的迴圈與換行

#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

#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 開始就搞定了

#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 的倒直角三角形

#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 的等腰三角形

#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; }

更複雜的巢狀迴圈

輸出一個邊長為 n 的平行四邊形

透過這張圖,我們可以分析出,它是由一個倒直角三角形加上一個正方形所組成的

運用輸出正方形的程式碼(在練習時請自己重新打一個,不要用複製貼上的方式,否則無法增加熟練度)

#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; }

和倒直角三角形的程式碼

#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 的平行四邊形,由於會先輸出倒直角三角形,把輸出的指令放在上方

#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; }

接著放入正方形的指令

#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,因此要修改一下倒三角形的條件式

#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 的倒直角三角形了