CC++ & Algorithm

二维数组:像一张表格或电影院座位

困难7
语言版本:C++
概述:二维数组就像一个表格,有行和列,可以帮助我们存储更复杂的数据,比如教室座位表。

二维数组:像一张表格或电影院座位

我们学过一维数组是一排储物柜,只能存一列数据。那如果想存一张表格怎么办?比如全班同学的成绩单:有行(每个同学)和列(语文、数学、英语)。这就是二维数组!它像一张表格,也像电影院的座位:有(第几排)和(第几号)。在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表示墙壁。

新手容易犯的错误

  1. 下标越界
    如果数组是 arr[3][4],只能用下标02行、03列。用 arr[3][4] 会越界,程序可能崩溃或输出奇怪的值。

  2. 行列顺序搞反
    定义 arr[3][4] 表示3行4列。访问时先写行再写列。如果把行当列用,会访问到错误位置甚至越界。

  3. 忘记初始化
    局部数组(函数内定义)的元素值是随机的(垃圾值)。需要显式赋值或初始化。可以用 {} 初始化部分或全部:

    int arr[2][3] = {{1,2,3}, {4,5,6}};  // 全部初始化
    int brr[2][3] = {};                   // 全部初始化为0
    
  4. 循环边界写错
    比如定义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

相关指引

  • 一维数组:二维数组的基础。先掌握一维数组,再学二维。
  • 字符串:字符数组可以看作二维数组的一行,但字符串处理有特殊函数。
  • 多维数组:三维数组像魔方,理解二维后可以推广。
  • 结构体:当数据有不同的类型(如姓名和分数),用结构体数组比二维数组更灵活。

现在,你可以用二维数组来存储任何表格数据:班级座位、游戏地图、购物清单、日历……动手试试吧!

例题精讲

1单选题

在C++中,定义了一个二维数组int a[3][4];,那么a[2][3]表示的是?

A第2行第3列的元素
B第3行第4列的元素
C第3行第3列的元素
D第2行第4列的元素
2判断题

在C++中,二维数组在内存中是以行优先的方式存储的,即先存完第一行所有元素,再存第二行,以此类推。

3单选题

下列哪个选项能正确遍历一个3行4列的二维数组arr并输出所有元素?

Afor(int i=0;i<3;i++) for(int j=0;j<4;j++) cout<<arr[i][j];
Bfor(int i=0;i<4;i++) for(int j=0;j<3;j++) cout<<arr[j][i];
Cfor(int i=0;i<3;i++) for(int j=0;j<3;j++) cout<<arr[i][j];
Dfor(int i=0;i<4;i++) for(int j=0;j<4;j++) cout<<arr[i][j];
4填空题
下面的函数用于计算一个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;
}
5判断题

在C++中,二维数组int a[2][3] = {{1,2},{3,4,5}};的初始化是合法的,数组a中a[0][2]的值为0。