Ch9 陣列

上一章:處理不同輸入規則
下一章:字串與大數
回目錄:國立科學園區實驗中學C++程式語言自學講義

為何需要陣列

還記得我們在條件判斷的章節中曾經學到
從三個數字裡面挑出最大的數字或最小的數字

數字只有三個的時候
可以宣告a, b, c三個變數

但若數字有100個該怎麼辦呢?
宣告a, b, c, d, e, f, g, h, i, , x, y, z,再宣告A, B, C, D, X, Y, Z,再宣告AA, BB, CC嗎?
看起來很不妙,說不定自己都忘記宣告到第幾個了

宣告a1, a2, a3, a4, , a100呢?
雖然分得清楚數量跟現在是第幾個
但是要用手打出a1至a100也太累了
萬一有10000個數字就更不得了

陣列的用途就在這裡
你可以把它當成一大群變數
除了宣告的時候可以一次通通宣告出來之外
還有許多方便的功能
一起來看看

宣告一個陣列

一個變數就相當於一個盒子
盒子的種類就代表著盒子裡面可以放什麼類型的資料
例如宣告成int的變數就相當於可以存放整數的盒子

而陣列就相當於一排盒子
這一排盒子裡面的每一個盒子都可以放一個自己的值
而宣告成int的陣列就相當於一排可以存放整數的盒子
也就是一群整數類型的變數

宣告陣列的方法如下

int a[100];

這樣的陣列代表有100個存放整數的位置

而這100個位置的編號
不是從1到100
而是從0到99!!!

切記切記

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 →

使用陣列裡的值

陣列裡面的每一格都可以當成一般變數來使用
可以將它改成某個值
可以對它cin
可以印出它的值(cout)
也可以將某個變數的值變成和它的值一樣(=)
一切用法都跟一般變數完全相同

要取用名為a的陣列裡的第i格
可以寫成a[i]
請記得方框左邊的是陣列的名稱
方框裡面的是要取用的格子的編號

以下的範例都假設已經宣告了int a[100]

將陣列a的編號為0的格子存入5

a[0]=5;

將陣列a的編號為40的格子讀入使用者的輸入

cin >> a[40];

印出陣列a的編號為80的格子的值

cout << a[80];

將b這個變數變成和陣列a的第20格一樣的值

b = a[20];

切記,這個陣列有幾格
是在宣告的時候就已經決定了
例如當初宣告成

int a[100];

就代表讓a這個陣列有100個格子
而這些格子的編號為0至99

如果要取用不存在的格子
會發生什麼事?
例如

cin >> a[-1];   //負數的編號是絕對不存在的
cout << a[100]; //要宣告101格以上才會有第100格
a[99999] = 5;   //要宣告100000格以上才會有第99999格

程式會當掉!!
請大家多加留意

那麼到底應該宣告幾格才夠呢
可以從題目敘述來判斷題目至多會用到幾個格子
我的習慣是會再多留一些
(就像剪膠帶時會多剪一小段XD)
例如題目保證只會輸入1000個數字
我就會宣告

int a[1005];

不過這只是個人習慣問題
同學可以依自己習慣來做

陣列也不是想開多大就可以開多大喔
同學可以試試看開多大會讓程式當掉(那尼?)
(大概是一百萬就會掛了)

讀入和印出陣列裡的值

會使用到陣列的題目
通常會先輸入一個n來代表接下來有幾個數字要放入陣列內

絕對不要寫成

int n; cin >> n; int a[n];

因為要使用多少記憶體是在執行程式前就要先決定好的
而非隨著使用者的輸入來決定
所以可以先看題目敘述的n最大會到多少
直接宣告這麼大的陣列就一定夠用了

接下來題目就會輸入n個數字
要將這n個數字存進陣列裡面
可以使用for迴圈來幫忙
範例程式如下

int a[100]; //因為題目保證n絕不超過100 int n; cin >> n; for(int i=0;i<n;i++){ //從0號到n-1號都讀進來 cin >> a[i]; }

這樣一來就可以把題目輸入的資料都存進陣列裡了

【例題】

輸入一個n以及n個數字
請將該n個數字再依序輸出
其中,題目保證 n <= 50

int a[50]; //因為n保證不超過50 int n; cin >> n; for(int i=0;i<n;i++){ cin >> a[i]; } for(int i=0;i<n;i++){ cout << a[i] << " "; //把陣列裡的每一個值印出來,以空白隔開 }

【學生練習題】

把陣列裡的每個值都看過一遍

【例題】

輸入一個n以及n個數字
請輸出裡面最小的數字
(保證 n<=50)

還記得當初從3個數字裡找最小值的程式

int a, b, c; cin >> a >> b >> c; int min; min=a; if(b<min) min=b; if(c<min) min=c; cout << min <<endl;

先假設a是最小的
再依序看b和c,如果比目前看過的最小值還要小
就更新目前看過的最小值
等所有數字都看過之後就可以找出最小值了

現在改成從n個數字裡面找最小值
方法也是一模一樣的
只是把a、b、c
換成a[0]、a[1]、a[2]a[n-1]而已

