--- GA: G-RZYLL0RZGV --- ###### tags: `大一程設` `東華大學` `東華大學資管系` `基本程式概念` `資管經驗分享` # 巢狀迴圈、陣列淺談 [toc] # 前言 前面介紹過do-while/while/for-loop,這邊就簡單的介紹巢狀迴圈可能用在什麼地方,以及跟陣列有什麼關係。 # 巢狀迴圈 最好理解的方式就是:迴圈裡面又包了一個迴圈 :point_down: ```cpp= for(初值; 條件; 步進){ for(初值; 條件; 步進){ } } ``` 那巢狀迴圈究竟可以做什麼?我又該怎麼用眼睛來看巢狀迴圈的運作呢? 先讓我向各位預告,各位接下來在使用巢狀迴圈時可能犯的錯誤,緊接著談什麼樣的例子可以使用巢狀迴圈來解決。 ### 常犯錯誤 <span style="color:red;">**非常重要!!!** </span> 除非你有其他需求,否則... 就新手而言 在寫巢狀迴圈的時候,<span style="color:red;">**切記初值的變數要設不一樣**</span>,否則你想做的和你實際做出來的會差非常的多:open_mouth: 兩者的差異示範 :point_down: 第一個程式碼初值變數設**不一樣**。 第二個程式碼的初值變數設**一樣**。 1. 變數設不相同 :heavy_check_mark: ```cpp= for(int i=0;i<3;i++){ //外層迴圈 cout<<"進到for1"<<endl; for(int j=0;j<3;j++){ //內層迴圈 cout<<"進到for2"<<endl; } cout<<"\n"; } ``` **輸出:** 可以看到這種做法內層的迴圈會執行9次。 當外層的迴圈,i=0時,馬上進到內層迴圈j=0,內層迴圈不斷執行且j++,直到j<3不成立後會跳出內層迴圈,此時,我們又重新回到外層迴圈,i++,i=1,繼續執行(再次進到內層迴圈)直到i<3不成立。 ``` 進到for1 進到for2 進到for2 進到for2 進到for1 進到for2 進到for2 進到for2 進到for1 進到for2 進到for2 進到for2 ``` 2. 變數相同 (有其他需求例外:wink:) 在這個情況裡,注意到第四行的內層for迴圈,初值的變數與外層的初值變數是相同的(皆是i),所以在執行的過程中,內層迴圈改動i值同樣會影響到外層迴圈。 ```cpp= for(int i=0;i<3;i++){ cout<<"進到for1"<<endl; for(i=0;i<3;i++){ cout<<"進到for2"<<endl; } cout<<"\n"; } ``` **輸出:** 從輸出來看,應該能明顯的看出兩種情況的差異。我們的外層迴圈只有電腦剛到外層時才執行一次,因為內層迴圈將i的值改為3,所以不論是在內層還是外層都因為條件i<3不成立而跳出迴圈。 ``` 進到for1 進到for2 進到for2 進到for2 ``` ### 巢狀迴圈實例 實例有很多很多。所以我就先介紹幾個就好 #### 九九乘法表 >我需要介紹嗎?:anger: > 2 X 11 = 23 此處使用巢狀迴圈,外層for用來記錄現在是1~9哪個表,內層迴圈的功能是讓當下表裡面的 「? x 1」 ~「? x 9」都跑完。 ```cpp= for(int i=1;i<=9;i++){ //外層 for(int j=1;j<=9;j++){ //內層 cout<<i<<" X "<<j<<" = "<<i*j<<"\t"; // \t 為跳一個tab的距離 } cout<<"\n"; //\n為換行 } ``` **輸出:** 從輸出來看 外層掌控 :point_down: 方向 內層掌控 :point_right: 方向 ``` 1 X 1 = 1 1 X 2 = 2 1 X 3 = 3 1 X 4 = 4 1 X 5 = 5 1 X 6 = 6 1 X 7 = 7 1 X 8 = 8 1 X 9 = 9 2 X 1 = 2 2 X 2 = 4 2 X 3 = 6 2 X 4 = 8 2 X 5 = 10 2 X 6 = 12 2 X 7 = 14 2 X 8 = 16 2 X 9 = 18 3 X 1 = 3 3 X 2 = 6 3 X 3 = 9 3 X 4 = 12 3 X 5 = 15 3 X 6 = 18 3 X 7 = 21 3 X 8 = 24 3 X 9 = 27 4 X 1 = 4 4 X 2 = 8 4 X 3 = 12 4 X 4 = 16 4 X 5 = 20 4 X 6 = 24 4 X 7 = 28 4 X 8 = 32 4 X 9 = 36 5 X 1 = 5 5 X 2 = 10 5 X 3 = 15 5 X 4 = 20 5 X 5 = 25 5 X 6 = 30 5 X 7 = 35 5 X 8 = 40 5 X 9 = 45 6 X 1 = 6 6 X 2 = 12 6 X 3 = 18 6 X 4 = 24 6 X 5 = 30 6 X 6 = 36 6 X 7 = 42 6 X 8 = 48 6 X 9 = 54 7 X 1 = 7 7 X 2 = 14 7 X 3 = 21 7 X 4 = 28 7 X 5 = 35 7 X 6 = 42 7 X 7 = 49 7 X 8 = 56 7 X 9 = 63 8 X 1 = 8 8 X 2 = 16 8 X 3 = 24 8 X 4 = 32 8 X 5 = 40 8 X 6 = 48 8 X 7 = 56 8 X 8 = 64 8 X 9 = 72 9 X 1 = 9 9 X 2 = 18 9 X 3 = 27 9 X 4 = 36 9 X 5 = 45 9 X 6 = 54 9 X 7 = 63 9 X 8 = 72 9 X 9 = 81 ``` #### 三角形、金字塔題目 巢狀迴圈最常見的例子還有三角形跟金字塔,網路上也是一堆資料可以拿來參考使用。待會我將介紹一個相當簡單的經典題目。 ```cpp= for(int i=1;i<=5;i++) { for(int j=1;j<=i;j=j+1) { cout << "*"; } cout << endl; } ``` 因為沒有空格的問題要解決,所以這個題目就更簡單了!我們觀察輸出得知,第一層需要一個 :star:,第二層需要兩個:star:......以此類推。 根據上面的的解答參考,我把兩個for分別做什麼事情抓出來 第一個for >i=1; i<=5 >總共有五層需要輸出 >i配合內層迴圈所以一開始值就給1 第二個for >j=1; j<=i >j<=i 用來寫第幾層就要輸出幾次:star: >以第二層為例,應該要輸出兩個:star: >當電腦進到內層迴圈時,此時的i=2; j的初值仍是1,因此j<=i會執行兩次  **輸出:** ``` * ** *** **** ***** ``` 不需要輸出空白的三角形是不是很好寫呢? 相信你會說「真的很好寫!」 然而凡事都是一步一步向前邁進,既然我們寫完三角形了,現在來試試看金字塔吧! #### 輸入二維以上陣列的值 輸入一維陣列的時候,我們只需要一個for迴圈就可以解決。但當出現二維或二維以上的陣列時,只要有關輸入值的部分,我們就一定要用到巢狀迴圈!其實不僅輸入值的部分,像是將陣列所有值都輸出、取值,也是會用到巢狀迴圈。 >只要想到二維以上的陣列,就要想起它們共同的老公。 >「巢狀迴圈」 [name=朱眼影] # 淺談陣列 **陣列的特性** - 相同data type - 連續空間 - 陣列的第一個索引值是0,不是1 ### 為什麼我們需要陣列? 試想一下,今天有一個任務是讓你寫一個可以用來輸入某班級的某科成績,而這個班上只有3個人。相信大家的反應都非常的直覺且肯定,沒錯!我們就宣告三個變數這個題目就差不多結束了! ``` cpp= int peo1,peo2,peo3; cin>>peo1>>peo2>>peo3; ``` **然而...** 如果今天這個班級有100個人呢? 你會想要宣告100個變數來解決這個題目嗎?如果你夠有氣魄,還真的宣告了100個變數,那我會更加深這個題目。 請你輸入這100個人的國、英、數、自、社五科的分數,你該怎麼做? 這時候我們的陣列就可以派上用場了! - 當我們需要輸入100人單一科的成績時; ```cpp= int score[100]; ``` - 當我們需要輸入100人五科的成績時; ```cpp= int score[100][5]; //可視為100個長度為5的int陣列 ``` **簡單的一行程式碼便可以取代一次宣告多個變數的命運** 當然,<span style="color:red;">**同一個陣列的資料型態必須是相同的**! </span>不能有人是字串,有些人是整數,還有些人是布林值。 ### 如何宣告陣列 1. 當你要宣告陣列時,首先要先告訴電腦這個陣列是什麼data type,這個做法就跟你宣告變數是一樣的。 2. 幫你的陣列取上一個響亮的大名 3. 給陣列長度 **綜合以上三點,可得到語法** > <span style="color:red;">data type</span> array_name[<span style="color:green;">長度</span>] 舉例來說 :point_down: ```cpp= String name[5]; //宣告一個名子為name長度為5的字串陣列 ``` #### 賦予陣列值 有兩種賦予值的方法,第一種是先宣告完陣列後再賦值,第二種是宣告時就給陣列值。 **1. 先宣告陣列,後面再輸入值** 如果要賦予陣列值可以使用for迴圈 - 輸入一維陣列的值 name[5] ``` cpp= for(int i=0;i<5;i++){ cin>>name[i]; } ``` - 2. 輸入二維陣列的值(使用巢狀迴圈) score[100][5] ```cpp= for(int i=0;i<100;i++){ for(int j=0;j<5;j++){ cin>>score[i][j]; } } ``` **2. 宣告的同時賦予值** - 完整給值(給初始值) ```cpp= int score[5]={100,50,99,48,78}; ``` 此時 ``` score[0]為100 score[1]為50 score[2]為99 score[3]為48 score[4]為78 ``` - 不完整給值 ```cpp= int score[5]={100,50}; ``` 此時 ``` score[0]為100 score[1]為50 score[2]~score[4]為0 ``` ### 如何取得陣列值 <span style="color:red;">**重要!!**</span> **陣列的第一個索引值是0不是1** 也就是說,當你要取得陣列的第一個值時,你必須將索引值打0才行,以下面這個已賦值的陣列為例。 ```cpp= int score[5]={100,50,99,48,78}; ``` 如果我們要取第一個人的成績,則要打score[0] 以此可推知,若要取第二個人的成績,則為score[1]