C語(yǔ)言學(xué)習(xí)1-數(shù)組、字符串

一、數(shù)組

一維數(shù)組

1. 數(shù)組定義

基本語(yǔ)法 正確示例:

// 數(shù)據(jù)類型 數(shù)組名[元素個(gè)數(shù)];
char arr[5];        // 字符數(shù)組
int arr[5];         // 整型數(shù)組  
double arr[5];      // 雙精度浮點(diǎn)數(shù)組
float arr[5];       // 單精度浮點(diǎn)數(shù)組

// 使用常量表達(dá)式定義數(shù)組大小
int a[5];           // 整型常量
int b['A'];         // 字符常量(等價(jià)于 int b[65])
int c[3*4];         // 常量表達(dá)式(等價(jià)于 int c[12])

? 錯(cuò)誤寫法:

int[5] a;           // 錯(cuò)誤:[]必須在數(shù)組名后面
int[] b;            // 錯(cuò)誤:必須指定元素個(gè)數(shù)
int size = 5;
int d[size];        // 錯(cuò)誤:C89標(biāo)準(zhǔn)不支持變量長(zhǎng)度(C99支持但有限制)

重要規(guī)則:

  • [] 必須放在數(shù)組名后面
  • 元素個(gè)數(shù)必須是常量常量表達(dá)式
  • 大多數(shù)情況下不能省略元素個(gè)數(shù)(函數(shù)形參和初始化時(shí)除外)

2. 數(shù)組初始化

完全初始化:

char arr[5] = {90, 91, 92, 93, 94};  // 全部元素初始化

部分初始化:

char arr[5] = {90, 91};              // 前兩個(gè)元素初始化,其余自動(dòng)設(shè)為0
// 等價(jià)于:{90, 91, 0, 0, 0}

自動(dòng)推斷大小:

int arr[] = {1, 2, 3, 4, 5};         // 編譯器自動(dòng)推斷大小為5

? 錯(cuò)誤初始化:

int a[3];
a[3] = {1, 2, 3};    // 錯(cuò)誤:定義后不能整體賦值
a = {1, 2, 3};       // 錯(cuò)誤:數(shù)組名是常量指針,不能賦值

注意: 數(shù)組名代表整個(gè)數(shù)組的起始地址,是一個(gè)常量指針。

3. 數(shù)組訪問(wèn)

讀取元素:

char arr[5] = {90, 91, 92, 93, 94};
char s1 = arr[0];    // 讀取第0個(gè)元素:90
char s2 = arr[1];    // 讀取第1個(gè)元素:91

修改元素:

arr[1] = 89;         // 修改第1個(gè)元素為89

?? 重要警告:

int arr[5] = {1, 2, 3, 4, 5};
arr[5] = 6; // ? 數(shù)組越界!C語(yǔ)言不會(huì)檢查邊界

C語(yǔ)言編譯器不會(huì)對(duì)數(shù)組下標(biāo)進(jìn)行越界檢查,程序員必須自己確保訪問(wèn)安全。

4. 數(shù)組作為函數(shù)參數(shù)

#include <stdio.h>

// 函數(shù)聲明:數(shù)組作為參數(shù)
void modifyArray(int arr[], int size) {
    for(int i = 0; i < size; i++) {
        arr[i] *= 2;  // 修改數(shù)組元素
    }
}

int main() {
    int numbers[5] = {1, 2, 3, 4, 5};
    
    printf("修改前: ");
    for(int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    
    // 傳遞數(shù)組給函數(shù)
    modifyArray(numbers, 5);
    
    printf("\n修改后: ");
    for(int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);  // 輸出:2 4 6 8 10
    }
    
    return 0;
}

關(guān)鍵點(diǎn): 數(shù)組名作為參數(shù)時(shí),傳遞的是數(shù)組的起始地址,形參和實(shí)參指向同一內(nèi)存空間。

二維數(shù)組

1. 二維數(shù)組定義與初始化

標(biāo)準(zhǔn)初始化:

// 3行4列的二維數(shù)組
int matrix[3][4] = {
    {1, 2, 3, 4},      // 第0行
    {5, 6, 7, 8},      // 第1行  
    {9, 10, 11, 12}    // 第2行
};

字符二維數(shù)組示例:

