Array Slide
Array Slide
由片語學習C程式設計
台灣大學資訊工程系劉邦鋒著
台灣大學劉邦鋒老師講授
第六單元
陣列
陣列
如果我們想要使用大量具同性質的變數,重複宣告變數需要
使用不同的變數名稱,非常麻煩。
我們可以使用陣列一次宣告許多同一性質的變數。
一次宣告 10 個整數變數。
a 後面的方括號 [10] 即表示 a 是一個有 10 個元素的整數
陣列。
特殊字元
中括號 [ ] 用來代表陣列。
屬性
int a[10];
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
a[9]
int a[10];
類別 – 整數 int
名字 – a
值 – 個別元素有個別的值。
元素個數 – 10
位址 – 第一個元素 a[0] 的位址。
學習要點
陣列的註標由 0 開始,所以陣列的第一個元素是 [0]。
一維陣列
使用片語 1 將一個陣列初始化為註標對應的偶數,並印出
陣列 a 中元素的值。
我們使用一個 for 迴圈將 a 中元素初始化,再用另一個
for 迴圈印出陣列 a 中各元素的值。
使用一個變數 i 作為註標,方便從陣列 a 取元素。
輸入 輸出
1 3 1 3
2 6 2 6
3 1 3 1
4 8 4 8
5 4 5 4
6 9 6 9
7 10 7 10
8 4 8 4
9 7 9 7
10 6 10 6
範例 程式 4: (inner-product.c) 計算內 積
1 # include < stdio .h >
2 main ()
3 {
4 int A [5] , B [5] , C = 0;
5 int i , j ;
6 for ( i = 0; i < 5; i ++)
7 scanf ( " % d " , &( A [ i ]));
8 for ( i = 0; i < 5; i ++)
9 scanf ( " % d " , &( B [ i ]));
10 for ( i = 0; i < 5; i ++)
11 C += A [ i ] * B [ i ];
12 printf ( " % d \ n " , C );
13 }
計算內積
計算向量 A 及 B 的內積,並將結果存入變數 C 中。
首先自鍵盤讀入向量 A 及 向量 B 中各元素的值。
再用另一個 for 迴圈來完成這個內積。
最後我們將結果 C 的值印出。
輸入
1 1 2 3 4 5
2 5 4 3 2 1
輸出
1 35
輸入檔並非一個數字一行,而是一個長度為 5 的向量一
行,而數字之間用一個空白隔開。
scanf 會在輸入檔中持續找數字,一行沒有找下一行,直到
找到為止。所以對 scanf 完全 沒有影 響。
在準備輸入檔時,我們可以清楚的理解,第一行五個數字是
給 A 向量,第二行五個數字是給 B 向量,這樣就不容易弄
錯。
學習要點
輸入檔的格式有助於了解輸入資料與變數的歸屬關係。
費伯納西數列
0 i =0
fib(i) = 1 i =1 (1)
fib(i − 1) + fib(i − 2) i ≥ 2
費伯納西數列
輸入 輸出
1 10 1 0
2 1
3 1
4 2
5 3
6 5
7 8
8 13
9 21
10 34
在陣列中尋找第一個符合某種性質的元素。
必須限定 i 不能超過 9,因為陣列只有 10 個元素。
迴圈結束後如果 i 為 10,則陣列 array 所有元素均為 1,
否則 array[i] 即為第一個不為 1 的元素。
輸入 輸出
1 50 1 2
2 3
3 5
4 7
5 11
6 13
7 17
8 19
9 23
10 29
11 31
12 37
13 41
14 43
15 47
學習要點
我們可以利用旗標陣列紀錄某個整數是否具有某種性質。
泡沫排序法
由左到右比較兩個相鄰元素,如果註標比較小的元素比較
大,則交換元素值。
由註標比較小的元素兩兩交換到註標比較大的元素,就能使
大的元素向註標比較大的方向移動,而小的元素向註標比較
小的方向移動。
用兩層 for 迴圈實作。
第一層迴圈決定兩兩交換的範圍。
第二層則實際作兩兩交換,
範例程式 8: (bubble-sort.c) 泡 沫排 序法
1 # include < stdio .h >
2 int main ()
3 {
4 int m , n [100];
5 int i , j , temp ;
6 scanf ( " % d " , & m );
7 for ( i = 0; i < m ; i ++)
8 scanf ( " % d " , &( n [ i ]));
9 for ( i = m - 2; i >= 0; i - -)
10 for ( j = 0; j <= i ; j ++)
11 if ( n [ j ] > n [ j + 1]) {
12 temp = n [ j ];
13 n [ j ] = n [ j + 1];
14 n [ j + 1] = temp ;
15 }
16 for ( i = 0; i < m ; i ++)
17 printf ( " % d \ n " , n [ i ]);
18 return 0;
19 }
輸入 輸出
1 10 1 0
2 7 6 9 0 8 4 5 3 2 1 2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
10 9
範 例 程 式 10: (print-array-address.c) 印 出 陣 列 a 中 的 元 素 的
大小及位址
1 # include < stdio .h >
2 main ()
3 {
4 int a [10];
5 int i ;
6
7 printf ( " % d \ n " , sizeof ( a [0]));
8 printf ( " % d \ n " , sizeof ( a ));
9 for ( i = 0; i < 10; i ++)
10 printf ( " % p \ n " , &( a [ i ]));
11 printf ( " % p \ n " , & a );
12 printf ( " % p \ n " , a );
13 }
輸出
1 4
2 40
3 0 x7fff8afdf920
4 0 x7fff8afdf924
5 0 x7fff8afdf928
6 0 x7fff8afdf92c
7 0 x7fff8afdf930
8 0 x7fff8afdf934
9 0 x7fff8afdf938
10 0 x7fff8afdf93c
11 0 x7fff8afdf940
12 0 x7fff8afdf944
13 0 x7fff8afdf920
14 0 x7fff8afdf920
a + (i × L) (2)
元素 a[i] 的記憶體位址可用上式表示。
a 為陣列 a 的起始位址,而 L 為每一元素所佔的位元組數。
a 的位址 和 a[0] 的位址一樣。
0028FEF4 a[0]
0028FEF8 a[1]
0028FEFC a[2]
0028FF00 a[3]
0028FF04 a[4]
0028FF08 a[5]
0028FF0C a[6]
0028FF10 a[7]
0028FF14 a[8]
0028FF18 a[9]
a 的意義
學習要點
在 C 程式語言中,陣列的值就是陣列的位址。如果要取陣列中
元素的值必須用方括號 [] 再加上註標變數。
片語 11: 陣 列的初 始化
1 int array [5] = {1 , 2 , 3 , 4 , 5};
陣列可以使用類似一般變數的方法加以初始化。
想給的初始值必須以逗號分開,再用大括號括起來。
片語 12: 陣 列的初 始化
1 int array [] = {1 , 2 , 3 , 4 , 5};
如果陣列有初始化,但沒有宣告宣告長度,編譯器會自行決
定陣列長度。
片語 13: 陣 列的初 始化
1 int array [5] = {1 , 2 , 3};
2 int array [5] = {1 , 2 , 3 , 0 , 0};
如果陣列有宣告長度,也有初始化,但初始化所給的元素數
目不足,則其餘的元素會被初始為 0。
兩種寫法是一樣的。
片語 14: 陣 列的初 始化
1 int array [10000] = {0};
利用這個補 0 的特性,我們可以很容易將整個陣列初始為
0。
多維陣列
多維陣列至少兩個個註標變數加上方括號 []才能指定陣列
中的元素。
矩陣相乘
計算矩陣 A 及 B 的乘積,將結果存入矩陣 C 中。
自鍵盤讀入矩陣 A 及 矩陣 B。
將矩陣 C 的各元素初始化為 0。
矩陣 C 的第 i 列 第 j 行的元素 C[i][j] 是矩陣 A 的第 i
列 及 於矩陣 B 的第 j 行的內積, 所以用另一個 for 迴圈
及註標變數 k 來完成內積。
印出 C。
範例 程式 17: (matrix-multiply.c) 矩陣 相乘
4 int A [2][3] , B [3][4] , C [2][4];
5 int i , j , k ;
6
7 for ( i = 0; i < 2; i ++)
8 for ( j = 0; j < 3; j ++)
9 scanf ( " % d " , &( A [ i ][ j ]));
10 for ( i = 0; i < 3; i ++)
11 for ( j = 0; j < 4; j ++)
12 scanf ( " % d " , &( B [ i ][ j ]));
13 for ( i = 0; i < 2; i ++)
14 for ( j = 0; j < 4; j ++)
15 C [ i ][ j ] = 0;
輸入 輸出
1 4 6 2 1 70
2 7 8 3 2 86
3 5 8 2 5 3 42
4 6 7 4 2 4 40
5 7 6 5 4 5 104
6 130
7 61
8 63
片語 18: 換行
1 printf ( " \ n " );
如果輸出一行一個數字就不容易理解,因為沒辦法和矩陣的
形狀連結起來。
如果我們在輸出矩陣 C 的時候不換行,執行結果會是所有
的數字都連在一起。
為了避免這個問題,我們可以在格式字串中加入空白,例如
"%d " 使數字不會連在一起,請注意%d之後的空白。
然後在適當的地方換行,將輸出結果與矩陣的形狀結合。換
行的方法就是在 printf 的格式字串單獨使用 \n。
範例 程 式 19: (matrix-multiply-lines.c) 矩陣 相乘
19 for ( i = 0; i < 2; i ++)
20 for ( j = 0; j < 4; j ++)
21 for ( k = 0; k < 3; k ++)
22 C [ i ][ j ] += A [ i ][ k ] * B [ k ][ j ];
23
24 for ( i = 0; i < 2; i ++) {
25 for ( j = 0; j < 4; j ++)
26 printf ( " %4 d " , C [ i ][ j ]);
27 printf ( " \ n " );
28 }
輸入 輸出
1 4 6 2 1 70 86 42 40
2 7 8 3 2 104 130 61 63
3 5 8 2 5
4 6 7 4 2
5 7 6 5 4
輸出一行
如果輸出都是一行一個數字,在處理大量迴圈資料時有些不
便。
以下範例會將輸出放進一行。
輸入
1 10
2 20
輸出
1 10 11 12 13 14 15 16 17 18 19 20
輸入
1 100
2 8
輸出
1 2 3 5 7 11 13 17 19
2 23 29 31 37 41 43 47 53
3 59 61 67 71 73 79 83 89
4 97
以一行 8 個質數的方式輸出。
以一個計數器 count 紀錄目前的質數個數。如果 count 除
以 8 餘 7,則代表處於行末,需換行。
多維陣列記憶體擺放
說明多維陣列在記憶體中的擺放方法。
使用輸出技術,讓位址的輸出和陣列的形狀相結合,方便使
用者檢視。
使用片語 18 換行,將輸出分塊,同樣方便使用者檢視。
記憶體大小
a[0]
a[0][0]
記憶體位置
記憶體中擺放的順序是
a[0][0][0],a[0][0][1],a[0][0][2],a[0][0][3],
a[0][1][0],最後一直排到 a[1][2][3]。
a 包含兩個矩陣。 每一個矩陣有三列,每一列都是一個有
四個元素的一維陣列。
擺放的方式就是先放第一個矩陣,再放第一個矩陣。 而一
個矩陣中先放第一列,再放第二列,最後放第三列。 每一
列由小到大按註標放。
0028FEB4 + (i × 3 × 4 + j × 4 + k) × 4 (4)
位址計算
n−1
X
a+( (ki × Πnj=i+1 mj ) + kn ) × L (5)
i=1
陣列 a 有 n 個維度,而第 i 個維度的元素數為 mi 。 a 為陣
列 a 的起始位址,而 L 是每一陣列元素所佔的位元組數。
元素 a[k1 ][k2 ] . . . [kn ] 的記憶體位址可表為上式。
C 程式語言 陣列的註標由 0 開始可大幅簡化位址的計算。
多維陣列也可以使用類似一維陣列的方法加以初始化。
對每一列給初始值。 以逗號分開,再用大括號括起來。然
後再把每一列的初始值以逗號分開,再用大括號括起來。
如果二維陣列有初始化,但沒有宣告宣告長度,編譯器會自
行決定。
不能寫成 array[][],這樣編譯器無法決定位址。
但可以寫成array[][3],因為這對決定位址並無影響。
輸出
1 1 2 3
2 4 5 6
片語 26: 陣 列的初 始化
1 int array [3][3] = {{1 , 2} , {4}};
2 int array [3][3] = {{1 , 2 , 0} ,{4 , 0 , 0} ,{0 , 0 , 0}};
不寫第一維的維度,編譯器會自行決定。
如果陣列有宣告長度,也有初始化,但初始化所給的元素數
目不足,則其餘的元素會被初始為 0。
以上兩種寫法是一樣的。
片語 27: 陣 列的初 始化
1 int array [100][100] = {{0}};
利用補 0 的特性可以很容易將整個陣列初始為 0。
輸出
1 1 2 0
2 4 0 0
3 0 0 0
4
5 0 0 0
6 0 0 0
7 0 0 0