C语言数组完全指南:一维数组、二维数组的声明初始化与遍历技巧
C语言数组从入门到精通:如何存储和操作一组数据?
C语言数组高效地管理同类型的数据集合,本文将详细讲解一维数组和二维数组的声明、初始化、遍历方法,包含数组排序、查找等实战应用案例。
在实际编程中,我们经常需要处理大量相同类型的数据。比如:100个学生的成绩、50个商品的价格、一个矩阵的数据等。如果为每个数据都定义一个变量,代码将变得冗长且难以维护。C语言提供了数组这种数据结构来高效地管理同类型的数据集合。
接下来这篇文章将带你全面掌握C语言数组的使用。
1. 什么是数组?
数组是相同类型数据的集合,这些数据在内存中连续存储,通过索引(下标)来访问每个元素。
数组的特点:
- 所有元素具有相同的数据类型
- 内存中连续存储
- 通过下标访问元素,下标从0开始
- 数组大小在创建时确定,不能改变
2. 一维数组的声明和初始化
声明语法:
数据类型 数组名[数组大小];初始化方法:
#include <stdio.h>
int main() {
    // 方法1:声明时完全初始化
    int scores[5] = {85, 92, 78, 90, 88};
    
    // 方法2:声明时部分初始化(未初始化的元素默认为0)
    int numbers[5] = {1, 2, 3}; // 等价于 {1, 2, 3, 0, 0}
    
    // 方法3:不指定大小,编译器自动计算
    int primes[] = {2, 3, 5, 7, 11, 13};
    
    // 方法4:先声明,后逐个赋值
    float prices[3];
    prices[0] = 12.5;
    prices[1] = 9.8;
    prices[2] = 15.3;
    
    return 0;
}3. 访问数组元素
数组元素通过下标访问,下标范围是0到(数组大小-1)。
#include <stdio.h>
int main() {
    int numbers[5] = {10, 20, 30, 40, 50};
    
    // 访问单个元素
    printf("第一个元素: %d\n", numbers[0]);  // 10
    printf("第三个元素: %d\n", numbers[2]);  // 30
    
    // 修改元素值
    numbers[1] = 25;
    printf("修改后的第二个元素: %d\n", numbers[1]);  // 25
    
    // 错误:访问越界(可能导致程序崩溃)
    // printf("%d\n", numbers[5]);  // 错误!有效下标是0-4
    
    return 0;
}4. 遍历数组:使用for循环
遍历数组是对数组最基本的操作,通常使用for循环。
#include <stdio.h>
int main() {
    int scores[5] = {85, 92, 78, 90, 88};
    int sum = 0;
    float average;
    
    // 遍历数组并计算总分
    printf("所有成绩: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", scores[i]);
        sum += scores[i];
    }
    
    average = (float)sum / 5;
    printf("\n总分: %d, 平均分: %.2f\n", sum, average);
    
    // 查找最高分
    int max_score = scores[0];
    for (int i = 1; i < 5; i++) {
        if (scores[i] > max_score) {
            max_score = scores[i];
        }
    }
    printf("最高分: %d\n", max_score);
    
    return 0;
}5. 二维数组:表格状数据
二维数组可以理解为由行和列组成的表格。
声明和初始化:
#include <stdio.h>
int main() {
    // 声明3行4列的二维数组
    int matrix[3][4] = {
        {1, 2, 3, 4},      // 第0行
        {5, 6, 7, 8},      // 第1行
        {9, 10, 11, 12}     // 第2行
    };
    
    // 也可以这样初始化
    int table[2][3] = {1, 2, 3, 4, 5, 6};
    
    return 0;
}遍历二维数组:
#include <stdio.h>
int main() {
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    
    printf("矩阵内容:\n");
    // 外层循环控制行
    for (int i = 0; i < 3; i++) {
        // 内层循环控制列
        for (int j = 0; j < 3; j++) {
            printf("%d\t", matrix[i][j]);
        }
        printf("\n");
    }
    
    // 计算对角线之和
    int diagonal_sum = 0;
    for (int i = 0; i < 3; i++) {
        diagonal_sum += matrix[i][i];  // 主对角线元素
    }
    printf("主对角线之和: %d\n", diagonal_sum);
    
    return 0;
}6. 数组实战:冒泡排序
排序是数组的重要应用之一,冒泡排序是最简单的排序算法。
#include <stdio.h>
int main() {
    int numbers[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(numbers) / sizeof(numbers[0]);  // 计算数组长度
    
    printf("排序前: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    // 冒泡排序
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (numbers[j] > numbers[j + 1]) {
                // 交换元素
                int temp = numbers[j];
                numbers[j] = numbers[j + 1];
                numbers[j + 1] = temp;
            }
        }
    }
    
    printf("排序后: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}7. 数组实战:二分查找
对于已排序的数组,二分查找是高效的搜索算法。
#include <stdio.h>
int main() {
    int numbers[] = {11, 12, 22, 25, 34, 64, 90};  // 必须是有序数组
    int n = sizeof(numbers) / sizeof(numbers[0]);
    int target, found = 0;
    
    printf("请输入要查找的数字: ");
    scanf("%d", &target);
    
    // 二分查找
    int left = 0, right = n - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        
        if (numbers[mid] == target) {
            printf("找到数字 %d,位置是 %d\n", target, mid);
            found = 1;
            break;
        } else if (numbers[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    
    if (!found) {
        printf("未找到数字 %d\n", target);
    }
    
    return 0;
}8. 数组作为函数参数
数组可以作为参数传递给函数,但需要特别注意数组在函数间的传递方式。
#include <stdio.h>
// 函数声明:参数可以写成 int arr[] 或 int *arr
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
// 修改数组元素的函数
void doubleArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;  // 会修改原始数组
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int n = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("原始数组: ");
    printArray(numbers, n);
    
    doubleArray(numbers, n);
    
    printf("加倍后的数组: ");
    printArray(numbers, n);  // 原始数组已被修改
    
    return 0;
}9. 常见错误与最佳实践
常见错误1:数组越界
int arr[5] = {1, 2, 3, 4, 5};
printf("%d", arr[5]);  // 错误!有效下标是0-4常见错误2:使用变量定义数组大小(C89标准)
int size = 10;
int arr[size];  // 在C89标准中错误,C99标准支持最佳实践:
- 总是检查数组下标是否越界
- 使用sizeof计算数组长度:int length = sizeof(arr) / sizeof(arr[0]);
- 数组作为函数参数时,需要同时传递数组大小
- 对数组进行修改操作前,考虑是否需要备份原始数据
10. 字符数组简介(字符串基础)
字符数组可以用来存储字符串。
#include <stdio.h>
int main() {
    // 字符数组存储字符串
    char name[20] = "张三";  // 自动添加结束符'\0'
    char greeting[] = "Hello, World!";
    
    printf("姓名: %s\n", name);
    printf("问候: %s\n", greeting);
    
    // 逐个字符遍历
    printf("字符串字符: ");
    for (int i = 0; greeting[i] != '\0'; i++) {
        printf("%c ", greeting[i]);
    }
    printf("\n");
    
    return 0;
}11. 总结
在本篇教程中,你学到了:
- 一维数组的声明、初始化和访问方法
- 使用for循环遍历数组的技巧
- 二维数组的表格式数据管理
- 冒泡排序和二分查找算法实现
- 数组作为函数参数的传递方式
- 字符数组的字符串存储特性
- 数组操作的常见错误和最佳实践
12. 动手练习
- 基础练习:编写程序计算数组元素的平均值并找出最大值、最小值。
- 进阶练习:编写程序实现矩阵的转置(行列互换)。
- 挑战练习:编写一个学生成绩管理系统,能够添加、显示、查询、统计学生成绩。