char arr[5][3] = {
    {91, 92, 93},      // 第0行
    {81, 82, 83},      // 第1行
    {71, 72, 73},      // 第2行
    {61, 62, 63},      // 第3行
    {51, 52, 53}       // 第4行
};

簡(jiǎn)化初始化:

// 可以省略第一維的大小
int arr[][3] = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};  // 編譯器自動(dòng)推斷為 int arr[3][3]

2. 二維數(shù)組訪問(wèn)

int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8}, 
    {9, 10, 11, 12}
};

// 訪問(wèn)單個(gè)元素
int element = matrix[0][0];  // 第0行第0列:1
matrix[1][2] = 99;          // 修改第1行第2列的元素

// 遍歷二維數(shù)組
for(int i = 0; i < 3; i++) {         // 遍歷行
    for(int j = 0; j < 4; j++) {     // 遍歷列
        printf("%d ", matrix[i][j]);
    }
    printf("\n");
}

注意: 數(shù)組下標(biāo)從 0 開始,matrix[m][n] 表示第 m 行第 n 列。

重要總結(jié)

核心要點(diǎn)

  1. 一維數(shù)組最重要:實(shí)際開發(fā)中一維數(shù)組使用頻率遠(yuǎn)高于多維數(shù)組
  2. 內(nèi)存連續(xù)性:數(shù)組元素在內(nèi)存中是連續(xù)存儲(chǔ)的
  3. 下標(biāo)從0開始:C語(yǔ)言數(shù)組下標(biāo)始終從0開始計(jì)數(shù)
  4. 邊界自檢:編譯器不檢查數(shù)組越界,需要程序員保證安全

使用建議

// 良好的編程習(xí)慣:使用常量定義數(shù)組大小
#define MAX_SIZE 100

int main() {
    int arr[MAX_SIZE];
    
    // 循環(huán)時(shí)使用明確的邊界檢查
    for(int i = 0; i < MAX_SIZE; i++) {
        // 安全操作
    }
    
    return 0;
}

實(shí)際應(yīng)用優(yōu)先級(jí)

  1. 一維數(shù)組:★★★★★(最常用)
  2. 二維數(shù)組:★★☆☆☆(較少使用)
  3. 高維數(shù)組:★☆☆☆☆(極少使用)

掌握一維數(shù)組的使用是學(xué)習(xí)C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ),二維及以上數(shù)組在實(shí)際工程中應(yīng)用場(chǎng)景有限。

二、字符數(shù)組和字符串

字符串的本質(zhì)

C語(yǔ)言中沒有專門的字符串?dāng)?shù)據(jù)類型,而是通過(guò) 字符數(shù)組 來(lái)模擬字符串的功能。

關(guān)鍵概念:

  • C語(yǔ)言中的字符串一定是 char 型數(shù)組
  • char 型數(shù)組不一定是字符串
  • 字符串 = 以數(shù)字 0(或 \0)結(jié)尾的字符數(shù)組

字符串的定義與區(qū)別

1. 字符 vs 字符數(shù)組 vs 字符串

#include <stdio.h>

int main() {
    // 1. 單個(gè)字符
    char ch = 'w';
    
    // 2. 普通字符數(shù)組 - 不是字符串!
    char arr[5] = {'h','e','l','l','o'};
    
    // 3. 字符串 - 以 \0 結(jié)尾
    char str1[] = {'h','e','l','l','o','\0'};  // 手動(dòng)添加 \0
    char str2[] = {'h','e','l','l','o', 0};    // 等價(jià)寫法,數(shù)字0 = \0
    
    // 4. 字符串字面量 - 編譯器自動(dòng)添加 \0
    char *str3 = "hello";                      // 字符串常量
    char str4[] = "hello";                     // 字符數(shù)組,自動(dòng)添加 \0
    
    return 0;
}

2. 內(nèi)存布局對(duì)比

普通字符數(shù)組: | 'h' | 'e' | 'l' | 'l' | 'o' | ? | ? | ... |
字符串:       | 'h' | 'e' | 'l' | 'l' | 'o' | \0 | ? | ... |

字符串的打印與遍歷

打印示例

#include <stdio.h>

