C初階2:數(shù)組

1. 初始化

1.1 整體初始化

試一下下面三段代碼,分析輸出。

  • 代碼一
int arr[12];
for(int i=0;i<12;++i){
    printf("%d ",arr[i]);
}
  • 代碼二
int arr[12] = {0};
for(int i=0;i<12;++i){
    printf("%d ",arr[i]);
}
  • 代碼三
int arr[12] = {2};
for(int i=0;i<12;++i){
    printf("%d ",arr[i]);
}

結(jié)論:

  1. 數(shù)組未初始化,數(shù)組里面的值都是隨機值。
  2. 數(shù)組初始化為{0},數(shù)組里面的值都是0。
  3. 數(shù)組初始化為{非零值},數(shù)組里面第一個值是非零值,其他的值都是0

1.2 部分初始化

試一下代碼,分析輸出。

int arr[12] = {[2]=2,[5]=5};
for(int i=0;i<12;++i){
    printf("%d ",arr[i]);
}

指定下標(biāo)的值被賦值,其他的值都是0。這是C99語法。

1.3 大小

試一下,下面代碼分析結(jié)果。

char carr[12];
int iarr[12];
double farr[12];
printf("carr = %d\n",sizeof(carr));
printf("iarr = %d\n",sizeof(iarr));
printf("farr = %d\n",sizeof(farr));

sizeof給出整個數(shù)組所占據(jù)的內(nèi)容的大小。數(shù)組大小=元素大小*數(shù)組個數(shù)。

問題:已知數(shù)組arr,如何求出數(shù)組元素個數(shù)?

1.4 賦值

試一下下面的代碼

int days[]={31,28,31,30,31,30,31,31,30,31,30,31};
int arr = days;

2. 數(shù)組與指針

2.1 數(shù)組名是地址

數(shù)組名是數(shù)組第一個元素的地址。

int arr[] = {1,2,3,4,5,6,7,8};
printf("&arr=%p\n",&arr);
printf("arr=%p\n",arr);
printf("&arr[0]=%p\n",&arr[0]);

數(shù)組下標(biāo)實現(xiàn)的操作指針也可以實現(xiàn)。數(shù)組名+下標(biāo)表示下標(biāo)i元素的地址。

No. 操作 下標(biāo) 指針
1 i個元素值 arr[i] *(arr+i)
2 i個元素地址 &arr[i] arr+i

所以,遍歷數(shù)組可以是

int arr[] = {1,2,3,4,5,6,7,8};
for(int i=0;i<8;++i){
    printf("%d\n",*(arr+i)); 
}

數(shù)組名是不可改變的。

int arr1[] = {1,2,3,4,5,6,7,8};
int arr2[] = {1,2,3,4,5,6,7,8};
arr2 = arr1

數(shù)組下標(biāo)比較易于理解,數(shù)組指針更靈活更高效。
要點

  1. 數(shù)組名是數(shù)組第一個元素的地址。
  2. 數(shù)組名+下標(biāo)表示下標(biāo)i元素的地址。
  3. 數(shù)組名是不可改變的。

2.2 數(shù)組名放入指針

地址存儲在指針中??梢杂弥羔槻僮鞯刂?。

int arr[] = {1,2,3,4,5,6,7,8};
int* p = arr;
for(int i=0;i<8;++i){
    printf("%d\n",*(p+i)); 
}

3. 函數(shù)與數(shù)組

3.1 傳遞數(shù)組給函數(shù)

數(shù)組作為函數(shù)參數(shù)時,通常必須再用一個參數(shù)傳入數(shù)組大小。

返回值類型 函數(shù)名(類型 參數(shù)名[],int size){

}

或者

返回值類型 函數(shù)名(類型* 參數(shù)名,int size){

}

例如:打印數(shù)組元素

#include <stdio.h>

void PrintArr1(int arr[],int n){
    for(int i=0;i<n;++i){
        printf("%d ",arr[i]);
    }
    printf("\n");
}
void PrintArr2(int* arr,int n){
    for(int i=0;i<n;++i){
        printf("%d ",arr[i]);
    }
    printf("\n");
}
int main(){
    int arr[] = {1,2,3,4,5,6,7,8,9};
    PrintArr1(arr,9);
    PrintArr1(arr,3);
    PrintArr1(arr+6,3);
    PrintArr1(arr+3,3);
}

試一下下面代碼

#include <stdio.h>

