📖 学习信息
学习课程:黑马 C++ 零基础入门教程
本日学习:C++ 数组完整知识点包含:一维数组(定义 + 初始化 + 常见操作)、冒泡排序算法、二维数组(定义 + 初始化 + 遍历)、数组注意事项、综合实战案例
一、前言
数组是 C++ 中存储同类型数据的连续内存集合,是最基础的数据结构之一。当需要存储大量相同类型的数据(比如学生成绩、员工工资、游戏坐标)时,使用数组可以避免定义大量零散变量,极大提高代码的整洁性和可维护性。数组也是后续学习指针、字符串、容器、算法的基础,必须彻底掌握。
二、一维数组
一维数组是最简单的数组形式,用于存储一行同类型的数据。
1. 一维数组的定义
语法:
数据类型 数组名[数组长度];
- 数据类型:数组中每个元素的类型(int、double、char 等)
- 数组名:数组的标识符,遵循变量命名规范
- 数组长度:数组能存储的元素个数,必须是常量表达式(不能是变量)
示例:
// 定义一个长度为5的整型数组,存储5个整数
int arr[5];
// 定义一个长度为10的浮点型数组
double scores[10];
2. 一维数组的初始化
数组初始化有三种常用方式,未初始化的数组元素值是随机的,建议养成初始化习惯。
// 1. 全部初始化:给所有元素赋值
int arr1[5] = {1, 2, 3, 4, 5};
// 2. 部分初始化:只给前n个元素赋值,剩余元素自动初始化为0
int arr2[5] = {1, 2, 3}; // 等价于 {1,2,3,0,0}
// 3. 省略数组长度:编译器自动根据初始化值的个数确定长度
int arr3[] = {1, 2, 3, 4}; // 数组长度为4
3. 数组元素的访问
通过下标访问数组元素,数组下标从 0 开始,最大下标为「数组长度 - 1」。
int arr[5] = {10, 20, 30, 40, 50};
// 访问第一个元素
cout << arr[0] << endl; // 输出10
// 访问第三个元素
cout << arr[2] << endl; // 输出30
// 修改元素值
arr[1] = 200;
cout << arr[1] << endl; // 输出200
4. 一维数组的常见操作
(1)数组遍历(最常用)
通过循环遍历数组的所有元素,是数组所有操作的基础。
int arr[5] = {1, 2, 3, 4, 5};
// 遍历数组,输出所有元素
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
(2)数组求和
int arr[5] = {1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += arr[i];
}
cout << "数组元素和为:" << sum << endl; // 输出15
(3)求数组最大值
int arr[5] = {12, 45, 7, 89, 23};
int max = arr[0]; // 假设第一个元素是最大值
for (int i = 1; i < 5; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
cout << "数组最大值为:" << max << endl; // 输出89
(4)数组逆序
将数组元素的顺序反转,比如 {1,2,3,4,5} → {5,4,3,2,1}
int arr[5] = {1, 2, 3, 4, 5};
// 首尾元素交换,循环到数组中间即可
for (int i = 0; i < 5/2; i++) {
int temp = arr[i];
arr[i] = arr[4 - i];
arr[4 - i] = temp;
}
// 输出逆序后的数组
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
三、重点算法:冒泡排序
冒泡排序是最基础的排序算法,核心思想是相邻元素两两比较,大的元素往后 “冒泡” ,每一轮排序都会将当前未排序部分的最大元素放到正确位置。
1. 算法原理
- 对于长度为 n 的数组,需要进行 n-1 轮 排序
- 每一轮排序中,需要进行 n-1-i 次 比较(i 为当前轮数,从 0 开始)
- 每次比较相邻两个元素,如果前一个大于后一个,就交换它们的位置
2. 完整代码实现
#include <iostream>
using namespace std;
int main()
{
int arr[6] = {4, 2, 8, 0, 5, 7};
int len = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
cout << "排序前:";
for (int i = 0; i < len; i++) {
cout << arr[i] << " ";
}
cout << endl;
// 冒泡排序核心
for (int i = 0; i < len - 1; i++) { // 外层循环:控制排序轮数
for (int j = 0; j < len - 1 - i; j++) { // 内层循环:控制每轮比较次数
if (arr[j] > arr[j + 1]) { // 前一个元素大于后一个,交换
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
cout << "排序后:";
for (int i = 0; i < len; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
3. 运行结果
排序前:4 2 8 0 5 7
排序后:0 2 4 5 7 8
四、二维数组
二维数组用于存储多行多列的同类型数据,比如学生的多门成绩、矩阵数据等,可以理解为 “数组的数组”。
1. 二维数组的定义
语法:
数据类型 数组名[行数][列数];
示例:
// 定义一个3行4列的整型数组,存储3个学生的4门成绩
int scores[3][4];
2. 二维数组的初始化
// 1. 全部初始化
int arr1[2][3] = {{1, 2, 3}, {4, 5, 6}};
// 2. 按行部分初始化,剩余元素自动为0
int arr2[2][3] = {{1, 2}, {4}}; // 等价于 {{1,2,0}, {4,0,0}}
// 3. 省略行数,编译器自动根据初始化值确定行数
int arr3[][3] = {1, 2, 3, 4, 5, 6}; // 等价于 2行3列
// 4. 省略列数(不推荐,编译器无法确定)
// int arr4[2][] = {1,2,3,4}; // 错误写法
3. 二维数组的访问与遍历
通过行下标和列下标访问元素,行下标和列下标都从 0 开始。遍历二维数组需要使用嵌套循环:外层循环控制行,内层循环控制列。
int scores[3][4] = {
{90, 85, 95, 88}, // 第1个学生的4门成绩
{78, 82, 80, 75}, // 第2个学生的4门成绩
{92, 98, 89, 96} // 第3个学生的4门成绩
};
// 遍历二维数组,输出所有成绩
for (int i = 0; i < 3; i++) { // 外层循环:遍历行
cout << "第" << i+1 << "个学生成绩:";
for (int j = 0; j < 4; j++) { // 内层循环:遍历列
cout << scores[i][j] << " ";
}
cout << endl;
}
4. 二维数组常见操作:计算每个学生的总分
int scores[3][4] = {
{90, 85, 95, 88},
{78, 82, 80, 75},
{92, 98, 89, 96}
};
for (int i = 0; i < 3; i++) {
int sum = 0;
for (int j = 0; j < 4; j++) {
sum += scores[i][j];
}
cout << "第" << i+1 << "个学生总分:" << sum << endl;
}
五、数组的核心注意事项与避坑点
-
**数组下标越界(最严重错误)**数组下标范围是
0 ~ 长度-1,访问超出范围的下标会导致程序崩溃或数据异常int arr[5] = {1,2,3,4,5}; cout << arr[5] << endl; // 错误:下标越界,最大下标是4 -
数组长度必须是常量表达式C++ 标准不支持用变量作为数组长度(部分编译器支持,但不推荐)
int n = 5; int arr[n]; // 错误:n是变量,不是常量 -
数组名的本质数组名是指向数组首元素的常量指针,不能被赋值
int arr[5] = {1,2,3,4,5}; int *p = arr; // 正确:arr指向首元素arr[0] // arr = p; // 错误:数组名是常量,不能赋值 -
不能直接赋值整个数组只能逐个元素赋值,不能直接用
arr1 = arr2赋值int arr1[5] = {1,2,3,4,5}; int arr2[5]; // arr2 = arr1; // 错误 // 正确:逐个赋值 for (int i = 0; i < 5; i++) { arr2[i] = arr1[i]; } -
sizeof 计算数组长度
sizeof(数组名)得到数组占用的总字节数,除以单个元素的字节数得到数组长度int arr[5] = {1,2,3,4,5}; int len = sizeof(arr) / sizeof(arr[0]); // 5
六、综合实战案例:学生成绩管理系统
结合一维数组和二维数组,实现一个简单的学生成绩管理系统,支持输入成绩、计算总分、平均分、排名:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const int STUDENT_NUM = 3; // 学生人数
const int SUBJECT_NUM = 3; // 科目数
string names[STUDENT_NUM]; // 存储学生姓名
int scores[STUDENT_NUM][SUBJECT_NUM]; // 存储成绩
int totalScores[STUDENT_NUM] = {0}; // 存储每个学生的总分
// 输入学生信息和成绩
for (int i = 0; i < STUDENT_NUM; i++) {
cout << "请输入第" << i+1 << "个学生姓名:";
cin >> names[i];
cout << "请输入" << names[i] << "的语文、数学、英语成绩(用空格分隔):";
for (int j = 0; j < SUBJECT_NUM; j++) {
cin >> scores[i][j];
totalScores[i] += scores[i][j];
}
}
// 输出成绩统计
cout << "\n===== 成绩统计 =====\n";
cout << "姓名\t语文\t数学\t英语\t总分\t平均分\n";
for (int i = 0; i < STUDENT_NUM; i++) {
double avg = totalScores[i] / (double)SUBJECT_NUM;
cout << names[i] << "\t"
<< scores[i][0] << "\t"
<< scores[i][1] << "\t"
<< scores[i][2] << "\t"
<< totalScores[i] << "\t"
<< avg << endl;
}
return 0;
}
七、今日学习总结
-
一维数组:
- 定义:
数据类型 数组名[长度];,长度必须是常量 - 初始化:全部初始化、部分初始化、省略长度初始化
- 常见操作:遍历、求和、求最值、逆序
- 核心算法:冒泡排序(n-1 轮,每轮 n-1-i 次比较)
- 定义:
-
二维数组:
- 定义:
数据类型 数组名[行数][列数]; - 初始化:按行初始化、省略行数初始化
- 遍历:嵌套循环,外层控制行,内层控制列
- 定义:
-
数组注意事项:
- 下标从 0 开始,避免越界
- 数组名是常量指针,不能赋值
- 不能直接赋值整个数组
- 用
sizeof(数组名)/sizeof(元素)计算数组长度
✍️ 下节预告
下一篇将正式进入 C++ 函数核心基础:函数的定义、函数的调用、值传递、函数的声明、函数的分文件编写,掌握函数可以将复杂程序拆分为独立模块,提高代码复用性和可维护性,为后续学习函数高级特性和面向对象编程打下坚实基础。