CC++ & Algorithm

C++二维数组的遍历

困难14
语言版本:C++Python
概述:学会用双重循环(就像按行和按列扫地)来访问二维数组的每一个元素。

二维数组遍历:像扫地一样扫过每一个格子

想象你有一张班级座位表,每个座位上坐着一个同学,你想知道全班同学的总零花钱。你需要一个格子一个格子地看,不能漏掉任何一个座位。在C++里,这种“把表格里所有格子都看一遍”的操作就叫二维数组的遍历。学会它,你就能轻松处理所有像成绩表、游戏地图、购物清单这样的“表格数据”。

什么是二维数组?什么是遍历?

二维数组就像一张方格纸,有。比如一个3行4列的数组,可以存储3个同学的4门科目成绩。遍历就是按某种顺序,把每个格子里的数据都访问一次——好比一个清洁机器人,沿着走廊扫完每一行每一列,确保每个角落都干净。

在C++中,二维数组定义时用两个方括号:int score[3][4]; 第一个数字是行数,第二个是列数。索引从0开始,所以第0行是第一个同学,第0列是第一门课。

用双重循环来遍历:外层管行,内层管列

最常用的方法是用嵌套循环:外层循环遍历每一行,内层循环遍历每一列。就像这样:

for (int row = 0; row < 行数; row++) {        // 外层:一行一行地走
    for (int col = 0; col < 列数; col++) {    // 内层:每一行里一列一列地看
        // 在这里处理 arr[row][col]
    }
}

变量 rowcol 分别代表行号和列号。为什么这样写?因为先固定行,再变列,正好和我们平时读书、看表格的习惯一致——从左到右,从上到下。

生活中的例子:统计班级零花钱

假设有3个同学,每个同学有4天攒的零花钱(单位:元)。我们想算全班总零花钱。

#include <iostream>
using namespace std;

int main() {
    // 3行4列:3个同学,每个人4天的零花钱
    int money[3][4] = {
        { 5,  8,  3,  6},   // 第0个同学:周一5元,周二8元……
        {10, 12,  7,  9},   // 第1个同学
        { 4,  6,  5, 11}    // 第2个同学
    };

    int total = 0;           // 总零花钱,初始为0
    int rows = 3;            // 行数=同学数
    int cols = 4;            // 列数=天数

    for (int r = 0; r < rows; r++) {      // 遍历每位同学
        for (int c = 0; c < cols; c++) {  // 遍历每位同学的所有天数
            total += money[r][c];         // 累加这个格子的值
        }
    }

    cout << "全班总零花钱是:" << total << "元" << endl;
    return 0;
}

运行结果:全班总零花钱是:86元

换个方向遍历:先列后行(竖着扫)

有时候我们需要“竖着”处理数据,比如看一个星期里,每一天全班的总零花钱。这时只要交换内外循环的角色:

for (int c = 0; c < cols; c++) {          // 外层:先固定列(星期几)
    for (int r = 0; r < rows; r++) {      // 内层:遍历所有同学
        // 处理 money[r][c]
    }
}

这样就会先访问第0列的所有行(周一所有同学的钱),再访问第1列……结果就是按星期几统计。

不过大部分场景我们习惯“先遍历行再遍历列”,因为更符合直觉。两种方式没有对错,看你要解决的问题。

常见错误:千万小心这些坑

1. 索引越界

新手最容易犯的错:忘记数组索引从0开始。比如一个3行的数组,最大行号是2(因为0、1、2)。如果你写成 for (int i = 0; i <= 3; i++),当 i=3 时就会访问到数组之外的内存,轻则得到奇怪结果,重则程序崩溃。

正确写法for (int i = 0; i < 行数; i++) 注意 < 不是 <=

2. 行列弄反

定义 int a[3][4]; 意思是3行4列。如果你在遍历时把行数和列数弄反,比如外层写 i < 4,内层写 j < 3,依然能跑,但访问的顺序和逻辑就乱了。尤其当数组不是正方形时,会导致数组越界。

记住:外层循环控制行,行数就是第一个方括号里的数字;内层循环控制列。

3. 忘记初始化遍历控制变量

有时候为了节省代码,有人会这样写:

int i = 0;
for (; i < rows; ) {
    for (int j = 0; j < cols; j++) {
        // ...
    }
    i++;
}