void Test1(int a[]){
    printf("sizeof(a):%d\n",sizeof(a));
    printf("a:%p\t&a:%p\n",a,&a);
}
void Test2(int* p){
    printf("sizeof(p):%d\n",sizeof(p));
    printf("p:%p\t&p:%p\n",p,&p);
}
int main(){
    int arr[10];
    printf("sizeof(arr):%d\n",sizeof(arr));
    printf("arr:%p\t&arr:%p\n",arr,&arr);
    Test1(arr);
    Test2(arr);
}

數(shù)組作為參數(shù)時,數(shù)組退化成指針,不能利用sizeof獲取數(shù)組大小,也就不能計算數(shù)組元素個數(shù)。

3.2 從函數(shù)返回數(shù)組

C 語言不允許返回一個完整的數(shù)組作為函數(shù)的參數(shù)。通過指定不帶索引的數(shù)組名來返回一個指向數(shù)組的指針。

類型* 函數(shù)名() {
   return 數(shù)組名;
}

練習(xí)

  1. 給定數(shù)組隨機填充指定范圍的數(shù)據(jù)。
    使用stdlib.h中的srand(time(NULL))rand()。
  2. 將一維數(shù)組的查找FindArr()、替換Replace()封裝成函數(shù)。

FindArr()可以返回bool(有無)、int(下標(biāo))、int*(地址)有什么區(qū)別。

  • 返回值含義(返回值的含義以及值是人為定義的)
    返回值有時存在兩種情況:合法值和非法值。
    如果有非法值的情況,通常使用一些特定的值指代特殊情況。例如:數(shù)組下標(biāo)只能是0和正數(shù)。我們實現(xiàn)數(shù)組查找元素下標(biāo)時,存在找不到元素的情況,這時,使用-1可以作為這種情況的返回值。

重點

int arr[] = {1,2,3,4,5,6};
// sizeof(數(shù)組名)
printf("sizeof(arr) = %ld\n",sizeof(arr));
// 數(shù)組名的值
printf("arr=%p\n&arr[0]=%p\n",arr,&arr[0]);

數(shù)組名是地址,是常量。

  1. 可以使用指針操作:解引用
  2. 數(shù)組作為函數(shù)參數(shù)和返回值時,傳指針/地址。

數(shù)組下標(biāo)與數(shù)組長度的關(guān)系

  1. arr長度為n,最后一個元素的下標(biāo)為n-1。
  2. 下標(biāo)為i是第i+1個元素,前面有i個元素(不包含i),后面有n-(i+1)個元素(不包含i)。
  3. 下標(biāo)i和j之間有j-i個元素(包含i,不包含j)

數(shù)組地址與數(shù)組名的關(guān)系

  1. 數(shù)組arr的首地址為arr,下標(biāo)為i的地址為arr+i
  2. p=arr+i,那么下標(biāo)對應(yīng)為p-arr。
  3. p前面有p-arr個元素(不包含p),后面有n-(p-arr+1)個元素(不包含p)。

4. 多維數(shù)組

4.1 聲明

  • 語法
類型 數(shù)組名[元素個數(shù)1][元素個數(shù)2]...[元素個數(shù)N];

多維數(shù)組最常用形式是二維數(shù)組。二維數(shù)組相當(dāng)于一個行列組成的表。

類型 二維數(shù)組名[行數(shù)][列數(shù)];

例如下面是一個43列元素類型為int的表。

int days[4][3];

4.2 初始化二維數(shù)組

多維數(shù)組可以通過在括號內(nèi)為每行指定值來進行初始化。

int days[4][3]={
    {31,28,31},
    {30,31,30},
    {31,31,30},
    {31,30,31}
};

4.3 訪問二維數(shù)組元素

二維數(shù)組中的元素是通過使用下標(biāo)(即數(shù)組的行索引和列索引)來訪問的。


// 獲取一月份的天數(shù)
int n = days[0][0];
// 修改二月份的天數(shù)
days[0][1] = 29;
// 打印一月份天數(shù)
printf("%d",days[0][0]);

4.4 二維數(shù)組元素遍歷

通常使用嵌套循環(huán)來處理二維數(shù)組。

for (int i = 0; i < 4; i++ ) {
    for (int j = 0; j < 3; j++ ) {
       printf("a[%d][%d] = %d\n",i,j,a[i][j]);
    }
}

4.5 二維數(shù)組輸入

int n,m;
scanf("%d%d",&n,&m);
int arr[n][m];
for (int i=0;i<n;++i){
  for (int j=0;j<m;++j){
      scanf("%d",&arr[i][j]);
  }
}

練習(xí)

  1. 輸入m個學(xué)生的n門課程成績,輸出各門課程成績以及總成績和平均值。

  2. 二維數(shù)組通常可用于表示數(shù)學(xué)中的矩陣。實現(xiàn)矩陣基本運算(加法、減法、乘法、轉(zhuǎn)置)。


  3. mn月的日期,按星期以日歷方式放入二維數(shù)組(列表示星期),并打印出來。