int main() {
    char arr[5] = {'h','e','l','l','o'};      // 普通字符數(shù)組
    char str[] = {'h','e','l','l','o','\0'};  // 字符串
    char str2[] = "hello";                    // 字符串
    
    // ? 危險(xiǎn):arr沒有\(zhòng)0結(jié)尾,printf會(huì)越界讀??!
    printf("arr: %s\n", arr);  // 可能打印亂碼
    
    // ? 安全:str和str2以\0結(jié)尾
    printf("str: %s\n", str);   // 輸出: hello
    printf("str2: %s\n", str2); // 輸出: hello
    
    return 0;
}

遍歷示例

#include <stdio.h>

int main() {
    char arr[5] = {'h','e','l','l','o'};
    char str[] = {'h','e','l','l','o','\0'};
    char str2[] = "hello";
    
    printf("遍歷字符數(shù)組arr:\n");
    for (int i = 0; i < sizeof(arr); i++) {
        printf("%c", arr[i]);  // 輸出: hello
    }
    printf("\n");
    
    printf("遍歷字符串str:\n");
    for (int i = 0; i < sizeof(str); i++) {
        printf("%c", str[i]);  // 輸出: hello
    }
    printf("\n");
    
    printf("遍歷字符串str2:\n"); 
    for (int i = 0; i < sizeof(str2); i++) {
        printf("%c", str2[i]); // 輸出: hello
    }
    printf("\n");
    
    return 0;
}

字符串長(zhǎng)度與結(jié)束標(biāo)志

字符串長(zhǎng)度規(guī)則

  • 從頭開始,到第一個(gè) \0 結(jié)束
  • \0 之前的字符個(gè)數(shù)就是字符串長(zhǎng)度

重要示例

#include <stdio.h>

int main() {
    char str1[30] = "http://c.biancheng.net";
    char str2[] = "C Language"; 
    char str3[30] = "You are a good\0 boy!";
    
    printf("str1: %s\n", str1);  // 輸出: http://c.biancheng.net
    printf("str2: %s\n", str2);  // 輸出: C Language  
    printf("str3: %s\n", str3);  // 輸出: You are a good
    
    return 0;
}

解釋:

  • str1, str2: 編譯器自動(dòng)在末尾添加 \0,正常輸出整個(gè)字符串
  • str3: 遇到中間的 \0 就結(jié)束,不輸出后面的 " boy!"

關(guān)鍵注意事項(xiàng)

1. 數(shù)組大小要足夠

// ? 錯(cuò)誤:數(shù)組太小,沒有空間存放 \0
char str[5] = "hello";  // 錯(cuò)誤!需要6個(gè)字節(jié)

// ? 正確:數(shù)組大小 = 字符數(shù) + 1(給\0留位置)
char str[6] = "hello";  // |h|e|l|l|o|\0|
char str[] = "hello";   // 編譯器自動(dòng)計(jì)算為6

2. 必須正確終止

// ? 不是字符串(缺少\0)
char not_string[5] = {'h','e','l','l','o'};

// ? 是字符串(有\(zhòng)0終止)
char is_string[6] = {'h','e','l','l','o','\0'};
char is_string2[] = "hello";

3. \0 之后的內(nèi)容被忽略

char msg[20] = "Hello\0World";
printf("%s", msg);  // 只輸出 "Hello",遇到\0就停止

實(shí)用技巧總結(jié)

安全定義字符串

// 方法1:使用字符串字面量(推薦)
char str1[] = "Hello World";

// 方法2:顯式添加\0
char str2[] = {'H','e','l','l','o','\0'};

// 方法3:先聲明后初始化
char str3[20];
str3[0] = 'H';
str3[1] = 'i';
str3[2] = '\0';  // 重要:手動(dòng)添加結(jié)束符

驗(yàn)證字符串完整性

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "hello";
    
    // 檢查是否以\0結(jié)尾
    printf("Length: %zu\n", strlen(str));      // 輸出: 5
    printf("Sizeof: %zu\n", sizeof(str));      // 輸出: 6 (包含\0)
    printf("Last char: %d\n", str[5]);         // 輸出: 0 (\0的ASCII值)
    
    return 0;
}

核心要點(diǎn)回顧

  1. 字符串本質(zhì):以 \0 結(jié)尾的字符數(shù)組
  2. 結(jié)束標(biāo)志:數(shù)字 0\0,不是字符 '0'
  3. 數(shù)組大小:必須 ≥ 字符數(shù) + 1(為 \0 預(yù)留空間)
  4. 打印行為printf 遇到 \0 就停止輸出
  5. 安全第一:確保所有字符串正確以 \0 結(jié)尾
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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