Skip to content

数组

在C语言中,数组是一种派生数据类型,用于存储相同类型的多个元素。数组为我们提供了一种方便的方式来组织和处理批量数据。在本章节中,我们将学习C语言中数组的定义、初始化、访问和使用方法。

1. 什么是数组?

数组是一种连续的内存空间,用于存储多个相同类型的元素。每个元素在数组中都有一个唯一的索引,通过索引可以访问和修改数组元素。

想象数组就像一排有编号的储物柜:

  • 整个储物柜:数组
  • 每个储物柜:数组元素
  • 储物柜编号:数组索引
  • 储物柜中的物品:元素值

2. 数组的定义

定义数组就是告诉编译器创建一个数组,指定其类型、名称和大小。数组定义的基本语法如下:

c
数据类型 数组名[数组大小];

2.1 说明

  • 数据类型:数组元素的类型
  • 数组名:数组的名称,遵循标识符命名规则
  • 数组大小:数组可以存储的元素个数,必须是一个常量表达式

2.2 示例

c
int numbers[5];  // 定义一个包含5个整型元素的数组
float prices[10];  // 定义一个包含10个浮点型元素的数组
char letters[26];  // 定义一个包含26个字符型元素的数组

3. 数组的初始化

初始化数组就是在定义数组的同时给数组元素赋初始值。数组初始化的基本语法如下:

3.1 完全初始化

c
数据类型 数组名[数组大小] = {元素1, 元素2, ..., 元素n};

示例:

c
int numbers[5] = {1, 2, 3, 4, 5};  // 完全初始化

3.2 部分初始化

如果初始化列表中的元素个数少于数组大小,剩余的元素会被自动初始化为0:

c
int numbers[5] = {1, 2, 3};  // 部分初始化,numbers[3]和numbers[4]会被初始化为0

3.3 省略数组大小

如果在初始化时提供了元素列表,可以省略数组大小,编译器会根据元素个数自动确定数组大小:

c
int numbers[] = {1, 2, 3, 4, 5};  // 数组大小为5

3.4 字符数组的初始化

字符数组可以用字符串字面量初始化:

c
char message[] = "Hello";

注意:字符串字面量会自动添加一个空字符'\0'作为结束符,所以上面的数组大小实际上是6。

4. 数组元素的访问

访问数组元素是通过索引来实现的。数组索引从0开始,到数组大小-1结束。

4.1 语法

c
数组名[索引]

4.2 示例

c
#include <stdio.h>

int main() {
    int numbers[5] = {1, 2, 3, 4, 5};
    
    // 访问数组元素
    printf("第一个元素: %d\n", numbers[0]);  // 1
    printf("第三个元素: %d\n", numbers[2]);  // 3
    printf("最后一个元素: %d\n", numbers[4]);  // 5
    
    // 修改数组元素
    numbers[1] = 10;
    printf("修改后的第二个元素: %d\n", numbers[1]);  // 10
    
    return 0;
}

4.3 注意事项

  • 索引越界:访问超出数组范围的索引会导致未定义行为,可能会破坏其他变量的值或导致程序崩溃
  • 索引从0开始:C语言中数组索引从0开始,这与许多其他编程语言相同

5. 数组的遍历

遍历数组是指访问数组中的每个元素。通常使用循环语句来遍历数组。

5.1 使用for循环遍历

c
#include <stdio.h>

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);  // 计算数组大小
    
    // 遍历数组并打印每个元素
    printf("数组元素: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    // 遍历数组并计算总和
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += numbers[i];
    }
    printf("数组元素总和: %d\n", sum);
    
    return 0;
}

5.2 使用while循环遍历

c
#include <stdio.h>

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    int i = 0;
    
    printf("数组元素: ");
    while (i < size) {
        printf("%d ", numbers[i]);
        i++;
    }
    printf("\n");
    
    return 0;
}

6. 多维数组

多维数组是指数组的元素也是数组,最常见的是二维数组。二维数组可以看作是一个表格或矩阵。

6.1 二维数组的定义

c
数据类型 数组名[行数][列数];

示例:

c
int matrix[3][4];  // 定义一个3行4列的整型二维数组

6.2 二维数组的初始化

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

也可以使用更简洁的方式:

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

6.3 二维数组的访问

c
#include <stdio.h>

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 访问二维数组元素
    printf("第一行第一列: %d\n", matrix[0][0]);  // 1
    printf("第二行第三列: %d\n", matrix[1][2]);  // 7
    printf("第三行第四列: %d\n", matrix[2][3]);  // 12
    
    return 0;
}

6.4 二维数组的遍历

c
#include <stdio.h>

int main() {
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 遍历二维数组
    printf("二维数组元素:\n");
    for (int i = 0; i < 3; i++) {  // 行循环
        for (int j = 0; j < 4; j++) {  // 列循环
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

7. 数组与函数

数组可以作为函数的参数传递,也可以作为函数的返回值(通过指针)。

7.1 数组作为函数参数

当数组作为函数参数时,实际上传递的是数组的首地址(指针),而不是整个数组的副本。

c
#include <stdio.h>

// 函数声明
void print_array(int arr[], int size);
void modify_array(int arr[], int size);

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("原始数组: ");
    print_array(numbers, size);
    
    modify_array(numbers, size);
    
    printf("修改后的数组: ");
    print_array(numbers, size);
    
    return 0;
}

// 打印数组元素
void print_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 修改数组元素
void modify_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // 每个元素乘以2
    }
}