4.6 簡化

初始化二維數(shù)組可以有如下簡化寫法:

  1. 省略內(nèi)部嵌套括號。
int days[4][3]={31,28,31,30,31,30,31,31,30,31,30,31};
  1. 省略第一維大小,第二維不能省略。
int days[][3]={31,28,31,30,31,30,31,31,30,31,30,31};

問題
二維數(shù)組可以整體初始化嗎?
練習(xí)

4.7 二維數(shù)組作為函數(shù)參數(shù)

二維數(shù)組作為函數(shù)參數(shù),需要同屬輸入行和列的個數(shù)。

void PrintMatrix(int m[4][3],int r,int c)
for (int i = 0; i < r; i++ ) {
    for (int j = 0; j < c; j++ ) {
       printf("%d\n",m[i][j]);
    }
}

4.8 多維數(shù)組

大于二維的數(shù)組的用法與二維數(shù)組一樣,只是使用比較少。

int days[][4][3]={
    {31,28,31,30,31,30,31,31,30,31,30,31}, // 平年
    {31,29,31,30,31,30,31,31,30,31,30,31}  // 閏年
};

printf("平年二月天數(shù)為%d\n",days[0][0][1]);// 平年第一季度第二個月
printf("閏年二月天數(shù)為%d\n",days[1][0][1]);// 閏年第一季度第二個月 

多維數(shù)組初始化只能第一個維度可以省略。

5 const數(shù)組

5.1 const數(shù)組是什么?

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

數(shù)組變量已經(jīng)是const指針,表示數(shù)組中的每一個元素都是const int,即每個元素不能通過arr改變。
例如:

const int arr[]={1,2,3,4,5,};
arr[0] = 0;

5.2 const數(shù)組怎么用?

保護數(shù)組值

因為數(shù)組作為函數(shù)參數(shù)是以地址方式傳遞的,所以函數(shù)內(nèi)部可以修改數(shù)組的值。
為了保護數(shù)組不被函數(shù)破壞,可設(shè)置參數(shù)為const
例如:

int sum(const int arr[],int len);

或者

int sum(const int* arr,int len);

6 變量指針 vs 數(shù)組指針

變量指針:指向單個變量的指針。
數(shù)組指針:指向數(shù)組的指針。

#include <stdio.h>

int main () {
    int n = 10;
    int *p;
    p = &n; // p指針指向變量
    printf("*p = %d\n",*p);
    
    int arr[] = {1,2,3,4,5,};
    p = arr;// p指針指向數(shù)組
    printf("*p = %d\n",*p);
    printf("*(p+1) = %d\n",*(p+1));
    printf("*(p+2) = %d\n",*(p+2));
    printf("*(p+3) = %d\n",*(p+3));
    printf("*(p+4) = %d\n",*(p+4));
    
    return 0;
}

指針既可以指向一個基本類型變量又可以指向一個數(shù)組。所以在使用時要注意分辨。

7 項目

輸入年份打印萬年歷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 教育心理學(xué)是一門研究學(xué)校內(nèi)外學(xué)生的發(fā)展、學(xué)習(xí)、動機、教學(xué)與評估的學(xué)科。 1、教師效能感:由于大眾媒體的影...
    蘊韻1236閱讀 294評論 0 6
  • 小編最近補看了歡樂喜劇人,節(jié)目段子各種搞笑!但是更迷上了這個煤炭一樣黑的男人有沒有!! ...
    慢慢狂奔閱讀 10,535評論 0 0
  • 互聯(lián)網(wǎng)+醫(yī)療行業(yè),會孕育大量的醫(yī)療健康服務(wù)創(chuàng)業(yè)公司,在醫(yī)生、患者、醫(yī)院、醫(yī)藥、單科領(lǐng)域、智能硬件、醫(yī)療新媒體等領(lǐng)域...
    阿柯瑪?shù)氐?/span>閱讀 310評論 0 0
  • 1、描述:名字《明天》 2、順序: 房子一路一花草一右側(cè)樹一左側(cè)樹一云朵一小鳥一人物(我,女兒,老公)本來畫的火柴...
    淘伊_心向光明閱讀 446評論 6 1
  • #玩卡不卡·每日一抽#每一位都可以通過這張卡片覺察自己: 1、直覺他叫什么名字?保羅 2、他幾歲了?40 3、他現(xiàn)...
    我心安住閱讀 140評論 0 0

友情鏈接更多精彩內(nèi)容