天天看點

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

所謂數組,是指将那些具有相同類型的、數量有限的若幹個變量通過有序的方法組織起來的一種便于使用的形式。數組屬于一種構造類型,其中的變量被稱為數組的元素。數組元素的類型可以是基本資料類型,也可以是特殊類型和構造類型。

一維數組

一位數組是最簡單的數組類型,它的定義形式如下:

類型說明符 數組名[常量表達式]

類型說明符是數組中每個元素的類型,常量表達式是數組元素的個數

在使用一維數組的時候需要留意以下兩個要點

  • 常量表達式的值必須是正整數
  • 數組元素的引用,數組的起始元素下标為0

下來我們通過一個簡單的示例了解一下數組

代碼如下:

#include<stdio.h>
#define N 9
int main(void) {
    int arr[N];
    int i;
    for (i = 0; i < N; i++)
    {
        arr[i] = i + 1;
        printf("arr[%d]=%d\t", i, arr[i]);
        if (0 == (i+1)%3)
        {
            printf("\n");
        }
    }
    return 0;
}
           

運作結果如下:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

我們分析一下上面這段代碼

我們定義了一個含有9個元素的一位數組arr,在引用數組中的元素時,采用"數組名[下标]"的方式,将其中的每一個元素視為一個普通的變量來進行操作。需要注意的是,因為定義的數組arr僅含有9個元素,是以在使用的過程中,下标值不能超過8,否則就會出現下标越界的錯誤,示例如下:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

在使用數組的時候要特别注意數組越界,不然很有可能為自己埋下一顆雷(bug)。

接下來我們我們通過一段代碼看一下數組在記憶體中是如何存放的

#include<stdio.h>
#define N 4
int main(void) {
    int arr[N];
    int i;
    for (i = 0; i < N; i++)
    {
        arr[i] = i;
        printf("&arr[%d]=%d\n", i, &arr[i]);
    }
    return 0;
}
           

運作結果如下:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

從結果我們可以看出,每個元素占用4個位元組,在内用中的存儲結構圖如下:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

最後我們再通過一個示例來鞏固一下一維數組

需求:使用數組儲存使用者輸入的資料,當輸入完畢後逆向輸出

代碼如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define N 5
int main(void) {
    int arr[N];//定義數組
    int i, temp;//定義變量
    printf("請輸入一個5個元素數組:\n");
    for (i = 0; i < N; i++)
    {
        scanf("%d", &arr[i]);
    }
    printf("讀取到的數組如下:\n");
    for (i = 0; i < N; i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
    for (i = 0; i < 2; i++)//将數組中元素的前後位置互換
    {
        temp = arr[i];
        arr[i] = arr[4 - i];
        arr[4 - i] = temp;
    }
    printf("輸出的逆向數組如下:\n");
    for (i = 0; i < N; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}
           

運作結果如下:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

二維數組

二維數組定義的一般形式如下:

類型說明符 數組名[常量表達式1][常量表達式2]

與一維數組的定義唯一的不同是多了一個常量表達式2,其中,常量表達式1為第一維的長度,常量表達式2為第二維的長度。通常在處理二維數組的時候,為了便于了解,都将數組視為一個矩陣,常量表達式1表示矩陣的行數,而常量表達式2表示矩陣的列數。與一維數組一樣,在定義二維數組時,常量表達式同樣不能為變量。下面先通過一段代碼來看二維數組的定義。

#include<stdio.h>

#define M 4
#define N 3


int main() {
  int arr[M][N];
  for (int i = 0; i < M; i++)
  {
    for (int j = 0; j < N; j++)
    {
      printf("&arr[%d][%d]=%d\t", i, j, &arr[i][j]);
    }
    printf("\n");
  }
  return 0;
}
           

運作結果:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

将二維數組arr視為一個矩陣,下圖顯示了數組中每個元素在矩陣中的存放位置。

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

數組中各個元素在矩陣中對應的位置由二維數組的兩個下标決定。我們可以将定義的二維數組int arr[4][3]視為由arr[4]和int [3] 兩部分構成,将arr[4]視為一個整型一維數組,其中含有4個元素arr[0]、arr[1]、arr[2]、arr[3],每個元素都是int[3]類型的,也就是說,每個元素又是一個一維數組,每個一維數組含有3個元素,如arr[0]含有arr[0][1]、arr[0][1]、arr[0][2]三個元素。

知道了二維數組的這種特殊結構之後,接下來通過下圖來了解二維數組在記憶體中的存儲結構。

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

通過上述二維數組在記憶體中的存儲結構圖可以發現,二維數組中的所有元素都存儲在一片連續的記憶體單元中,所占用的記憶體大小為元素類型所占用的記憶體大小乘以第一維及第二維的長度。如果以矩陣的方式來分析二維數組的存儲方式,那麼先從矩陣第一行從左往右依次存儲完所有元素,然後按照同樣的方法存儲第二行的所有元素,直到存儲完所有數組元素為止。

接下來再看一個二維數組的示例:

任意輸入一個3行3列的二維數組,求對角元素之和

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main() {
  int arr[3][3];
  int i, j, sum = 0;
  printf("please input:\n");
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 3; j++)
    {
      scanf("%d", &arr[i][j]);
    }
  }
  for (i = 0; i < 3; i++)
  {
    for ( j = 0; j < 3; j++)
    {
      if (i==j)
      {
        sum += arr[i][j];
      }
    }
  }
  printf("the result is: %d\n", sum);
  return 0;
}
           

運作結果如下:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

字元數組