7.2 数组作为函数返回值

C语言不允许直接返回整个数组,但可以返回指向数组的指针。

8. 字符数组与字符串

在C语言中,字符串通常存储在字符数组中,以空字符'\0'作为结束符。

8.1 字符数组的初始化

c
char str1[] = "Hello";
char str2[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

8.2 字符串的输入输出

c
#include <stdio.h>

int main() {
    char name[50];
    
    printf("请输入你的名字: ");
    scanf("%s", name);  // 注意:scanf会在遇到空格时停止读取
    
    printf("你好, %s!\n", name);
    
    return 0;
}

8.3 字符串处理函数

C语言提供了许多字符串处理函数,需要包含头文件<string.h>

  • strlen():计算字符串长度
  • strcpy():复制字符串
  • strcat():连接字符串
  • strcmp():比较字符串
c
#include <stdio.h>
#include <string.h>

int main() {
    char str1[20] = "Hello";
    char str2[20] = "World";
    
    printf("str1的长度: %zu\n", strlen(str1));  // 5
    
    strcpy(str1, "Hi");  // 复制字符串
    printf("str1: %s\n", str1);  // Hi
    
    strcat(str1, " " str2);  // 连接字符串
    printf("str1 + str2: %s\n", str1);  // Hi World
    
    int result = strcmp(str1, str2);  // 比较字符串
    printf("strcmp结果: %d\n", result);  // 非0值
    
    return 0;
}

9. 数组的注意事项

  1. 数组大小:数组大小必须是常量表达式,不能是变量
  2. 索引越界:访问超出数组范围的索引会导致未定义行为
  3. 内存分配:数组在定义时分配连续的内存空间
  4. 数组名:数组名是一个常量指针,指向数组的第一个元素
  5. 函数参数:数组作为函数参数时,会退化为指针,丢失大小信息

10. 示例:数组的应用

10.1 计算数组元素的平均值

c
#include <stdio.h>

int main() {
    int numbers[] = {85, 92, 78, 95, 88};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    int sum = 0;
    
    // 计算总和
    for (int i = 0; i < size; i++) {
        sum += numbers[i];
    }
    
    // 计算平均值
    float average = (float)sum / size;
    
    printf("数组元素: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    printf("总和: %d\n", sum);
    printf("平均值: %.2f\n", average);
    
    return 0;
}

10.2 查找数组中的最大值

c
#include <stdio.h>

int main() {
    int numbers[] = {10, 5, 20, 15, 25};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    int max = numbers[0];
    
    // 查找最大值
    for (int i = 1; i < size; i++) {
        if (numbers[i] > max) {
            max = numbers[i];
        }
    }
    
    printf("数组元素: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    printf("最大值: %d\n", max);
    
    return 0;
}

10.3 二维数组:矩阵加法

c
#include <stdio.h>

int main() {
    int matrix1[2][2] = {
        {1, 2},
        {3, 4}
    };
    
    int matrix2[2][2] = {
        {5, 6},
        {7, 8}
    };
    
    int result[2][2];
    
    // 矩阵加法
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            result[i][j] = matrix1[i][j] + matrix2[i][j];
        }
    }
    
    // 打印结果
    printf("矩阵加法结果:\n");
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            printf("%d ", result[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}

11. 动态数组

在C语言中,数组的大小在定义时就必须确定。如果需要在运行时确定数组大小,可以使用动态内存分配

11.1 使用malloc函数分配内存

c
#include <stdio.h>
#include <stdlib.h>

int main() {
    int size;
    int *numbers;
    
    printf("请输入数组大小: ");
    scanf("%d", &size);
    
    // 动态分配内存
    numbers = (int *)malloc(size * sizeof(int));
    
    if (numbers == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    // 初始化数组
    for (int i = 0; i < size; i++) {
        numbers[i] = i + 1;
    }
    
    // 打印数组
    printf("数组元素: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    // 释放内存
    free(numbers);
    
    return 0;
}

12. 小结

数组是C语言中用于存储多个相同类型元素的重要数据结构:

  1. 数组的定义:指定类型、名称和大小
  2. 数组的初始化:完全初始化、部分初始化或省略大小
  3. 数组的访问:通过索引访问和修改元素
  4. 数组的遍历:使用循环遍历所有元素
  5. 多维数组:如二维数组,用于表示表格或矩阵
  6. 数组与函数:数组作为函数参数时传递的是指针
  7. 字符数组与字符串:字符数组用于存储字符串
  8. 动态数组:使用动态内存分配创建可变大小的数组

合理使用数组可以有效地组织和处理批量数据,提高程序的效率和可读性。在使用数组时,应注意避免索引越界等常见错误。