这种写法虽然可行,但容易混淆,不如标准写法清晰。建议永远用 for (int i = 0; i < rows; i++) 的形式。

完整示例:打印成绩表并计算平均分

下面这个程序先让用户输入每个同学的3科成绩,然后打印出整个表格,最后输出每个同学的平均分。

#include <iostream>
using namespace std;

int main() {
    const int student = 3;          // 同学人数
    const int subject = 3;          // 科目数

    int score[student][subject];    // 存储成绩的二维数组

    // 输入成绩
    cout << "请输入" << student << "位同学的" << subject << "科成绩:" << endl;
    for (int i = 0; i < student; i++) {          // i 表示第几位同学
        cout << "第" << i + 1 << "位同学:";
        for (int j = 0; j < subject; j++) {      // j 表示第几科
            cin >> score[i][j];
        }
    }

    // 打印成绩表格(遍历输出)
    cout << "\n成绩表如下:" << endl;
    cout << "姓名\t语文\t数学\t英语" << endl;
    for (int i = 0; i < student; i++) {
        cout << "同学" << i + 1 << "\t";
        for (int j = 0; j < subject; j++) {
            cout << score[i][j] << "\t";
        }
        cout << endl;  // 每行结束后换行
    }

    // 计算每个同学的平均分(按行遍历)
    cout << "\n每位同学的平均分:" << endl;
    for (int i = 0; i < student; i++) {
        int sum = 0;                      // 当前同学的总分
        for (int j = 0; j < subject; j++) {
            sum += score[i][j];
        }
        double avg = (double)sum / subject;  // 转换成小数计算
        cout << "同学" << i + 1 << "的平均分:" << avg << endl;
    }

    return 0;
}

运行这个程序,你可以输入3位同学的成绩,系统会自动输出表格和平均分。

总结与相关指引

二维数组的遍历是基本功,就像练武必须扎马步一样。掌握了它,你就能做更多有趣的事:

  • 矩阵运算:比如把两张照片(矩阵)叠加
  • 游戏地图:比如迷宫每个格子是墙壁还是路
  • 图像处理:把一张图片的像素当成二维数组,放大、旋转
  • 动态规划:经典的背包问题、最短路径问题都要用二维数组来存储中间结果

如果你已经熟悉遍历,接下来可以学习:

  • 二维数组作为函数参数:如何把表格传给函数处理
  • 多维数组:三维数组(比如立体魔方)的遍历思路类似,只是多加一层循环
  • 二维数组与指针:更深入地理解数组在内存中的存储方式

遍历是一门手艺,多练习几个小项目,比如打印乘法口诀表、统计考试成绩、制作简单的扫雷游戏地图,你很快就会成为“表格高手”。

例题精讲

1单选题

已知二维数组 int arr[4][5]; 下列代码片段中,能够正确按行遍历数组所有元素的是( )

Afor(int i=0; i<4; i++) for(int j=0; j<5; j++) cout<<arr[i][j];
Bfor(int i=0; i<5; i++) for(int j=0; j<4; j++) cout<<arr[i][j];
Cfor(int i=1; i<=4; i++) for(int j=1; j<=5; j++) cout<<arr[i][j];
Dfor(int i=0; i<=4; i++) for(int j=0; j<=5; j++) cout<<arr[i][j];
2判断题

遍历二维数组时,若外层循环控制列,内层循环控制行,则可以实现按列遍历。

3填空题
下列代码计算二维数组int a[3][4]所有元素的和,请补全内层循环的条件。
int sum = 0;
for (int i = 0; i < 3; i++) {
    for (int j = 0; ___; j++) {
        sum += a[i][j];
    }
}
4单选题

int a[2][3] = {{1,2,3},{4,5,6}}; for (int i=0; i<2; i++) for (int j=0; j<3; j++) cout << a[j][i] << " "; 运行上述代码会得到什么结果?

A输出 1 4 2 5 3 6
B输出 1 2 3 4 5 6
C输出 4 1 5 2 6 3
D运行时越界错误
5填空题
下列代码按列遍历二维数组int b[3][4](先输出第0列所有行,再第1列……),请补全内层循环的条件。
for (int col = 0; col < 4; col++) {
    for (int row = 0; ___; row++) {
        cout << b[row][col] << " ";
    }
}