第04章_陣列
本章專題脈絡
1、陣列的概述
1.1 為什麼需要陣列
需求分析1:
需要統計某公司50個員工的工資情況,例如計算平均工資、找到最高工資等。用之前知識,首先需要宣告50個變數
來分別記錄每位員工的工資,這樣會很麻煩。因此我們可以將所有的資料全部儲存到一個容器中統一管理,並使用容器進行計算。
需求分析2:
容器的概念:
- 生活中的容器:水杯(裝水等液體),衣櫃(裝衣服等物品),集裝箱(裝貨物等)。
- 程式中的容器:將多個資料儲存到一起,每個資料稱為該容器的元素。
1.2 陣列的概念
-
陣列(Array),是多個
相同型別
資料按一定順序
排列的集合,並使用一個名字命名,並透過編號的方式對這些資料進行統一管理。 -
陣列中的概念
- 陣列名
- 下標(或索引、index)
- 元素
- 陣列的長度
陣列的特點:
- 陣列中的元素在記憶體中是依次緊密排列的,有序的。
- 建立陣列物件會在記憶體中開闢一整塊
連續的空間
。佔據的空間的大小,取決於陣列的長度和陣列中元素的型別。 - 我們可以直接透過下標(或索引)的方式呼叫指定位置的元素,速度很快。
- 陣列,一旦初始化完成,其長度就是確定的。陣列的
長度一旦確定,就不能修改
。 - 陣列名中引用的是這塊連續空間的首地址。
1.3 陣列的分類
按照陣列維度分:
- 一維陣列:儲存一組資料
- 二維陣列:儲存多組資料,相當於二維表,一行代表一組資料。每一行長度可以不同。
- 三維陣列、四維陣列、....
按照元素的資料型別分:
- int型別陣列
- char型別陣列
- double型別陣列
- ....
2、一維陣列的定義
2.1 陣列的定義方式1
陣列透過變數名後加方括號表示,方括號裡面是陣列可以容納的成員數量(即長度)。
int arr[10]; //陣列 arr ,裡面包含10個成員,每個成員都是 int 型別
#define NUM 10
int arr1[NUM];
注意,宣告陣列時,必須給出陣列的大小。
2.2 陣列元素的呼叫
-
格式:
陣列名[下標]
-
陣列的
下標從0開始
,用“int arr[10];”定義陣列,則最大下標值為9
,不存在陣列元素arr[10]。
arr[0] = 13; //對該位置陣列元素進行賦值
int score = arr[0]; //呼叫此位置的元素值
陣列角標越界:
假設陣列有n個元素,如果使用的陣列的下標小於0,或者大於n-1,就是陣列越界訪問了,超出了陣列合法空間的訪問。
C語言不做陣列下標越界的檢查,編譯器也不一定報錯,但是編譯器不報錯,並不意味著程式就是正確!
int scores[20];
scores[20] = 51;
說明:陣列 scores 只有20個成員,因此 scores[20] 這個位置是不存在的。但是,引用這個位置並不會報錯。賦值操作會導致緊跟在 scores 後面的那塊記憶體區域被賦值(這實際是其它變數的區域),因此不知不覺就更改了其它變數的值。這很容易引發錯誤,而且難以發現。
2.3 關於長度
陣列的位元組長度
sizeof 運算子會返回整個陣列的位元組長度。
int arr[10];
printf("陣列的位元組長度為:%zd\n",sizeof(arr)); //40
陣列的長度
在定義陣列時,需要指定陣列中元素的個數,方括號中的常量表示式用來表示元素的個數,即陣列長度。
由於陣列成員都是同一個型別,每個成員的位元組長度都是一樣的,所以陣列整體的位元組長度除以某個陣列元素的位元組長度,就可以得到陣列的成員數量。
//陣列中元素的個數:
int arrLen = sizeof(arr) / sizeof(arr[0]);
int a[10];
printf("陣列的位元組長度為:%zu\n", sizeof(a)); // 40
printf("陣列每個元素的位元組長度為:%zu\n", sizeof(int)); // 4
printf("陣列的長度為:%zu\n", sizeof(a) / sizeof(int)); // 10
複習: sizeof 返回值的資料型別是
size_t
,所以 sizeof(a) / sizeof(a[0]) 的資料型別也是size_t 。在 printf() 裡面的佔位符,要用 %zd 或 %zu 。
注意:陣列一旦宣告/定義了,其長度就固定了,不能動態變化。
2.4 陣列的遍歷
將陣列中的每個元素分別獲取出來,就是遍歷
。for迴圈與陣列的遍歷是絕配。
舉例1:宣告長度為10的int型別陣列,給陣列元素依次賦值為0,1,2,3,4,5,6,7,8,9,並遍歷陣列所有元素
int main() {
int arr[10];
//給陣列中的每個元素賦值
for (int i = 0; i < sizeof(arr)/sizeof(int); i++) { //對陣列元素arr[0]~arr[9]賦值
arr[i] = i;
}
//遍歷陣列中的元素
printf("遍歷陣列中的元素:\n");
for (int i = 0; i < sizeof(arr)/sizeof(int); i++) { //輸出arr[0]~arr[9]共10個陣列元素
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
2.5 陣列的其它定義方式
定義方式2:(定義方式1在2.1節講的)
陣列可以在宣告時,使用大括號,同時對每一個成員賦值。
int arr[5] = {22, 37, 90, 48, 95};
變形形式1:
C 語言允許省略方括號裡面的陣列成員數量,這時根據大括號裡面的值的數量,自動確定陣列的長度。
int arr[3] = {10,20,30};
// 等同於
int arr[] = {10,20,30}; //陣列 arr 的長度,將根據大括號裡面的值的數量,確定為 3
變形形式2:
對陣列部分元素賦初值:如果大括號裡面的值,少於陣列的成員數量,那麼未賦值的成員自動初始化為 0 。
int arr[5] = {10, 20, 30};
// 等同於
int arr[5] = {10,20,30, 0, 0};
變形方式3
:
將整個陣列的每一個成員都設定為零,最簡單的方式如下
int a[100] = {0};
錯誤方式:
使用大括號賦值時,大括號裡面的值不能多於陣列的長度,否則編譯時會報錯。
int arr[3] = {1,2,3,4}; // 報錯
定義方式3:陣列初始化時,可以指定為哪些位置的成員賦值。
int arr[15] = {[2] = 10, [5] = 20, [14] = 30}; //非角標2、5、14的位置自動賦值為0
//等同於
int arr[15] = {[5] = 20, [14] = 30, [2] = 10}; //指定位置的賦值可以不按角標從小到大的順序
變形形式1:
指定位置的賦值與順序賦值,可以結合使用。
int arr[15] = {1, [5] = 10, 11, [10] = 20, 21}; //角標0、5、6、10、11的位置被賦值
變形形式2:
省略成員數量時,如果同時採用指定位置的賦值,那麼陣列長度將是最大的指定位置再加1。
int arr[] = {[2] = 6, [9] = 12}; //此時陣列的長度是10
3、一維陣列記憶體分析
3.1 陣列記憶體圖
針對於如下程式碼:
int a[5] = {1,2,3,4,5};
對應的記憶體結構:
說明:
1)陣列名,記錄該陣列的首地址 ,即 a[0]的地址。
2)陣列的各個元素是連續分佈的, 假如 a[0] 地址是0x1122,則a[1]地址= a[0]的地址+int位元組數(4)
= 0x1122 + 4 = 0x1126,後面 a[2] 地址 = a[1]地址 + int 位元組數(4)
= 0x1126 + 4 = 0x112A,依次類推...
3.2 注意事項
C 語言規定,陣列變數一旦宣告,陣列名指向的地址就不可更改。因為宣告陣列時,編譯器會自動為陣列分配記憶體地址,這個地址與陣列名是繫結的,不可更改。
因此,當陣列定義後,再用大括號重新賦值,是不允許的。下面的程式碼會報錯。
錯誤舉例1:
int nums[5];
nums = {22, 37, 3490, 18, 95}; // 使用大括號賦值時,必須在陣列宣告時賦值,否則編譯時會報錯。
錯誤舉例2:
int nums[5] = {1, 2, 3, 4, 5};
nums = {6, 7, 8, 9, 10}; // 報錯
錯誤舉例3:
int ints[100];
ints = NULL; //報錯
這也導致不能將一個陣列名賦值給另外一個陣列名。
int a[5] = {1, 2, 3, 4, 5};
// 寫法一
int b[5] = a; // 報錯
// 寫法二
int b[5];
b = a; // 報錯
上面兩種寫法都會更改陣列 b 的地址,導致報錯。
3.3 變長陣列
陣列宣告的時候,陣列長度除了使用常量,也可以使用變數或表示式來指定陣列的大小。這叫做變長陣列
(variable-length array,簡稱 VLA)。
方式1:
int n = 10;
int arr[n];
變長陣列的根本特徵是陣列長度只有執行時才能確定
。它的好處是程式設計師不必在開發時,隨意為陣列指定一個估計的長度,程式可以在執行時為陣列分配精確的長度。
任何長度需要執行時才能確定的陣列,都是變長陣列。比如,
int i = 10;
int a1[i];
int a2[i + 5];
int a3[i + k];
注意:變長陣列在C99標準中被引入,在C11標準中被標記為可選特性。某些編譯器可能不支援變長陣列,或者可能有特定的限制和行為。
方式2:
如果你的編譯器版本不支援變長陣列,還可以考慮使用動態記憶體分配(使用malloc()函式
)來建立動態大小的陣列。
分配:
int length = 5;
int *arr = (int *)malloc(length * sizeof(int));
釋放:
free(arr);
4、一維陣列的應用
4.1 數值型陣列特徵值統計
這裡的特徵值涉及到:平均值、最大值、最小值、總和等
舉例1:定義一個int型的一維陣列,包含10個元素,然後求出陣列中的最大值,最小值,總和,平均值,並輸出出來。
int main() {
int arr[10] = {34, 54, 2, 32, 54, 57, 3, 32, 87, 43};
int max = arr[0];//用於記錄陣列的最大值
int arrLen = sizeof(arr) / sizeof(int);//獲取陣列中元素的個數
for (int i = 1; i < arrLen; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
printf("最大值為:%d\n", max);
//獲取陣列的最小值
int min = arr[0];
for (int i = 1; i < arrLen; i++) {
if (min > arr[i]) {
min = arr[i];
}
}
printf("最小值為:%d\n", min);
//獲取陣列的總和
int sum = 0;
for (int i = 0; i < arrLen; i++) {
sum += arr[i];
}
printf("總和為:%d\n", sum);
//獲取陣列的平均值
int avg = sum / arrLen;
printf("平均值為:%d\n", avg);
return 0;
}
舉例2:評委打分
分析以下需求,並用程式碼實現:
(1)在程式設計競賽中,有10位評委為參賽的選手打分,分數分別為:5,4,6,8,9,0,1,2,7,3
(2)求選手的最後得分(去掉一個最高分和一個最低分後其餘8位評委打分的平均值)
int main() {
int scores[10] = {5,4,6,8,9,0,1,2,7,3};
int max = scores[0]; //記錄最高分
int min = scores[0]; //記錄最低分
int sum = 0; //記錄總分
int arrLen = sizeof(scores) / sizeof(int); //記錄陣列長度
for(int i = 0;i < arrLen;i++){
if(max < scores[i]){
max = scores[i];
}
if(min > scores[i]){
min = scores[i];
}
sum += scores[i];
}
//計算平均分
double avg = (double)(sum - max - min) / (arrLen - 2);
printf("選手去掉最高分和最低分之後的平均分為:%.2lf\n" , avg);
return 0;
}
4.2 陣列的複製
由於陣列名是指標,所以複製陣列不能簡單地複製陣列名。
int a[3] = {10,20,30};
int* b;
b = a;
上面的寫法,結果不是將陣列 a 複製給陣列 b ,而是讓 a 和 b 指向同一個陣列。
正確方式1:使用迴圈
這是複製陣列最簡單的方法,將陣列元素逐個進行復制。比如,將陣列 a 的成員逐個複製給陣列 b。
#include <stdio.h>
#define LENGTH 3
int main() {
int a[LENGTH] = {10, 20, 30};
int b[LENGTH];
// 複製陣列 a 到陣列 b
for (int i = 0; i < LENGTH; i++) {
b[i] = a[i];
}
// 列印陣列 b 的內容
printf("複製後的陣列 b:");
for (int i = 0; i < LENGTH; i++) {
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
正確方式2:使用 memcpy() 函式
memcpy() 函式定義在標頭檔案 string.h 中,直接把陣列所在的那一段記憶體,再複製一份。3個引數依次為:目標陣列
、源陣列
以及要複製的位元組數
。
#include <stdio.h>
#include <string.h>
#define LENGTH 3
int main() {
int a[LENGTH] = {10, 20, 30};
int b[LENGTH];
// 使用 memcpy 函式複製陣列 a 到陣列 b
memcpy(b, a, LENGTH * sizeof(int));
// 列印陣列 b 的內容
printf("複製後的陣列 b:");
for (int i = 0; i < LENGTH; i++) {
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
兩種方式對比:
下面是對兩種方式進行比較的一些要點:
- 迴圈複製:
- 優點:
簡單直觀
,容易理解和實現。不需要引入額外的標頭檔案。 - 缺點:需要編寫迴圈程式碼來遍歷陣列並逐個賦值,相對而言可能
稍顯繁瑣
。不適用於複製大型陣列或複雜資料結構。
- 優點:
- memcpy函式複製:
- 優點:使用標準庫提供的函式,可以實現
快速且高效
的記憶體複製。適用於大型陣列或複雜資料
結構的複製。可以直接複製位元組數,不需要遍歷陣列。 - 缺點:需要包含
<string.h>
標頭檔案。對於簡單的陣列複製,可能有些過於繁重
。
- 優點:使用標準庫提供的函式,可以實現
4.3 陣列元素的反轉
實現思想:陣列對稱位置的元素互換。
方式1:
程式碼實現
int main() {
int arr[] = {1,2,3,4,5,6,7,8,9};
int size = sizeof(arr) / sizeof(arr[0]); //陣列的長度
printf("原始陣列:");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
for(int i = 0;i < size / 2;i++){
int temp = arr[i];
arr[i] = arr[size - 1 - i];
arr[size - 1 - i] = temp;
}
printf("反轉後的陣列:");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
方式2:
int main() {
int arr[] = {1, 2, 3, 4, 5,6,7,8,9};
int size = sizeof(arr) / sizeof(arr[0]); //陣列的長度
printf("原始陣列:");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
int left = 0; // 起始指標
int right = size - 1; // 結尾指標
while (left < right) {
// 交換起始指標和結尾指標指向的元素
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
// 更新指標位置
left++;
right--;
}
printf("反轉後的陣列:");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
4.4 char型陣列與字串
4.4.1 char型陣列
字元型陣列,顧名思義,陣列元素的資料型別為字元型的陣列。
一方面,可以看做普通的陣列,初始化、常用操作如前所述。比如:
char arr[] = {'a','b','c','d'};
另一方面,字元型陣列可以用於儲存字串。
4.4.2 字串的使用
"helloworld"
"abc"
"a"
"123"
這種由雙引號引起來的一串字元稱為字串字面值(String Literal),簡稱字串(String)。
通常把""
稱為空串
,即一個不包含任意字元的字串;而" "
則稱為空格串
,是包含一個空格字元的字串。二者不能等同。
C語言沒有專門用於儲存字串的變數型別,字串都被儲存在char型別的陣列中。在字串結尾,C 語言會自動新增一個'\0'
的跳脫字元作為字串結束的標誌,所以字元陣列也必須以 '\0'字元結束。
宣告方式1:標準寫法
//顯式以'\0'為最後一個字元元素結束
char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
如果一個字元陣列宣告如下,由於必須留一個位置給 \0
,所以最多隻能容納9個字元的字串。
char str1[10];
宣告方式2:簡化寫法
字串寫成陣列的形式,是非常麻煩的,C 語言提供了一種簡化寫法。雙引號之中的字元,會被自動視為字元陣列。
//自動在末尾新增'\0'字元
char str1[12] = {"hello world"}; //注意使用雙引號,非單引號
//或者
char str2[12] = "hello world"; //可以省略一對{}來初始化陣列元素
由於字元陣列的長度可以讓編譯器自動計算,所以宣告時可以省略字元陣列的長度:
char str1[] = {"hello world"};
//或者
char str2[] = "hello world";
雙引號裡面的字串,不用自己新增結尾字元 \0 ,C 語言會自動新增。所以,程式碼中陣列 str1或str2的元素依次為 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0'。
字串對應陣列的長度
對應的儲存為:
其中,陣列由連續的儲存單元組成,字串中的字元被儲存在相鄰的儲存單元中,每個單元儲存一個字元。所以,上述兩個陣列的長度不是11,而是12。
字串的長度
char nation[10]={"China"};
陣列nation的前5個元素為: ′C′,′h′,′i′,′n′,′a′,第6個元素為′\0′,後4個元素也自動設定為空字元。
注意:在計算字串長度的時候,'\0' 是結束標誌,不算作字串內容。
#include <stdio.h>
#include <string.h> //需要載入此標頭檔案
int main() {
char nation[10] = "China";
printf("%d\n", strlen(nation)); //5
}
區分:'\0'、0、'0'
字元 '\0' 不同於字元 '0' ,前者的ASCII 碼是0(二進位制形式 00000000 ),後者的 ASCII 碼是48(二進位制形式 00110000 )。
練習1:字元陣列、字串的長度
char s1[50] = "hello"; //宣告1
char s2[] = "hello"; //宣告2
char s3[5] = "hello"; //宣告3
對於宣告1:賦給的元素的個數小於該陣列的長度,則會自動在後面加 '\0', 表示字串結束。所以,字元陣列 s1 的長度是 50 ,但是字串“hello”的實際長度只有5(不包含結尾符號 '\0' ),所以後面空出來的45個位置,都會被初始化為 '\0'。
對於宣告2:字元陣列 s2 的長度是 6(包含結尾符號 '\0' ),但是字串“hello”的實際長度只有5。
對於宣告3:賦給的元素的個數等於該陣列的長度,則不會自動新增 '\0'。但字串要求以'\0'結束,所以這種寫法是錯誤的,要避免。
練習2:比較"x"和'x'的不同
-
書寫形式不同:字串常量用雙引號,字元常量用單引號。
-
儲存空間不同:在記憶體中,字元常量只佔用一個位元組的儲存空間,而字串儲存時自動加一個結束標記'\0',所以'x'佔用1個位元組,而"x"佔用2個位元組。
- 二者的操作也不相同。例如,可對字元常量進行加減運算,字串常量則不能。
練習3:輸出字元陣列
#include <stdio.h>
int main() {
char str1[]={"China\nBeijing"};
char str2[] = "helloworld";
puts(str1);
puts(str2);
return 0;
}
【中央財經大學2018研】若有定義和語句:char s[10]; s="abcd"; printf("%s\n",s);,則結果是( )。
A.輸出abcd@#$
B.輸出a
C.輸出abcd
D.編譯不透過【答案】D
【解析】在定義一維字元陣列時,s為陣列名,指向陣列首元素的地址,為地址常量,不可更改,因此語句s="abcd"是非法的,編譯不會透過。
5、多維陣列
5.1 理解
二維陣列、三維陣列、...都稱為多維陣列。本節主要講解二維陣列,三維及以上的陣列,以此類推即可。
舉例:公司有3個攻堅小分隊,每隊有6名同事,要把這些同事的工資用陣列儲存起來以備檢視。
此時建立陣列salary用於儲存工資,它應當是二維的。第一維用來表示第幾分隊,第二維用來表示第幾個同事。例如用salary2,3
表示角標2對應分隊的角標3對應隊員的工資。
對於二維陣列的理解,可以看作是由一維陣列巢狀而成的。即一維陣列array1又作為另一個一維陣列array2的元素而存在。
5.2 二維陣列的定義方式1
定義方式1:
int a[3][4]; //二維陣列
二維陣列a可看成由三個一維陣列構成,它們的陣列名分別為 a[0]、a[1]、a[2]。這三個一維陣列各有 4 個元素,如,一維陣列 a[0] 的元素為 a[0][0]
、a[0][1]
、a[0][2]
、a[0][3]
。二維陣列a共有12個成員(3 x 4 = 12)。
也可以簡化理解為:
二維陣列,常稱為矩陣(matrix)
。把二維陣列寫成行(row)
和列(column)
的排列形式,可以形象化地理解二維陣列的邏輯結構。
三維陣列如下:
int arr1[3][4][5]; //三維陣列
技巧:C 語言允許宣告多維陣列,有多少個維度,就用多少個方括號,比如二維陣列就使用兩個方括號。
錯誤方式:
float a[3,4]; //在一對方括號內不能寫兩個下標
5.3 二維陣列的記憶體分析
用矩陣形式
(如3行4列形式)表示二維陣列,是邏輯
上的概念,能形象地表示出行列關係。而在記憶體
中,各元素是連續存放的,不是二維的,是線性
的。
C語言中,二維陣列中元素排列的順序是按行存放
的。即:先順序存放第一行的元素,再存放第二行的元素。(最右邊的下標變化最快,第一維的下標變化最慢)。
舉例,整型陣列b[3][3]
在記憶體中的存放:
舉例:關於長度
int b[3][3];
printf("%d\n",sizeof(b)); //36
printf("%d\n",sizeof(b)/sizeof(int)); //9
5.4 成員的呼叫
格式:陣列名[下標] [下標]
跟一維陣列一樣,多維陣列每個維度的第一個成員也是從 0 開始編號。
舉例1:給指定索引位置的元素賦值
int arr1[3][5];
//給指定索引位置的元素賦值
arr1[0][0] = 12;
arr1[3][4] = 5;
舉例2:檢視陣列元素的地址
int main() {
int arr2[3][4];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("&arr2[%d][%d] = %p\n", i, j, &arr2[i][j]);
}
}
return 0;
}
輸出結果如下:
5.5 二維陣列其它定義方式
定義方式2:宣告與初始化同時進行
多維陣列也可以使用大括號,在宣告的同時,一次性對所有成員賦值。
int a[3][4] = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
上例中, a 是一個二維陣列,這種賦值寫法相當於將第一維的每個成員寫成一個陣列。
說明:這裡的地址以十進位制數值進行的說明。
int main() {
int a[3][4] = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
printf("%p\n",a[0]); //0000006ac71ffd30
printf("%p\n",a[0] + 1); //0000006ac71ffd34
printf("%p\n",a[0] + 2); //0000006ac71ffd38
printf("%p\n",a[0] + 3); //0000006ac71ffd3c
printf("%p\n",a[0] + 4); //0000006ac71ffd40
printf("%p\n",a + 1); //0000006ac71ffd40
printf("%p\n",a[1]); //0000006ac71ffd40
printf("%p\n",a[1] + 1); //0000006ac71ffd44
return 0;
}
定義方式3:部分元素賦值
多維陣列也可以僅為指定的位置進行初始化賦值,未賦值的成員會自動設定為“零”值 。
//指定了 [0][0] 和 [1][1] 位置的值,其他位置就自動設為 0 。
int a[2][2] = {[0][0] = 1, [1][1] = 2};
定義方式4:使用單層大括號賦值
多維陣列也可以使用單層大括號賦值。不管陣列有多少維度,在記憶體裡面都是線性儲存。對於a[2][2]
來說, a[0][0]
的後面是 a[0][1]
,再後面是a[1][0]
,以此類推。
int a[2][2] = {1, 0, 0, 2}; //會自動匹配到各行各列
定義方式5:方式4的簡化
在方式4的基礎上,如果對全部元素賦值,那麼第一維的長度可以不給出。
//int a[2][3] = {1, 2, 3, 4, 5, 6};
//可以寫為:
int a[][3] = {1, 2, 3, 4, 5, 6};
//也可以寫為:
int a[][3] = {{1, 2, 3},{4, 5, 6}}; //行數自然判定為2
練習:下面哪些賦值操作是正確的?(都對)
int arr1[3][2]={{1,2},{3,4},{5,6}}; //對應定義方式2
int arr2[3][2]={1,2,3,4,5,6}; //對應定義方式4
int arr3[][2]={1,2,3,4,5,6}; //對應定義方式5
int arr4[][2]={{1,2},{3,4},{5,6}}; //對應定義方式5
int arr5[][2]={1,2,3,4,5}; //對應定義方式5。未顯式賦值的位置預設賦值為0
錯誤方式:在定義二維陣列時,必須指定列數(即一行中包含幾個元素)
int array[][]; //錯誤,必須指定列數
int array[3][]; //錯誤,必須指定列數
【武漢科技大學2019研】以下能對陣列value進行正確初始化的語句是( )。
A.int value[2][]={{1,1},{2,2}};
B.int value[][3]={{1,,3},{4,5,6}};
C.int value[2][3]={1,2,3,4,5,6};
D.int value[][3]={{1},{4,6,}};【答案】C
【解析】二維陣列的定義必須指定列數,可以不用指定行數,A錯誤;陣列value為int型陣列,不能給陣列裡面的元素賦空值,BD錯誤,答案選C。
5.6 舉例
舉例1:獲取arr陣列中所有元素的和
提示:使用for的巢狀迴圈即可。
#include <stdio.h>
#define ROWS 3
#define COLS 4
int main() {
int arr[ROWS][COLS] = {{3, 5, 8},
{12, 9},
{7, 0, 6, 4}};
int sum = 0;//記錄總和
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
sum += arr[i][j];
}
}
printf("總和為%d\n", sum);
return 0;
}
舉例2:求二維陣列最大值以及對應的行列角標
#include <stdio.h>
#define ROWS 3
#define COLS 4
int main() {
int a[ROWS][COLS] = {{1, 2, 3, 4},
{9, 8, 7, 6},
{-10, 10, -5, 2}};
int maxValue = a[0][0];
int maxRow = 0;
int maxCol = 0;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (maxValue < a[i][j]) {
maxValue = a[i][j];
maxRow = i;
maxCol = j;
}
}
}
printf("最大值: %d\n", maxValue);
printf("對應的行索引: %d\n", maxRow);
printf("對應的列索引: %d\n", maxCol);
return 0;
}
舉例3:將一個二維陣列行和列的元素互換,存到另一個二維陣列中。
a[i][j] ---> b[j][i]
#include <stdio.h>
#define ROWS 2
#define COLS 3
int main() {
int a[ROWS][COLS] = {{1, 2, 3},
{4, 5, 6}};
int b[COLS][ROWS];
printf("陣列 a:\n");
for (int i = 0; i < ROWS; i++) { //處理a陣列中的一行中各元素
for (int j = 0; j < COLS; j++) { //處理a陣列中某一列中各元素
printf("%5d", a[i][j]); //輸出a陣列的一個元素
}
printf("\n");
}
for (int i = 0; i < ROWS; i++) { //處理a陣列中的一行中各元素
for (int j = 0; j < COLS; j++) { //處理a陣列中某一列中各元素
b[j][i] = a[i][j]; //將a陣列元素的值賦給b陣列相應元素
}
}
printf("陣列 b:\n"); //輸出b陣列各元素
for (int i = 0; i < COLS; i++) { //處理b陣列中一行中各元素
for (int j = 0; j < ROWS; j++) //處理b陣列中一列中各元素
printf("%5d", b[i][j]); //輸出b陣列的一個元素
printf("\n");
}
return 0;
}
執行結果:
舉例4:二維char型陣列
將"Apple"、"Orange"、"Grape"、"Pear"、"Peach"儲存在陣列中。
char fruit[][7]={"Apple","Orange","Grape","Pear","Peach"};
對應圖示:
舉例5:使用二維陣列列印一個 10 行楊輝三角。
提示:
-
第一行有 1 個元素, 第 n 行有 n 個元素
-
每一行的第一個元素和最後一個元素都是 1
-
從第三行開始, 對於非第一個元素和最後一個元素的元素。即:
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
#include <stdio.h>
#define ROWS 10
int main() {
int yangHui[ROWS][ROWS];
for (int i = 0; i < ROWS; i++) {
//初始化第一列和對角線上的元素為1
yangHui[i][0] = 1;
yangHui[i][i] = 1;
//給其他位置元素賦值
for (int j = 1; j < i; j++) {
yangHui[i][j] = yangHui[i - 1][j - 1] + yangHui[i - 1][j];
}
}
// 列印楊輝三角
for (int i = 0; i < ROWS; i++) {
// 列印每行的元素
for (int j = 0; j <= i; j++) {
printf("%5d ", yangHui[i][j]);
}
printf("\n");
}
return 0;
}
【華南理工大學2018研】以下陣列定義中不正確的是( )。
A.int a[2][3];
B.int b[][3]={0};
C.int c[100][100]={0};
D.int d[3][]={{1}, {1, 2, 3},{1}};【答案】D
【解析】定義二維陣列時一定要指定陣列的列數,可以不指定陣列的行數,D錯誤。