字元數組顧名思義就是數組的元素類型為字元型的數組。特殊之處在于它是數組元素為字元的數組。其定義的一般形式和注意事項與之前講解的一般數組類似,隻是其中的類型說明符是char。當然,并不是說類型說明符隻能是char,也可以是long、int等,但是由于char型隻占用一個位元組的大小,使用long型和int型來定義字元數組會造成資源的浪費,是以一般選擇使用char型來定義字元數組。

一維字元數組

首先通過下面一段代碼來看看一維字元數組的定義。

#include<stdio.h>
#define SIZE 20
int main() {
    long arr1[SIZE] = {'h','e','l','l','o',' ','w','o','r','l','d','!'};
    char arr2[SIZE] = { 'h','e','l','l','o',' ','w','o','r','l','d','!' };
    printf("long型字元數組占用的記憶體大小為:%d\n", sizeof(arr1));
    printf("char型字元數組占用的記憶體大小為:%d\n", sizeof(arr2));
    return 0;
}
           

運作結果:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

在上面的代碼中定義了不同類型的字元數組來存放相同的字元,可以看出,它們占用的記憶體大小相差很大,long型字元數組所占用記憶體大小是char型數組占用記憶體大小的4倍。從這點可以看出,選用char型作為數組類型避免了記憶體空間的浪費。下面通過一段代碼來了解字元數組的初始化特點。

#include<stdio.h>
#define SIZE 20
int main() {
    int i;
    char arr[SIZE] = { 'h','e','l','l','o',' ','w','o','r','l','d','!' };
    for (i = 0; i < SIZE; i++)
    {
        printf("%c", arr[i]);
    }
    
    return 0;
}
           

運作結果:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

運作結果為“Hello World!”,其中有一些空字元。看看上面代碼中定義的arr數組,其數組長度為20,而初始化的字元元素的個數為12,初始化的字元元素個數小于數組長度,編譯器在編譯過程中将後面沒有初始化的數組元素指派為‘\0’,這也正是列印輸出中含有空字元的原因。在列印的時候也可以将數組中的元素‘\0’視為數組結束的标志,例如:

#include<stdio.h>
#define SIZE 20
int main() {
    int i;
    long arr[SIZE] = { 'h','e','l','l','o',' ','w','o','r','l','d','!' };
    for (i = 0; arr[i]!='\0'; i++)
    {
        printf("%c", arr[i]);
    }
    
    return 0;
}
           

運作結果:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

這時的輸出結果中就不含有任何空字元了,因為巧妙地使用了字元數組中的‘\0’标志。當然,也可以采用字元串常量的方式來對一維字元數組進行初始化,例如:

#include<stdio.h>
#define SIZE 20
int main() {
    int i;
    char arr[SIZE] = { "hello world!" };
    for (i = 0; arr[i] != '\0'; i++)
    {
        printf("%c", arr[i]);
    }
    
    return 0;
}
           

運作結果:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

在對一維字元數組進行定義和初始化的過程中,可以不指定其長度。使用字元常量清單和字元串常量的方式進行初始化的結果是不同的,例如:

#include<stdio.h>
int main() {
    int i;
    char arr1[] = { "hello world!" };
    char arr2[] = {'h','e','l','l','o',' ','w','o','r','l','d','!'};
    
    printf("采用字元串常量進行初始化的arr1數組的長度為:%d\n", sizeof(arr1));
    printf("采用字元常量清單進行初始化的arr2數組的長度為:%d\n", sizeof(arr2));
    
    return 0;
}
           

運作結果:

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

從運作結果發現,采用這兩種方式得到的數組長度并不相同,在采用字元串常量對字元數組進行初始化的過程中,在記憶體中進行存儲時會自動在字元串的後面添加一個結束符‘\0’,是以得到的字元數組長度是字元串常量的長度加1;而采用字元常量清單的方式對字元數組進行初始化就不會在最後添加一個結束符,是以利用這種方式定義的字元數組的長度就是字元常量清單中字元的個數。

數組執行個體

交換數組中最大數和最小數的位置

執行個體代碼

//
// Created by 沖哥 on 2021/22/09.
// 實作功能:交換數組中最大數和最小數的位置
//

#include "stdio.h"

int main(){
    int a[10];
    int max, min;
    int m, n;

    printf("請輸入10個數字:\n");
    for (int i = 0; i < 10; i++) {
        scanf("%d", &a[i]);
    }
    printf("輸入的10個數是:\n");
    for (int i = 0; i < 10; i++) {
        printf("%4d", a[i]);
    }
    printf("\n");
    max = a[0];
    for (int i = 0; i < 10; i++) {
        if (a[i] > max) {
            max = a[i];
            m = i;
        }
    }

    min = a[0];
    for (int i = 0; i < 10; i++) {
        if (a[i] < min) {
            min = a[i];
            n = i;
        }
    }

    a[m] = min;
    a[n] = max;

    printf("交換最大數和最小數的位置後:\n");
    for (int i = 0; i < 10; i++) {
        printf("%4d", a[i]);
    }
} 
           

運作結果

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

程式分析

首先找到數組中的最大值和最小值,記錄它們的位置,然後交換位置,最後将交換後的數組輸出。

如果您覺得本篇文章對您有幫助就順手點個贊吧

更多幹貨内容請檢視我的個人公衆号:C語言中文社群。

【C語言中文社群】是一個C語言/C++視訊教程、學習筆記、電子書、計算機二級資料等專注于C語言/C++程式設計學習者的幹貨知識分享平台,精選深度文章,分享優秀幹貨類、技能類的學習資源,幫助學習中的你。

C語言從青銅到王者——數組詳解總結【一維數組、二維數組、字元數組、數組執行個體】

繼續閱讀