定義
二維數組定義的一般形式是:
類型說明符 數組名[常量1][常量2]
常量1:第一維下標的長度
-
常量2:第二維下標的長度
int a[3][4];
這個二維數組表示一個三行四列的整形變量集合,數組名為a,下標變量的類型為整型。該數組的下標變量共有3×4個,即:
a[0][0], a[0][1], a[0][2], a[0][3]
a[1][0], a[1][1], a[1][2], a[1][3]
a[2][0], a[2][1], a[2][2], a[2][3]
仔細看這個二維數組,我們可以把它理解為一個二維坐標系的位置。這個二維坐標系的原點在左上角,x軸向右遞增,y軸向下遞增。(在計算機UI設計中,這種二維坐標系經常被使用)
如圖所示:
存儲形式
在內存中,二維數組被保存成一段連續的內存空間。就如同一個一維數組,二維數組也是按一維線性排列的。
具體的存儲方式有兩種:
- 按行排列
放完一行之后順次放入第二行。
- 按列排列
放完一列之后再順次放入第二列。
我們再回頭看一下這個二維數組:
int a[3][4];
其實,在內存中它的存儲方式相當于:
int b[12];
只不過,計算機把它分成了三個部分。
a[0][0] 對應于 b[0]
a[1][0] 對應于 b[4]
a[3][0] 對應于 b[8]
二維數組元素的引用
二維數組的元素也稱為雙下標變量,其表示的形式為:
數組名[下標][下標]
其中下標應為整型常量或整型表達式。例如:
a[0][2]
表示數組a第一行第三列的元素。
在講一維數組時,很多人反饋說無法區分數組定義和引用時方括號中的內容,今天我們來說一下這兩處用法的區別:
- 數組聲明的方括號中的是某一維的長度,即數組下標最大值 + 1
- 數組引用中的下標是該元素在數組中的位置標識
- 前者只能是常量,而后者可以是常量,變量或表達式。
下面我們通過一個具體的例子來講解。
一個學習小組有5個人(A, B, C, D, E),三次考試每個人的成績如下。請編程實現計算這個小組所有人三次考試的平均成績。
我們用一個二維數組a[5][3]存放五個人三次考試的成績。再用一個一維數組v[3]存放所求得每次考試的平均成績,最后求出v中三個成績的平均值。代碼如下:
int main(void)
{
int i, j, s = 0;
int average;
int v[3];
int a[5][3];
printf("input score:\n");
for(i = 0; i < 3; i++)
{
for(j = 0; j < 5; j++)
{
scanf("%d", &a[j][i]);
s += a[j][i];
}
v[i] = s / 5;
s = 0;
}
average = (v[0] + v[1] + v[2]) / 3;
printf("First:%d\nSecond:%d\nThird:%d\n", v[0], v[1], v[2]);
printf("Final Average:%d\n", average );
return 0;
}
執行結果如下:
大家應該都注意到了,我們通過scanf函數從鍵盤一個個錄入每個成績保存在二維數組中,這種方法太繁瑣。每次調試都需要輸入這15個數字,肯定沒人愿意。接下來我們看看有沒有其他的方法。
二維數組初始化
二維數組初始化也是在類型說明時給各下標變量賦以初值。主要有兩種方式:
- 按行分段賦值
- 按行連續賦值
這兩種方式如下:
int a[5][3] = {{80, 75, 92}, {61, 65, 71}, {59, 63, 70}, {85, 87, 90}, {76, 77, 85}};
int a[5][3] = {80, 75, 92, 61, 65, 71, 59, 63, 70, 85, 87, 90, 76, 77, 85};
這兩種賦初值的結果是完全相同的。
于是,上面的代碼可以改寫成這樣。
int main(void)
{
int i, j, s = 0;
int average;
int v[3];
int a[5][3]={{80, 75, 92}, {61, 65, 71}, {59, 63, 70}, {85, 87, 90}, {76, 77, 85}};
for(i = 0; i < 3; i++){
for(j = 0; j < 5; j++){
s += a[j][i];
}
v[i] = s / 5;
s = 0;
}
average = (v[0] + v[1] + v[2]) / 3;
printf("First:%d\nSecond:%d\nThird:%d\n",v[0],v[1],v[2]);
printf("Final Average:%d\n", average );
return 0;
}
執行結果完全相同,只不過不需要輸入。
在對二維數組賦初值時,我們還要注意幾點:
-
可以只對部分元素賦初值,未賦初值的元素自動取0值。
int a[3][3] = {{1}, {2}, {3}};
int a[3][3] = {{0, 1}, {0, 0, 2}, {3}};
這句話可以得到下面這兩個數組:
1 0 0
2 0 0
3 0 0
0 1 0
0 0 2
3 0 0
- 如對全部元素賦初值,第一維的長度可以不給出。
例如:
int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
可以寫為:
int a[][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- 數組是一種構造類型的數據
二維數組可以看作是由一維數組的嵌套而構成的。因此,一個二維數組也可以分解為多個一維數組。
如二維數組a[3][4],可分解為三個一維數組,其數組名分別為:
a[0]
a[1]
a[2]
這三個一維數組都有4個元素,例如:一維數組a[0]的元素為a[0][0],a[0][1],a[0][2],a[0][3]。
為什么是這么奇怪的數組名呢,其實是這樣,a[0]中保存的是a[0][0]的地址,那么其實就是a[0][0]~a[0][3]這4個元素組成的一維數組的第一塊空間的地址,那么它就是這個一維數組的數組名。
注意,a[0],a[1],a[2]不能當作下標變量使用,它們是數組名,不是一個單純的下標變量。
我是天花板,讓我們一起在軟件開發中自我迭代。
如有任何問題,歡迎與我聯系。
上一篇:C語言從零開始(十四)-字符串處理
下一篇:C語言從零開始(十六)-指針1