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. 动手练习
- 基础练习:编写程序计算数组元素的平均值并找出最大值、最小值。
- 进阶练习:编写程序实现矩阵的转置(行列互换)。
- 挑战练习:编写一个学生成绩管理系统,能够添加、显示、查询、统计学生成绩。