二维数组:像一张表格或电影院座位
困难7二维数组:像一张表格或电影院座位
我们学过一维数组是一排储物柜,只能存一列数据。那如果想存一张表格怎么办?比如全班同学的成绩单:有行(每个同学)和列(语文、数学、英语)。这就是二维数组!它像一张表格,也像电影院的座位:有行(第几排)和列(第几号)。在C++里,我们可以用二维数组来存放所有表格类数据。
什么是二维数组?
二维数组就是“数组的数组”。可以想象成一个棋盘,格子按行和列排列。每个格子都有两个坐标:行号(从0开始)和列号(从0开始)。比如教室里有3行座位,每行4个座位,就需要一个3行4列的二维数组来记录每个座位坐的是谁。
如何定义二维数组?
格式:类型 数组名[行数][列数];
例如:
int grades[3][4]; // 3行,每行4个整数,共12个格子
行数和列数必须是常量(可以用 const 变量)。数组一旦定义,行数和列数固定。
如何访问二维数组的元素?
用两个下标:数组名[行下标][列下标]。
- 行下标范围:0 到 行数-1
- 列下标范围:0 到 列数-1
例如:
grades[0][1] = 95; // 第1行第2列(下标0行,1列)赋值为95
cout << grades[2][3]; // 输出第3行第4列的值
? 注意:下标从0开始!第1行对应下标0,第1列对应下标0。
用双重循环遍历二维数组
访问所有元素最常用的方法就是用双重循环:外层循环遍历每一行,内层循环遍历每一列。
就像你按顺序检查电影院每一排的每一个座位一样。
// 定义一个3行4列的二维数组
int seats[3][4]; // 3排,每排4个座位
// 输入数据
for (int row = 0; row < 3; row++) { // row:行号
for (int col = 0; col < 4; col++) { // col:列号
cin >> seats[row][col];
}
}
// 输出数据
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 4; col++) {
cout << seats[row][col] << " ";
}
cout << endl; // 每行输出后换行,形成表格
}
生活中的例子:记录一周的零花钱
假设你想记录一周(7天)里每天花在零食和文具上的钱。可以用一个2行7列的二维数组:
- 行0:零食花费
- 行1:文具花费
- 列:星期一~星期天
#include <iostream>
using namespace std;
int main() {
const int ROWS = 2; // 2类:零食和文具
const int COLS = 7; // 7天
int spend[ROWS][COLS]; // 二维数组:存放花费
cout << "请输入一周7天零食和文具的花费(先零食,后文具):" << endl;
for (int r = 0; r < ROWS; r++) { // r: 行,0零食,1文具
for (int c = 0; c < COLS; c++) { // c: 列,0~6对应周一~周日
cin >> spend[r][c];
}
}
// 计算本周零食总花费
int total_snack = 0; // 零食总花费
for (int c = 0; c < COLS; c++) {
total_snack += spend[0][c]; // 第0行是零食
}
cout << "本周零食总花费:" << total_snack << "元" << endl;
return 0;
}
另一个常见例子:游戏地图——用二维数组表示迷宫,0表示空地,1表示墙壁。
新手容易犯的错误
-
下标越界
如果数组是arr[3][4],只能用下标02行、03列。用arr[3][4]会越界,程序可能崩溃或输出奇怪的值。 -
行列顺序搞反
定义arr[3][4]表示3行4列。访问时先写行再写列。如果把行当列用,会访问到错误位置甚至越界。 -
忘记初始化
局部数组(函数内定义)的元素值是随机的(垃圾值)。需要显式赋值或初始化。可以用{}初始化部分或全部:int arr[2][3] = {{1,2,3}, {4,5,6}}; // 全部初始化 int brr[2][3] = {}; // 全部初始化为0 -
循环边界写错
比如定义3行却循环i < 4,会越界。常犯错误:忘记行数列数从0开始,写成i <= 行数。
完整示例:输入班级成绩并计算每科平均分
假设有3个同学,每个同学考了4科(语文、数学、英语、科学)。我们想输入成绩,然后输出每科的平均分。
#include <iostream>
using namespace std;
int main() {
const int STU = 3; // 学生人数(行数)
const int SUB = 4; // 科目数(列数)
int grades[STU][SUB]; // 3行4列的成绩表
// 输入成绩
cout << "请依次输入" << STU << "个同学" << SUB << "科成绩:" << endl;
for (int i = 0; i < STU; i++) { // i: 学生编号(行)
for (int j = 0; j < SUB; j++) { // j: 科目编号(列)
cin >> grades[i][j];
}
}
// 计算每科平均分
cout << "各科平均分:" << endl;
for (int j = 0; j < SUB; j++) { // 遍历每一列(科目)
int sum = 0; // 该科总分
for (int i = 0; i < STU; i++) { // 累加所有学生的该科成绩
sum += grades[i][j];
}
double avg = (double)sum / STU; // 平均分
cout << "科目" << j+1 << ": " << avg << endl;
}
return 0;
}
运行示例:
请依次输入3个同学4科成绩:
88 90 76 85
92 87 91 80
78 85 79 88
各科平均分:
科目1: 86
科目2: 87.3333
科目3: 82
科目4: 84.3333
相关指引
- 一维数组:二维数组的基础。先掌握一维数组,再学二维。
- 字符串:字符数组可以看作二维数组的一行,但字符串处理有特殊函数。
- 多维数组:三维数组像魔方,理解二维后可以推广。
- 结构体:当数据有不同的类型(如姓名和分数),用结构体数组比二维数组更灵活。
现在,你可以用二维数组来存储任何表格数据:班级座位、游戏地图、购物清单、日历……动手试试吧!
例题精讲
在C++中,定义了一个二维数组int a[3][4];,那么a[2][3]表示的是?
在C++中,二维数组在内存中是以行优先的方式存储的,即先存完第一行所有元素,再存第二行,以此类推。
下列哪个选项能正确遍历一个3行4列的二维数组arr并输出所有元素?
下面的函数用于计算一个3行4列的二维数组所有元素之和,请将代码补充完整。
int sumArray(int arr[3][4]) {
int sum = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
sum += ___;
}
}
return sum;
}在C++中,二维数组int a[2][3] = {{1,2},{3,4,5}};的初始化是合法的,数组a中a[0][2]的值为0。