tags: 大一程設 東華大學 東華大學資管系 基本程式概念 資管經驗分享

巢狀迴圈、陣列淺談

前言

前面介紹過do-while/while/for-loop,這邊就簡單的介紹巢狀迴圈可能用在什麼地方,以及跟陣列有什麼關係。

巢狀迴圈

最好理解的方式就是:迴圈裡面又包了一個迴圈 :point_down:

for(初值; 條件; 步進){ for(初值; 條件; 步進){ } }

那巢狀迴圈究竟可以做什麼?我又該怎麼用眼睛來看巢狀迴圈的運作呢?
先讓我向各位預告,各位接下來在使用巢狀迴圈時可能犯的錯誤,緊接著談什麼樣的例子可以使用巢狀迴圈來解決。

常犯錯誤

非常重要!!!

除非你有其他需求,否則 就新手而言

在寫巢狀迴圈的時候,切記初值的變數要設不一樣,否則你想做的和你實際做出來的會差非常的多:open_mouth:

兩者的差異示範 :point_down:
第一個程式碼初值變數設不一樣
第二個程式碼的初值變數設一樣

  1. 變數設不相同 :heavy_check_mark:
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


  1. 變數相同 (有其他需求例外:wink:)

在這個情況裡,注意到第四行的內層for迴圈,初值的變數與外層的初值變數是相同的(皆是i),所以在執行的過程中,內層迴圈改動i值同樣會影響到外層迴圈。

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」都跑完。

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

三角形、金字塔題目

巢狀迴圈最常見的例子還有三角形跟金字塔,網路上也是一堆資料可以拿來參考使用。待會我將介紹一個相當簡單的經典題目。

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迴圈就可以解決。但當出現二維或二維以上的陣列時,只要有關輸入值的部分,我們就一定要用到巢狀迴圈!其實不僅輸入值的部分,像是將陣列所有值都輸出、取值,也是會用到巢狀迴圈。

只要想到二維以上的陣列,就要想起它們共同的老公。
「巢狀迴圈」 朱眼影

淺談陣列

陣列的特性

  • 相同data type
  • 連續空間
  • 陣列的第一個索引值是0,不是1

為什麼我們需要陣列?

試想一下,今天有一個任務是讓你寫一個可以用來輸入某班級的某科成績,而這個班上只有3個人。相信大家的反應都非常的直覺且肯定,沒錯!我們就宣告三個變數這個題目就差不多結束了!

int peo1,peo2,peo3; cin>>peo1>>peo2>>peo3;

然而
如果今天這個班級有100個人呢? 你會想要宣告100個變數來解決這個題目嗎?如果你夠有氣魄,還真的宣告了100個變數,那我會更加深這個題目。
請你輸入這100個人的國、英、數、自、社五科的分數,你該怎麼做?

這時候我們的陣列就可以派上用場了!

  • 當我們需要輸入100人單一科的成績時;
int score[100];
  • 當我們需要輸入100人五科的成績時;
int score[100][5]; //可視為100個長度為5的int陣列

簡單的一行程式碼便可以取代一次宣告多個變數的命運
當然,同一個陣列的資料型態必須是相同的! 不能有人是字串,有些人是整數,還有些人是布林值。

如何宣告陣列

  1. 當你要宣告陣列時,首先要先告訴電腦這個陣列是什麼data type,這個做法就跟你宣告變數是一樣的。
  2. 幫你的陣列取上一個響亮的大名
  3. 給陣列長度

綜合以上三點,可得到語法

data type array_name[長度]

舉例來說 :point_down:

String name[5]; //宣告一個名子為name長度為5的字串陣列

賦予陣列值

有兩種賦予值的方法,第一種是先宣告完陣列後再賦值,第二種是宣告時就給陣列值。

1. 先宣告陣列,後面再輸入值

如果要賦予陣列值可以使用for迴圈

  • 輸入一維陣列的值
    name[5]
for(int i=0;i<5;i++){ cin>>name[i]; }
    1. 輸入二維陣列的值(使用巢狀迴圈)
      score[100][5]
for(int i=0;i<100;i++){ for(int j=0;j<5;j++){ cin>>score[i][j]; } }

2. 宣告的同時賦予值

  • 完整給值(給初始值)
int score[5]={100,50,99,48,78};

此時

score[0]為100
score[1]為50
score[2]為99
score[3]為48
score[4]為78
  • 不完整給值
int score[5]={100,50};

此時

score[0]為100
score[1]為50
score[2]~score[4]為0

如何取得陣列值

重要!! 陣列的第一個索引值是0不是1
也就是說,當你要取得陣列的第一個值時,你必須將索引值打0才行,以下面這個已賦值的陣列為例。

int score[5]={100,50,99,48,78};

如果我們要取第一個人的成績,則要打score[0]
以此可推知,若要取第二個人的成績,則為score[1]