您好,登錄后才能下訂單哦!
本篇內容介紹了“C語言二維數組是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
二維數組的定義
同一維數組一樣,既支持 C89 標準的二維靜態數組,又支持 C99 標準的二維動態數組或變長數組。某些 C 編譯器還沒更新到支持 C99 標準的語法,故可能在一些編譯器中變長數組會報錯。如無特殊說明,教程中所指二維數組,均默認為靜態數組。
靜態二維數組定義的一般格式為:
類型 數組名[第一維大小][第二維大小];
其中,第一、二維的大小一般均為常量表達式。
例如:
int a[4][5];
定義了一個 4 行 5 列的 int 型二維數組 a。
float sc[3][4];
定義了一個 3 行 4 列的 float 型二維數組 sc。
如下二維數組的定義形式均是錯誤的。
int a[][3];//錯誤。編譯器無法確定所需空間int a[2][];//錯誤。缺少列下標,編譯器無法確定所需空間
動態數組例子如下(僅做了解)。
int n=2;int a[n][3];//動態數組,正確的C99語法。但在某些編譯器中可能報錯int a[2][n];//動態數組,正確的C99語法
定義時未初始化的數組,其數據元素的值一般為無意義的隨機值,如:
int a[2][3];//該數組的6個元素均為隨機值
可以把二維數組看成一個特殊的一維數組,它的每個元素又是一個一維數組。例如,定義一個表示 3 個學生 4 門課程成績的二維數組:
int sc[3][4];
定義了一個 3 行 4 列的二維數組 sc,該二維數組可表示 3 個對象(學生),從這個角度看,該二維數組可以看成含 3 個對象(學生)的一維數組,3 個對象(元素)分別為:sc[0]、sc[1]、sc[2],其中 sc 為該一維數組名。
每個對象(元素)sc[i] 又是一個包含 4 個屬性(4 門成績)的一維數組,4 個屬性分別 為:sc[i][0](語文)、sc[i][1](數學)、sc[i][2](外語)、sc[i][3](C 語言)。每一行表示一個學生,每一列表示一門課程,形成如下所示的行列矩陣形式。
語文 數學 外語 c語言
sc[0](第一個學生)-----sc[0][0] sc[0][1] sc[0][2] sc[0][3]
sc[1](第二個學生)-----sc[1][0] sc[1][l] sc[1][2] sc[1][3]
sc[2](第三個學生)-----sc[2][0] sc[2][1] sc[2][2] sc[2][3]
二維數組名 sc 是首對象(第一個學生)sc[0] 的地址,即 sc=&sc[0]。二維數組名加 1 表示跳過一個對象,即 sc+1 為第二個對象(學生)sc[1] 的地址,sc+2 為第三個對象(學生)sc[2] 的地址。
從行列式角度分析,二維數組名即首行的地址,C 語言中的地址一般均是空間首地址。故二維數組名是首行首地址,該數組名加 1 表示跳過一整行,到達第二行的首地址,以此類推。
【例 1】以下二維數組 sc 用于保存 3 個學生的 4 門課程(語數外及 C 語言)成績。根據程序的運行結果,分析二維數組名的含義。
#includeint main (void){ int sc[3][4]; printf("sc=%p\n",sc); printf ("&sc[0]=%p\n",&sc[0]); printf("sc+1=%p\n",sc+1); printf("sc+2=%p\n",sc+2); return 0;}
程序某次運行的結果:
sc=0060FEE0
&sc[0]=0060FEE0
sc+1=0060FEF0
sc+2=0060FF00
程序分析:
1) 本例中定義的二維數組為 3 行 4 列,含 3 個學生對象,對應 3 行,每個學生對象包括 4 個屬性,對應 4 列。
2) 二維數組名 sc 相當于首對象即第一個學生 sc[0] 的地址,即 sc==&sc[0]。輸出地址一般使用格式控制符 %p 或 %x 或 %08x。由某次運行結果可知,sc 和 &sc[0] 的值均為十六進制數 0060FEE0。
由此可得:二維數組名為首對象或首行的地址。
3) 二維數組名加 1 表示跳過一個對象(一行)的空間,為下一個對象(下一行)的地址。即跳過一個對象所有屬性(一行中所有列元素)對應的空間,到達下一個對象(下一行)的起始位置。
而本例中一個對象有 4 個屬性,每個屬性均為整型變量,在 VC++6.0 中占 4 字節,故一個對象(一行)共占 4X4=16 個字節。故 sc、sc+1、sc+2 均相差 16 個字節,轉換為十六進制為 0x10。如運行結果所示。
4) 程序每次運行為某變量空間分配的起始地址可能有差別。
二維數組的引用
二維數組的引用格式為:
數組名[行下標][列下標];
注意引用數組元素時不能加類型,行下標、列下標均從 0 開始。且行下標和列下標的形式可以為常量、變量或表達式。
若 M 和 N 均為已定義的正整數:
int i,j; //i和j分別表示行下標和列下標.int a[M][N]; //定義了一個M行N列的二維整型數組a
行下標i的范圍為 0?M-1。
列下標j的范圍為 0?N-1。
稱第幾個時,習慣上是從第 1 個開始,第 2 個,第 3 個,…,而不從第 0 個開始。但是二維數組的行下標及列下標均是從 0 開始的,為統一起見,本書中對數組元素的引用,采用行列序號來描述,如 a[i][j] 為 i 行 j 列元素,而不說成第 i 行第 j 列元素。例如:
int a[3][4];a[0][0]; //為0行0列元素a[2][1]; //為2行1列元素a[1][1+2]; //為1行3列元素
例如:
int n=4, i, j ;int a[3][4]; //定義了一個3行4列的二維數組a
對該數組的引用形式為 a[i][j],其中,行下標 i 的范圍為 0?2,列下標 j 的范圍為 0?3。以下對該二維數組的引用均是正確的。
a[2][n-1]=a[0][1+1] +a[2][2-1]; //a[0][2]、a[2][1]相加后賦給a[2][3]a[3-1][n-1];//引用2行3列元素
以下對該二維數組的引用形式是錯誤的。
a[-2][1]; //行下標-2越界,應為0?2a[3][2]; //行下標3越界,應為0?2a[2][n]; //列下標n=4越界,應為0?3a[2,3]; //引用形式錯誤,應為a[2][3]a[2][]; //缺少列下標int a[1][n-2]; //引用不能加類型,若為定義,第二維含有變量n,錯誤
【例 2】定義一個 2 行 3 列的二維數組,從鍵盤上輸入 6 個數值,依次給該二維數組的每個元素賦值,按每行三個元素輸出該二維數組及所有元素的和。
程序分析:
例題涉及對二維數組的賦值,一般使用雙重循環,外層循環控制行下標,內層循環控制列下標。二維數組的每個元素 a[i][j] 像普通變量一樣使用,使用 scanf 函數輸入時,一定要加 &。輸入時,可以輸入完 6 個數據后按一次回車鍵。
本題要求每輸出一行后換行,即輸出完一行中的所有列數據(內層循環結束)后換行。
實現代碼:
#includeint main (void){ int a[2][3]; //先定義,后賦值 int i,j,s=0; printf("Input 6 integers:"); for(i=0;i<2;i++) { for (j=0; j<3; j++) { scanf ("%d",&a[i][j]); //勿忘 & s+=a[i][j] ; //與上一條語句不能顛倒 } } for(i=0;i<2;i++) { for (j=0; j<3; j++) printf("%d\t",a[i][j]); //使用\t 的作用 printf ("\n"); //注意該輸出換行符的位置 } printf("s=%d\n", s); return 0;} 運行結果為: Input 6 integers:1 2 3 4 5 6 1 2 3 4 5 6 s=21 二維數組的初始化
二維數組可以先定義,后賦值,在顯式賦值之前,二維數組的各數據元素是隨機值。也可以在定義二維數組的同時,采用初始化列表的形式對其元素賦初值,稱為二維數組的初始化。
二維數組的初始化方式通常有以下幾種。
1) 分行給出初始化數據,且每行的初始化數據個數等于列數。例如:
int a[2][3]={{1,2,3},{4,5,6}};
該初始化列表給出了兩行數據,每一行數據用一對大括號 {} 括起來,一行中的數據及行與行之間均用逗號隔開。這是一種較常用的二維數組的初始化方式。
該初始化語句相當于如下 6 條賦值語句。
a[0][0]=1; a[0][1]=2; a[0][2]=3;a[1][0]=4; a[1][1]=5; a[1][2]=6;
由于初始化列表中明確給出了兩行數據,故定義該數組時,其第一維的大小可省略,編譯器能間接算出該數組的行數為 2,故依然可以確定其空間大小,因此,在對二維數組進行初始化時,其第一維的大小可以省略,即寫成如下形式:
int a[][3]={{l,2,3},{4,5,6}};
注意:第二維的大小一定不能省略!如下初始化均是錯誤的。
int a[2][] = {{l,2,3},{4,5,6}}; //錯誤。不能省略第二維大小int a[][] = {{l,2,3}, {4,5,6}}; //錯誤。不能省略第二維大小int a[][3]; //錯誤。沒有提供初始化列表時,兩維的大小都必須顯式給出int a[2][3] = {{l,2,3},{4,5,6},{7,8,9}}; //錯誤。初始行數多于數組行數
如果把上面一條初始化語句改為省略第一維的大小,便是正確的,即:
int a[][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; //正確。間接得知該數組為三行
2) 分行給出初始化數據,但每行的初始化數據個數少于列數。例如:
int a[2][3]={{l,2},{4}};
該初始化列表給出了兩行數據,第一行給出兩個數據,少一個,對 int 型默認為補 0;第二行僅給出一個數據,少兩個,補兩個 0。所以上述初始化語句相當于:
int a[2][3]={{1,2,0},{4,0,0}};
同理:
int a[][3]={{0},{0}};
相當于:
int a[][3] = {{0,0,0},{0,0,0}}; //2行3列
3) 初始化數據沒有分行,容易產生混亂,不推薦這種方式。
如果初始化數據的個數是列數的整數倍,即:
int a[2][3]={l,2,3,4,5,6};
初始化數據以列數三個為一組,共分為兩組,且每組數據個數恰好等于列數 3,故第一組賦值給第 1 行,第二組賦值給第 2 行。初始化后,數組中各元素為:
1 2 3
4 5 6
例如:
int a[2][3]={1,2,3,4};
由于該二維數組列數為 3,初始化數據以三個為一組,共分為兩組,但第二組僅一個數據,少于列數 3,對 int 型數組用 0 補齊。故第一組數據 1,2,3 賦值給第一行,第二組補齊為三個數據 4,0,0 后,賦值給第二行。相當于 int a[][3]={1,2,3,4,0,0}; 初始化后, 數組中各元素為:
1 2 3
4 0 0
int a[][3] = {1,2,3,4,5,6,7,8}; //正確,可間接得知該數組為三行,不推薦
第三行不夠三個數據,用 0 補齊。故該語句相當于:
int 3[][3] = {1,2,3,4,5,6,7,8,0};
初始化后,數組中各元素為:
1 2 3
4 5 6
7 8 0
如果第一維大小沒有省略,則初始化數據的個數一定不能超過數組元素的總個數,否則報錯。例如:
int a[2][3] = {1,2,3,4,5,6,7,8};//錯誤。初始數據個數8多于數組總個數6
二維數組的存儲
二維數組在邏輯(表現形式)上可理解為矩陣形式(分行分列),但其物理存儲形式卻是連續的,即存完第一行,在其后面接著存儲第二行,第三行,…,如無特殊說明,本書中涉及對二維數組的表述一般指的是其邏輯形式即矩陣形式。
二維教組的應用舉例
【例 3】一個班級有 N 名學生,每個學生有 4 門課程(語文、數學、外語、C 語言),計算每個學生的平均分。編寫程序實現該功能需求。
問題分析:該問題可把每個學生當成一個對象,而每個對象(學生)有 5 個屬性:4 門課程成績及平均分。故該問題可使用二維數組來處理數據,該二維數組含有 N 個對象,故第一維的大小為 N,每個對象有 5 個屬性,故第二維的大小為 5。為便于驗證,本例中學生個數 N 設為 3 個。
實現代碼:
#include#define N 3int main (void){ float a[N][5],sum; //sum用來累加每個學生4門課的總成績 int i, j ; printf ("輸入%d個學生信息(語、數、外、C語言成績):\n",N); for(i=0;i
運行結果為:
輸入3個學生信息(語、數、外、C語言成績):
NO1:82 91 88 93
NO2:83 84 80 91
NO3:73 79 86 81
學號 語文 數學 外語 C語言 平均成績
NO1: 82.0 91.0 88.0 93.0 88.5
NO2: 83.0 84.0 80.0 91.0 84.5
NO3: 73.0 79.0 86.0 81.0 79.8
“C語言二維數組是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。