謹記
每個人心中都有一片海袜硫,自己不揚帆氯葬,沒人幫您啟航,久了就是一片死海婉陷。人生帚称,就是一場自己與自己的較量:讓積極打敗消極,讓快樂打敗憂郁秽澳,讓勤奮打敗懶惰闯睹,讓堅強打敗脆弱。在每一個充滿希望的清晨担神,告訴自己:努力楼吃,就總能遇見更好的自己。
今天這篇文章將為讀者介紹C語言中一個非常重要的知識點————數(shù)組妄讯,相信的知識已經(jīng)不能滿足我們實際開發(fā)的需要孩锡,所以,為了開發(fā)更快捷亥贸、更方便躬窜,那么今天開始我們就走進C語言的重點知識點。
通過本篇文章炕置,你將學到如下知識點:
- 一維數(shù)組的概念
- 一維數(shù)組的定義方式
- 一維數(shù)組的內(nèi)存分配
- 一維數(shù)組的排序
- 二維數(shù)組的介紹
- 二維數(shù)組的初始化
- 二維數(shù)組的深入
一荣挨、一維數(shù)組
1、數(shù)組的定義
數(shù)組就是具有一定順序關系的若干變量的一個集合朴摊,我們簡稱數(shù)組默垄,其中每一個變量我們稱為數(shù)組的元素,數(shù)組的幾個關鍵點:
- 1甚纲、組成數(shù)組的元素都是互不相干的獨立的變量
- 2厕倍、這些變量(數(shù)組元素)的數(shù)據(jù)類型必須是相同的
- 3、變量之間有一定的順序關系贩疙。
例如:int [10]讹弯;
在前面的文章中已經(jīng)提到過况既,數(shù)組是C語言的構造數(shù)據(jù)類型,一個數(shù)組可以分解成多個數(shù)組元素组民,這些數(shù)組元素可以是基本數(shù)據(jù)類型或者構造數(shù)據(jù)類型棒仍,因此,如果按照數(shù)組元素的類型來進行一個劃分臭胜,那么數(shù)組可以分為數(shù)值數(shù)組莫其、字符數(shù)組、指針數(shù)組耸三、結構體數(shù)組等乱陡。
在C語言中,如果程序員要想使用數(shù)組仪壮,那么首先必須的去定義憨颠。數(shù)組的代表就是一維數(shù)組。
一維數(shù)組就是只有一個下標的數(shù)組积锅,我們稱為一維數(shù)組爽彤。定義格式:
<存儲類型> <數(shù)據(jù)類型> <數(shù)組名>[<常量表達式>]
存儲類型指的是auto, register, static, extern。若省略缚陷,相當于auto适篙。
數(shù)據(jù)類型可以是任一種基本數(shù)據(jù)類型或構造數(shù)據(jù)類型。
數(shù)組名是用戶定義的數(shù)組標識符箫爷。
方括號中的常量表達式表示數(shù)據(jù)元素的個數(shù)嚷节,也稱為數(shù)組的長度。
對于數(shù)組的定義虎锚,需要注意一下幾點:
- 1丹喻、數(shù)組的數(shù)據(jù)類型,其實就是指的數(shù)組元素的取值數(shù)據(jù)類型翁都,對于同一個數(shù)組碍论,數(shù)組元素的數(shù)據(jù)類型都是一樣的。
- 2柄慰、數(shù)組名應當符合標識符的命名規(guī)定鳍悠,即由字母、數(shù)字和下劃線組成坐搔,但不能以數(shù)字開頭藏研。
- 3、在同一作用域中概行,數(shù)組名不能和其他變量的名稱一樣蠢挡,
- 4、方括號中常量表達式表示數(shù)組元素的個數(shù),如a[6]表示數(shù)組a有6個元素业踏,它需要在數(shù)組定義時就確定下來禽炬,不能隨著程序的運行動態(tài)更改。它的下標從0開始計算勤家,因此6個元素分別為a[0]腹尖、a[1]、a[2]伐脖、a[3]热幔、a[4]、a[5]讼庇。
- 5绎巨、不能用變量來表示數(shù)組的長度,只能是常量表達式或者常量
- 6蠕啄、允許多個相同數(shù)據(jù)類型的數(shù)組和變量聲明和定義场勤。
int num[3];//定義了一個名稱叫做num的數(shù)組,數(shù)組中可以存儲3個int類型的數(shù)據(jù)
// num = 15;//會報錯介汹,系統(tǒng)不知道應該給誰賦值
// 只要定義一個C語言的數(shù)組, 系統(tǒng)就自動會給數(shù)組中的每一塊小得存儲空間一個編號
//這個編號從0開始,依次遞增
//數(shù)組中系統(tǒng)自動綁定的編號舶沛,我們稱為索引
num[0] = 10;
num[1] = 12;
num[2] = 20;
注意點:C語言中規(guī)定了數(shù)組必須逐個元素引用嘹承,而不能整體引用。數(shù)組的引用實際上就是數(shù)組元素的引用如庭。數(shù)組元素的一般表示方法為: 數(shù)組名[下標]
若數(shù)組在定義時指定有n個元素叹卷,則數(shù)組的下標范圍為0~(n-1)。如果數(shù)組的下標越界坪它,則有可能導致以下幾種結果:
① 若越界訪問的內(nèi)存空間是空閑的骤竹,程序可能不受影響,仍能正確運行往毡。
② 若越界訪問的空間已經(jīng)被占用蒙揣,且寫了很重要的數(shù)據(jù)。在這種情況下开瞭,若程序執(zhí)行了非法寫操作懒震,則程序可能會異常終止或崩潰。
③ 若越界訪問的空間是空閑的嗤详,程序只是進行了讀操作个扰,則程序能繼續(xù)運行,但無法得出正確的結果葱色。
④ 其他情況递宅。
2、一維數(shù)組的初始化
一維數(shù)組初始化嚴格上來說有7種。
1办龄、局部數(shù)組初始化
對于普通局部數(shù)組烘绽,若定義時,沒有初始化土榴,則數(shù)組中元素的值诀姚,是不確定的。
2玷禽、static數(shù)組不初始化
對于static修飾的數(shù)組赫段,若定義時,沒有初始化矢赁,則數(shù)組中元素的值默認為0
3糯笙、全局數(shù)組不初始化
對于全局數(shù)組,若定義時撩银,沒有初始化给涕,則數(shù)組中元素的值默認也為0。
4额获、全部初始化
與變量在定義時初始化一樣够庙,數(shù)組也可以在定義時進行初始化,如對整型數(shù)組進行初始化抄邀。
int a[10]={1, 2, 9, 21, 8, 10, 7, 24, 0, 20};
此處還是要注意耘眨,數(shù)組只能通過下標逐個引用元素。定義數(shù)組時境肾,對數(shù)組元素的初始化剔难,只能寫成一行,不能換行寫奥喻。
5偶宫、部分初始化:數(shù)組在定義時可以對其中的部分數(shù)據(jù)進行初始化。當“{}”中值的個數(shù)少于元素個數(shù)時环鲤,只給前面部分元素賦值纯趋。例如,如下定義就是對數(shù)組的前5個數(shù)據(jù)初始化冷离,而后5個數(shù)據(jù)自動賦0结闸。
比如:int a[10] = {1,2,3,5} 前面4個有數(shù)據(jù)初始化,后面6個數(shù)據(jù)會自動賦0
6酒朵、數(shù)組全部賦值
若想要對數(shù)組中的元素全部賦值桦锄,則可以省略數(shù)組下標中的常量。編譯器會根據(jù)初始化列表自動計算數(shù)組元素的個數(shù)蔫耽,如下所示结耀。
int a[]={1, 2, 5, 23, 8, 10, 7, 24, 0, 22};
7留夜、數(shù)組全部初始化為0
特殊寫法: int a[10] = {0};
當然給數(shù)組清零,還有其他寫法图甜,比如可以使用庫函數(shù)memset碍粥,把數(shù)組用0來填充,需要引入頭文件string.h黑毅。
int main(int argc, const char * argv[]) {
int a[10];
memset(a, 0, sizeof(a));
return 0;
}
可以使用庫函數(shù)bzero嚼摩,把數(shù)組清0,需要引入頭文件strings.h矿瘦。
int main(int argc, const char * argv[]) {
int a[10];
bzero(a, sizeof(a));
return 0;
}
3枕面、一維數(shù)組內(nèi)存分配
在內(nèi)存中,數(shù)組中的元素占用連續(xù)的存儲空間缚去,并且根據(jù)每個元素所占存儲空間來進行內(nèi)存分配潮秘。數(shù)組名代表數(shù)組的起始地址,是地址常量易结,對數(shù)組名求sizeof()枕荞,可以得出數(shù)組在內(nèi)存空間中所占用的總空間。類似的道理搞动,可以很容易利用下面的表達式來計算出數(shù)組的元素個數(shù):
數(shù)組的元素個數(shù) = sizeof(數(shù)組名) / sizeof(數(shù)據(jù)類型)
#include <stdio.h>
int main(int argc, const char * argv[]) {
//定義一個5個元素的數(shù)組
int a[5] = {1,2,3,4,5};
int sizea = sizeof(a);//求數(shù)組所占用的空間大小
printf("%d\n",sizea);
printf("%p\n",a);
printf("數(shù)組起始地址%p\n",&a[0]);
int n = sizeof(a) / sizeof(int);//求數(shù)組元素個數(shù)
for (int i = 0; i < n; i++) {
printf("a[%d]的地址%p\n",i,&a[i]);
}
return 0;
}
運行結果:
20
0x7fff5fbff830
數(shù)組起始地址0x7fff5fbff830
a[0]的地址0x7fff5fbff830
a[1]的地址0x7fff5fbff834
a[2]的地址0x7fff5fbff838
a[3]的地址0x7fff5fbff83c
a[4]的地址0x7fff5fbff840
Program ended with exit code: 0
通過上面的程序例子躏精,我們可以看出,對數(shù)組名求地址鹦肿,其實就是數(shù)組的第一個元素的地址矗烛,所以我們可以變像的說數(shù)組名就是一個指針,只不過是一個靜態(tài)的指針狮惜,一個數(shù)組內(nèi)存空間是連續(xù)的高诺,從運行結果也可以看出來碌识。
4碾篡、數(shù)組的排序
A、冒泡排序法
對于冒泡排序法筏餐,過程如下:
(1)比較第一個數(shù)與第二個數(shù)开泽,若為逆序a[0]>a[1],則交換魁瞪;然后比較第二個數(shù)與第三個數(shù)穆律;依次類推,直至第n-1個數(shù)和第n個數(shù)比較為止——第一趟冒泡排序导俘,最終峦耘,最大的數(shù)被安置在最后一個元素位置上。
(2)對前n-1個數(shù)進行第二趟冒泡排序旅薄,最終辅髓,使次大的數(shù)被安置在第n-1個元素位置。
(3)重復上述過程,共經(jīng)過n-1次冒泡排序后洛口,排序結束矫付。
(省略了頭文件和主函數(shù),直接展示的核心代碼)
//任意輸入10個元素的數(shù)組排序
第一種:
int a[N], i, j, k;
for (i = 0; i < N; i++) {
scanf("%d",&a[i]);
}
for (i = 0; i < N - 1; i++) {
for (j = 0; j < N - 1 - i; j++) {
if (a[j] > a[j+1]) {
k = a[j];
a[j] = a[j+1];
a[j+1] = k;
}
}
}
printf("\n");
for (i = 0; i < N; i++) {
printf("%5d", a[i]);
}
第二種:
//利用sizeof
int a[] = {1,23,45,6,58,29},i,j,k,n;
n = sizeof(a) / sizeof(a[0]);
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - 1 - i; j++) {
if (a[j] > a[j+1]) {
k = a[j];
a[j] = a[j+1];
a[j+1] = k;
}
}
}
for (i = 0; i < n; i++) {
printf("%d\n",a[i]);
}
第三種第焰,循環(huán)剝離
int a[] = {1,23,45,6,58,29},i,j,k,n,index;
n = sizeof(a) / sizeof(a[0]);
for (i = 0; i < n - 1; i++) {
index = 0;
for (j = 0; j < n - 1 - i; j++) {
if (a[index] < a[j+1]) {
index = j+1;//下標替換
}
}
k = a[index];//賦值
a[index] = a[n - 1 -i];
a[n - 1 -i] = k;
}
for (i = 0; i < n; i++) {
printf("%d\n",a[i]);
}
B买优、選擇排序法
選擇排序的排序過程如下。
(1)首先通過n-1次比較挺举,從n個數(shù)中找出最小的杀赢, 將它與第一個數(shù)交換——第一次選擇排序,結果最小的數(shù)被安置在第一個元素位置上豹悬。
(2)再通過n-2次比較葵陵,從剩余的n-1個數(shù)中找出關鍵字次小的記錄,將它與第二個數(shù)交換——第二次選擇排序瞻佛。
(3)重復上述過程脱篙,共經(jīng)過n-1次排序后,排序結束伤柄。
(省略了頭文件和主函數(shù)體)
int a[N], i, j, r, t;//定義數(shù)組和變量
printf("Please input %d numbers\n",N);
for (i = 0; i < N; i++)//進行循環(huán)輸入數(shù)組元素
scanf("%d",&a[i]);
for (i = 0; i < N-1; i++)//循環(huán)變量
{
r = i;
for (j = i+1; j < N; j++)
if (a[j] < a[r])
r = j;
if(r != i)//判斷
{
t = a[r];
a[r] = a[i];
a[i] = t;
}
}
printf ("the array after sort:\n");
for (i = 0; i < N; i++)//打印
printf ("%5d",a[i]);
printf ("\n");
多維數(shù)組(二維數(shù)組)
1绊困、多維數(shù)組定義
前面提到一維數(shù)組只有一個下標。那么具有兩個或兩個以上下標的數(shù)組适刀,就稱為多維數(shù)組秤朗。多維數(shù)組元素有多個下標,以標識它在數(shù)組中的位置笔喉。多維數(shù)組的說明與一維數(shù)組的說明基本類似取视,其說明的一般形式如下:
<存儲類型><數(shù)據(jù)類型><數(shù)組名><常量表達式1><常量表達式2>…<常量表達式n>
可以看出,多維數(shù)組與一維數(shù)組的說明相比常挚,只是增加了多個下標作谭,其他特性基本與一維數(shù)組相同。例如:int b[2][3][4]奄毡。
在這里重點介紹二維數(shù)組折欠,多維數(shù)組的用法可由二維數(shù)組類推而得到。
2吼过、二維數(shù)組
二維數(shù)組定義的一般形式是:
<存儲類型><數(shù)據(jù)類型><數(shù)組名>[常量表達式1][常量表達式2]
其中常量表達式1表示第一維下標的長度锐秦,即行數(shù),常量表達式2 表示第二維下標的長度盗忱,即列數(shù)酱床。例如:int a[2][3]。
說明了一個二行三列的數(shù)組趟佃,數(shù)組名為a扇谣,其下標變量的類型為整型慷垮。該數(shù)組的下標變量共有2×3個,即:
a[0][0],a[0][1],a[0][2]
a[1][0],a[1][1],a[1][2]
3揍堕、二維數(shù)組的初始化
==============二維數(shù)組============
格式:<存儲類型><數(shù)據(jù)類型><數(shù)組名>[常量表達式1][常量表達式2]
其中常量表達式1表示第一維下標的長度料身,即行數(shù),常量表達式2表示第二維下標的長度衩茸。即列數(shù)
初始化
① 降維給二維數(shù)組賦初值芹血,即按行初始化。每一組的初始值都用{ }括起來楞慈。
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
//按降維給a數(shù)組元素全部初始化
int a[3][3] = {{1}, {4}};
//只初始化了部分數(shù)組元素幔烛,其他元素為0。第一行為1 0 0,第二行為4 0 0
② 按線性存儲的形式給二維數(shù)組賦初值囊蓝。
int a[2][3] = {1, 2, 3, 4, 5, 6};
//按線性存儲形式給二維數(shù)組全部初始化
int a[3][3] = {1, 2 };
//只初始化了部分數(shù)組元素饿悬,其他元素為0。第一行為1 0 0,第二行為2 0 0聚霜,第三行為0 0 0狡恬。
③ 可以省略左邊下標范圍的方式,給二維數(shù)組賦初值蝎宇。
int a[][3] = {{1, 2, 3}, {4, 5, 6}};
//省略左邊下標范圍弟劲,給數(shù)組所有元素初始化
特別要注意的是,第一維的長度可以省略姥芥,但是兔乞,第二維的長度不能省,比如下面的寫法:
int a[2][] = {{1, 2, 3}, {4, 5, 6}};
編譯程序時凉唐,會有語法錯誤庸追。
error: array type has incomplete element type
結論:二維數(shù)組第二維的長度不能省略。
// int a[2][] = {{1,2,3},{4,5,6}};//報錯
4台囱、二維數(shù)組內(nèi)存分配
二維數(shù)組在概念上是二維的淡溯,也就是說其下標在兩個方向上變化,有行和列的說法玄坦。下標變量在數(shù)組中的位置也處于一個平面之中血筑,而不是象一維數(shù)組只是一個向量绘沉。但是內(nèi)存卻是連續(xù)編址的煎楣,是按一維線性排列的。如何在一維存儲器中存放二維數(shù)組车伞,
在C語言中择懂,二維數(shù)組采取了和一維數(shù)組類似的存儲方式,按行優(yōu)先存另玖,存儲了第一行的元素困曙,即存第二行的表伦,依次類推。
int main(int argc, const char * argv[]) {
int a[2][3] = {{8, 2, 6}, {1, 7, 9}}, i, j;;
for (i = 0; i < 2; i++)
for (j = 0; j < 3; j++)
printf ("%d ", a[i][j]);
printf ("\n");
for (i = 0; i < 2; i++)
for (j = 0; j < 3; j++)
printf ("%p ", &a[i][j]);
printf ("\n");
return 0;
}
運行結果:
8 2 6 1 7 9
0x7fff5fbff810
0x7fff5fbff814
0x7fff5fbff818
0x7fff5fbff81c
0x7fff5fbff820
0x7fff5fbff824
Program ended with exit code: 0
深入理解二維數(shù)組慷丽,在數(shù)組定義形式你可以知道蹦哼,其實一個二維數(shù)組只是比一維數(shù)組多了一個下標,那么要糊,從內(nèi)存分配的角度上來看的話纲熏,我們可以把一個二維數(shù)組看作是有很多個一維數(shù)組構成。例如:int a[3][4]锄俄【志ⅲ可以理解成二維數(shù)組含有三個元素:a[0],a[1]奶赠,a[2]鱼填。每個元素a[i]由包含四個元素的一維數(shù)組組成。舉一個程序代碼例子
#include <stdio.h>
#define DEBUG 0
int main(int argc, const char * argv[]) {
/*
我們也可以把二維數(shù)組毅戈,看成由多個一維數(shù)組組成苹丸。例如:int a[3][4]∥可以理解成二維數(shù)組含有三個元素:a[0]谈跛,a[1],a[2]塑陵。每個元素a[i]由包含四個元素的一維數(shù)組組成感憾。
*/
int a[3][4] = {{8, 2, 6, 4}, {1, 4, 7, 9}};
//預編譯指令
#if DEBUG
a++;
a[0]++;
a[1]++;
a[2]++;
a[3]++;
#endif
printf("a :%p a+1 :%p\n\n", a, a+1);
printf("a[0]:%p a[0]+1:%p &a[0][1]=%p\n", a[0], a[0]+1, &a[0][1]);
printf("a[1]:%p a[1]+1:%p &a[1][1]=%p\n", a[1], a[1]+1, &a[1][1]);
printf("a[2]:%p a[2]+1:%p &a[2][1]=%p\n", a[2], a[2]+1, &a[2][1]);
printf("a[3]:%p a[3]+1:%p &a[3][1]=%p\n", a[3], a[3]+1, &a[3][1]);
//有一個3×4的矩陣,要求輸出其中值最大的元素的值令花,以及它的行號和列號
int max, i, j, r = 0, c = 0;
int b[3][4] ={{24, 89, 2, 41}, {3, 11, 9, 1}};
max = b[0][0];
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
if (b[i][j] > max)
{
max = b[i][j];
r = i;
c = j;
}
printf("Max=%d, row=%d, column=%d\n", max, r, c);
return 0;
}
運行結果:
a :0x7fff5fbff7e0 a+1 :0x7fff5fbff7f0
a[0]:0x7fff5fbff7e0 a[0]+1:0x7fff5fbff7e4 &a[0][1]=0x7fff5fbff7e4
a[1]:0x7fff5fbff7f0 a[1]+1:0x7fff5fbff7f4 &a[1][1]=0x7fff5fbff7f4
a[2]:0x7fff5fbff800 a[2]+1:0x7fff5fbff804 &a[2][1]=0x7fff5fbff804
a[3]:0x7fff5fbff810 a[3]+1:0x7fff5fbff814 &a[3][1]=0x7fff5fbff814
Max=89, row=0, column=1
Program ended with exit code: 0
通過運行結果我們可以得出結論:
1阻桅、 a是二維數(shù)組名,是地址常量兼都。
2嫂沉、 a[0],a[1]扮碧, a[2]趟章, a[3]實際上都是一維數(shù)組名,代表一維數(shù)組的起始地址慎王,也都是地址常量蚓土。
3、 a+1和a的地址差16個字節(jié)赖淤,相當于4個數(shù)組元素蜀漆。因此,可以看出a代表第1行的地址咱旱,a+1代表第2行的地址确丢。
4绷耍、 a[0]+1和a[0]的地址差4個字節(jié),相當于1個數(shù)組元素鲜侥。因此褂始,a[0]+1相當于元素&a[0][1], a[1]+1相當于元素&a[1][1]描函,a[2]+1相當于元素&a[2][1]病袄。
如果讀者還想繼續(xù)深入研究二維數(shù)組,可以自行查閱一些相關資料赘阀,當然益缠,后面的文字中,我也會單獨的講解基公。
總結
希望讀者認真學習幅慌,一步一個腳印,踏踏實實的把基礎落實好轰豆。這篇文章主要介紹了C語言的構造數(shù)據(jù)類型數(shù)組胰伍,重點掌握一維數(shù)組,了解和熟悉二維數(shù)組酸休,望讀者掌握好骂租。
結尾
最后,希望讀者在讀文章的時候發(fā)現(xiàn)有錯誤或者不好的地方斑司,歡迎留言渗饮,我會及時更改,感謝你的閱讀和評論已經(jīng)點贊收藏宿刮。