學數組,這一篇就夠了

“傷害人的並非事件本身,而是他對事件的看法。” 戴爾·卡耐基—《人性的弱點》

今日,我們請來了一位老大,別看他只是個人,他能裝的東西比你還要多呢。
在這裏插入圖片描述

這位老大叫什麼呢,等一下再說啊,老大的名字可不是能隨便亂說的

老大的簡介:

(array)是按順序儲存的一系列相同的值,可以是10個char類型的字符或15個int類型的值。沒錯,這位老大便是數組。這位老大還是有許多小弟的,這些小弟姓什麼呢,有個專門的名字叫元素。沒錯,整個數組有一個數組名,通過整數下標訪問數組中單獨的項或元素(element)。

如何定義數組呢:

**

int name[10];//說明可存儲10個int類型整數的數組
char name[10];//說明可存儲10個字符的數組

**

老大介紹得差不多了,那麼接下來便是介紹小弟(數組裏的元素)了。小弟可是很厲害的呢,它可以是任意數據類型哦。

我們將用於識別數組元素的數字稱爲下標(subscript),索引(indice),或偏移量(offset)。需要注意的是下標必須是整數哦,下標中的整數也代表了數組中有多少元素,而且要從0開始計數。下標也是存在陷阱的,因爲怕影響到執行的速度,C編譯器是不會檢查數組的下標是否正確的哦。而且數組的元素是被依次存在內存中相鄰的位置。

**

int name[10];//元素爲name[0]~name[9]
name[10]=55;//這個便是錯的,該數組元素不存在

**

注意:每個int爲2字節,char爲1字節。順便擴展一下位、字,字節與KB的關係:

KB 1KB=1024B

MB 1MB=1024KB

GB 1GB=1024MB

TB 1TB=1024GB

int類型數組元素的用法和int類型變量的用法類似,比如要讀取int類型變量name,應該這樣寫

**

scanf("%d",&name);//讀取變量
scanf("%d",&name[n]);//讀取數組

**

昨天我們運用了許多的for循環,就有小夥伴跟我說那麼多for可以獨立出來寫麼,獨立的for循環我個人不建議。將for循環合併成一個循環可以使程序顯得更加緊湊,但我們也要遵循模塊化的原理。模塊化主要是把程序劃分爲一些獨立的單元,每個單元執行一個任務,這樣也能提高程序的可讀性。更重要的是模塊化使程序的不同部分彼此獨立,方便以後對程序的修改。

當我們定義數組後,該如何賦值呢:

**

int name[5]={1,2,3,4,5};
int name[5]={1,2,3,4};

**

我們認真看就會發現第一行和第二行的差別,第一行將5個值賦給了name,而第二行卻只有4個數值,那麼還差一個怎麼辦呢?不用怕,編譯器會爲它補上0的,但也只能補0哦。

接下來我們就來更加詳細的介紹數組:

初始化數組

數組通常被用來存儲程序需要的數據。比如一個內含12個整數元素的數組就可以存儲12個月的天數。在這種情況下,在程序一開始就初始化數組比較好。大家知道什麼是標量變量麼,簡單說就是隻存儲單個值的變量。接下來我們來初始化這種變量:

**

float flax=PI*2;/*PI已定義爲宏*/
初始化數組:
int main()
{int name[5]={1,2,3,4,5};
...}

**

如上所示,我們用以逗號分隔的值列表(用花括號括起來的)來初始化數組,各值之間用逗號分隔,在逗號和值之間可以有空格。上面的初始化是把1賦值給數組的首元素(即name[0])。
下面給大家展示一個簡單的程序:

**

#include<stdio.h>
int main()
{ const int days[]={31,28,31,30,31,30,31,31,30,31};
int index;
for(index=0;index<sizeof day/sizeof days[0];index++)
printf("Month %2d has %d days.\n",index+1,days[index]);
return 0;
}

**

運行結果如圖:

在這裏插入圖片描述

這裏需要注意如下幾點:

NO.1我們在上面初始化數組時是省略了方括號中的數字,編譯器會根據初始化列表中的項數來確定數組的大小。

NO.2 Sizeof運算符給了它運算對象的大小(以字節爲單位)。使用Sizeof days 是整個數組的大小,Sizeof day[0]是數組中元素的大小。整個數組的大小除以單個元素的大小就是數組元素的個數。

指定初始化器

C99多了一個新特性:指定初始化器。利用該特性可以初始化指定的數組元素。

例如可以在初始化列表中使用帶方括號的下標指明待初始化的元素:

int shu[6]={[5]=55};//把shu[5]初始化爲55

一般來說,在初始化一個元素後,沒有被初始化的元素都會被設置爲0。以下面程序爲例:

**

#include<stdio.h>
#define months 12
int main ()
{ int days[months]={31,28,[4]=31,30,31,[1]=29};
int i;
for(i=0;i<months;i++)
{printf("%2d %d\n",i+1,days[i]);}
return 0;
}

**

運行如下:
在這裏插入圖片描述