int n; int a[50]; cin >> n; for(int i=0;i<n;i++){ //把所有數字讀進來 cin >> a[i]; } int min; min=a[0]; //先假設a[0]是最小的 for(int i=1;i<n;i++){ //從a[1]開始一個一個看,如果比目前小就改成它 if(a[i]<min) min=a[i]; } cout << min << endl;

【學生練習題】

【例題】

輸入一個n以及n個數字
請輸出奇數和偶數分別有幾個
(n<=50)

這題可以多利用兩個變數來記錄奇數有多少、偶數有多少

int n; int a[50]; cin >> n; for(int i=0;i<n;i++){ cin >> a[i]; } int odd=0; int even=0; for(int i=0;i<n;i++){ if(a[i]%2==1) odd=odd+1; else even=even+1; } cout << odd << " " << even << endl;

【學生練習題】

以使用者的輸入來指定陣列裡的某一格

我們也可以直接用cin的變數來指定某一格

舉例來說

int n; int a[100]; cin >> n; a[n] = 1;

哪一格會變成1?
完全是依照輸入的數字n來決定

當然,也可以利用迴圈把好幾格變成1
例如

int n, i; int a[100]; for(i=0;i<10;i++){ cin >> n; a[n] = 1; }

這樣一來,總共會有10格變成1
哪10格?完全依照使用者輸入的數字決定
這可以用來達成標記的功能

【例題】

班上有n個人,廣播把m個人叫走了
輸入n與m,還有m個號碼
依序輸出班上每個人在或不在教室
1代表在,0代表他離開了

一開始,大家都還留在班上,先把每一格都標上1來表示他在班上

for(i=1;i<=n;i++) a[i]=1;

廣播來了,把被叫走的人的那格改成0,代表他不在班上了

cin>>m; for(i=0;i<m;i++){ cin>>k; a[k]=0; }

用k來代表每次廣播叫到的號碼
這邊可以看到cin被包在迴圈裡了
m是多少,就會有幾次cin>>k
並且把第k格的數字變成0

最後把班上所有人在或不在的訊息印出來

for(i=1;i<=n;i++){ cout<<a[i]<<endl; }

【例題】

承上題
請把所有還在教室的人的號碼依序印出來,中間空一格

把還在教室的人印出來
不在教室的就不要印
那麼就要使用if else囉

for(i=1;i<=n;i++){ if(a[i]==1) cout<<i<<" "; }

【學生練習題】

小補充~

剛才的陣列a
裡面的內容只會有0或1,不會變成其他數字
這樣的話其實可以在宣告陣列時
將原本的int a[100]
改成bool a[100]
(其餘的程式都不用變)
這樣一來使用的記憶體可以更少一點喔~

bool在上學期最一開始有介紹過
是用來表達「是或否」的變數
因此可能的值就只有0或1而已
所以使用的記憶體可以比int更少
不過如果大家還不熟悉bool的用法
可以繼續維持使用int沒有關係~!

組合技:找出眾數

【例題】

班上有n個人,保證n小於等於36
輸入一個數字n,以及n個數字代表每個人的身高
請求出班上大家身高的「眾數」,以及它所出現的次數

看到會輸入n個數字代表大家的身高
首先就要馬上想到
要開一個陣列來存這些數字

int height[40]; //因為題目保證n不超過36,那就乾脆40好了

接著把n以及n個身高讀進來

int n; cin >> n; int i; for(i=1;i<=n;i++) cin >> height[i];

好了,現在我們已經儲存好全班的身高了
接下來要怎麼找出「出現最多次的身高」呢?

我們可以把所有可能出現的身高都拿來看一看
例如可以先把1號同學的身高當成目標,看看全班有多少人和1號同學一樣高,並且記錄下來
再把2號同學的身高當成目標,看看全班有多少人和2號同學一樣高,並且看看這個數量是不是多於剛才1號那次所統計的
.
.
.
一直到把班上的第n號同學當成目標,看看全班有多少人和n號同學一樣高,這樣一來就把所有可能的數量都看過了,當然也可以順便找出最大的數字了

以下示範程式

先宣告兩個變數來代表「出現最多次的身高」、「它出現的次數」

int answer_height; int max_num;

接下來的迴圈中會不斷比較那時算出的數量有沒有比max_num還要大
如果有的話就會去取代max_num以及answer_height
為了要讓max_num一定至少會被取代掉一次
可以先讓它等於一個絕對小於答案的數字:-1

max_num=-1;

接下來要運用到我們學過的「迴圈包迴圈」
外面那層迴圈用來「試著把每一個人的身高都當成目標看看」
裡面那層迴圈用來「看看全班每一個人,有哪幾個人的身高和目標相同」

int i, j; for(i=1;i<=n;i++){ //輪流把1號至n號的同學的身高都拿來當目標看看 int goal=height[i]; //把i號同學的身高當成目標 int count=0; //用來計算全班有多少人是這個身高,計數器先歸零 for(j=1;j<=n;j++){ //把全班都看一看 if(height[j]==goal) count=count+1; //如果這個人的身高和現在的目標相同,就把計數器+1 } if(count>max_num){ //最後看看計數器,如果比目前的最大值還要大,就把最大值和答案更新過來 max_num=count; answer_height=goal; } }

最後印出答案
記得中間要空一格喔

cout << answer_height << " " << max_num ;

【學生練習題】

上一章:處理不同輸入規則
下一章:字串與大數
回目錄:國立科學園區實驗中學C++程式語言自學講義