該程序需要注意以下幾點(需要多多思考哦):

NO.1 如果指定初始化器後面有更多的值,如該例中的初始化列表中的片段:[4]=31,30,31,那麼後面這些值將被用於初始化爲30和31.

NO.2 如果再次初始化指定的元素,那麼最後的初始化將會取代之前的初始化。比如上面的程序中初始化列表開始時把days[1]初始化爲28,,但是days[1]又被後面的指定初始化[1]=29初始化爲29.

NO.3 說到如果沒有指定元素大小會怎樣呢?如下:

**

int shu[]={1,[6]=2};//該數組有7個元素
int shu[]={1,[6]=2,3};//該數組有8個元素

**

即:編譯器會把數組的大小設置爲足夠裝得下初始化的值。

數組邊界

我們在使用數組時,要防止數組下標越過邊界。簡單來說就是確保下標是有效的值。比如:

int you[20];
在使用該數組時,就需要注意在程序中使用的數組下標在0~19的範圍內,況且編譯器不會檢查出這種錯誤。前面也說到過。

因此,使用越界的數組下標會導致程序改變其他變量的值。不同的編譯器運行該程序的結果可能也會不同哦,有的甚至會導致程序異常中止。

還要記住一點就是數組元素的編號是從0開始的哦,最好是在聲明數組時使用符號常量來表示數組的大小。

數組下標

C99標準允許了一種新型的聲明方式:

int a1[n];//c99之前是不允許這樣的哦
這創建了一種新型數組,稱爲變長數組。簡稱VLA(C11放棄了這一舉措,把VLA設定爲可選,而不是語言必備的特性)

C99引入變長數組主要是爲了讓C成爲更好的數值計算語言。

注意:變長數組是指用整型變量或表達式聲明或定義的數組,而不是說數組的長度會隨時變化,變長數組在其生存期內的長度同樣是固定的。

多維數組

上面把數組介紹得差不多了,那麼下面就開始介紹二維和多維數組。我們可以把一維數組想象成一行數據,把二維數組想象成數據表,把三維數組想象成一疊數據表。

現在用一個項目來講解二維數組:

如果有一個氣象員想要收集5年內每個月的降水量數據,那麼他要如何表示數據呢?一個方案是創建60個變量,每個變量存儲一個數據項,顯然這個方法太麻煩。那麼我們就可以用到二維數組來解決,即創建一個主數組,主數組含有5個元素,每個元素是內含12個元素的數組(每個元素表示一個月)。

聲明數組如下:

float rain[5][12];
//內含5個數組元素的數組,每個數組元素內含12個float類型的元素
float rain[5][12]  //顏色部分是指rain是一個內含5個元素的數組;非顏色部分則是指一個含有12個float類型元素的數組。

這說明每個元素的類型都是float[12],簡單說也就是rain的每個元素本身都是一個內含12個float類型值的數組。那麼rain[0]是一個數組,它的首元素就是rain[0][0],第二個便是rain[0][1],以此類推。

該項目代碼如下:

#include<stdio.h>
#define months 12//12個月
#define years 5//年數
int main()
{const float rain[years][months]={
{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
{4.1,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
};//初始化時可省略內部的花括號,只要保證初始化的數值個數正確
int year,month;
float subtot,total;
printf("year    rainfall   (inches)\n");
for (year=0,total=0;year<years;year++)//每一年,各月的降水量總和
{ for(month=0,subtot=0;month<months;month++)
subtot+=rain[year][month];
printf("%5d %15.1f\n",2015+year,subtot);
total+=subtot;} //5年的總降水量
printf("\nThe yearly average is %.1f inches.\n\n",total/years);
printf("monthly averages:\n\n");
printf("Jan Feb Mar Apr May Jun Jul Aug Sep Oct");
printf("Nov Dec\n");
for(month=0;month<months;month++){
for(year=0,subtot=0;year<years;year++)
subtot+=rain[year][month];
printf("%4.1f",subtot/years);
}
printf("\n");
return 0;
}

運行結果如下:

在這裏插入圖片描述

此程序計算了每年的總降水量,年平均降水量和月平均降水量。

該程序使用了兩個嵌套for循環,第一個是嵌套for循環的內層循環,在year不變的情況下,遍歷month計算某年的總降水量;外層循環則改變year的值,重複遍歷month,計算五年的總降水量。

這裏我們可以看到處理二維數組需要處理用到2重嵌套循環,通常來說,處理三維數組需要用到3重嵌套循環,四維則需要用到4重嵌套循環。

我們說的二維數組的許多相關內容都適用於三維或者多維數組。比如聲明一個三維數組如下:

int name [3][3][3];

最後的話

相信你學到這裏或多或少都對數組有了一定的瞭解,想要更好的理解數組,建議多看幾遍哦。這也是經過多次閱讀書籍從而整理出來數組裏最重要的一些知識點。希望大家看完這篇文章後對數組有更好的瞭解。

公衆號:程序員Bob
一個正在學習的大學生,歡迎關注和我一起交流哦!
點贊關注~謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章