📄 一句话概括
引用二维数组的某一格,要写两对方括号:数组名[行下标][列下标]。千万别写成 a[i, j]——那会变成 3.1.9 的逗号表达式,等价于 a[j],离你想取的格子十万八千里。遍历整张表就用两层 for:外管行、内管列。
📝 本节和前面几节的关系
7.2.1 把表订好了,这一节学"怎么取表里某一格"。a[i][j] 里的两个下标各自独立,每对方括号就是一次查找(第一对方括号先定位到某一行,第二对再定位到行里的某一格)——这正是 7.5.2"用指针遍历"能成立的原因。遍历它要两层循环,也就是 5.4 学过的"外圈一格 = 内圈一整圈"。
一、引用的写法
数组名[行下标][列下标]
int a[3][4] = {
{85, 92, 78, 90},
{60, 75, 88, 95},
{100, 55, 70, 80}
};
a[0][0] // 85 —— 第 0 行第 0 列
a[1][2] // 88 —— 第 1 行第 2 列
a[2][3] // 80 —— 最后一格
a[1][2] = 99; // 也能赋值(左值,3.4)
下标对照表(行列都从 0 起):
| 想要 | 写什么 |
|---|---|
| 第 1 行第 1 列 | a[0][0] |
| 第 i 行第 j 列 | a[i-1][j-1] |
| 最后一行最后一列 | a[2][3](3 行 4 列时) |
| 不存在的 | a[3][0]、a[0][4] —— 越界 |
二、a[i, j] 为什么是坑
新手很容易把两个下标写成 a[i, j]。它能编过,但意思完全变了:
a[i, j] ≡ a[j] // 逗号取末值(3.1.9),只留下 j
而 a[j] 是"第 j 行整行"(在 7.5.2 会知道它其实是个地址),不是"第 i 行第 j 列"。你想取一个数,拿到的是一个地址——结果当然全错,而且不报错。
口诀:一行一对括号,两行两对。
三、遍历:两层 for 二次上岗
for (int i = 0; i < 行数; i++) { // 外层:走行
for (int j = 0; j < 列数; j++) { // 内层:走列
// 在这里用 a[i][j]
}
}
这就是 5.4 说的"外圈一格 = 内圈一整圈":外层 i 每走一步,内层 j 就把这一行从左到右走完。所以总的"进去多少次" = 行 × 列。
四、动手 Demo:三种常见处理
#include <iostream>
using namespace std;
int main() {
int a[3][4] = {{85, 92, 78, 90},
{60, 75, 88, 95},
{100, 55, 70, 80}};
int rows = sizeof(a) / sizeof(a[0]); // 3(7.2.1)
int cols = sizeof(a[0]) / sizeof(a[0][0]); // 4
cout << "---- 原表 ----" << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) cout << a[i][j] << "\t";
cout << endl;
}
cout << "---- 每行总和 ----" << endl;
for (int i = 0; i < rows; i++) {
int rowSum = 0;
for (int j = 0; j < cols; j++) rowSum += a[i][j];
cout << "第 " << i + 1 << " 行 = " << rowSum << endl;
}
cout << "---- 全表最大值 ----" << endl;
int mx = a[0][0]; // 从第 0 行第 0 列起步
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if (a[i][j] > mx) mx = a[i][j];
cout << "最大 = " << mx << endl;
return 0;
}
看到什么算成功:原表 3 行 4 列;每行总和依次是 345、318、305;最大值 100。
三个套路的要点:
| 任务 | 关键写法 | 注意 |
|---|---|---|
| 打印整表 | 双层循环 + \t 对齐 |
内层走完要 endl 换行 |
| 每行求和 | rowSum 声明在外层、清 0 在外层 |
放错位置就会累加成"全表总和" |
| 找全表最大 | 初值取 a[0][0],其余全比一遍 |
别取 0——全是负数时就错了 |
30 秒实验:把 int rowSum = 0; 挪到外层循环之前(两层循环外面),重跑。"每行总和"会变成 345、663、968——越滚越大,因为累加器再也没清零。这个错误极常见,值得亲手犯一次。
五、常见误区
- "
a[i, j]就是a[i][j]"——不是。逗号运算只剩j,取到的是整行地址而不是一格。两行两对括号。 - "外层行、内层列可以随我换"——语法上可以,但换完之后"每行求和"就变成了"每列求和"(数值会不一样)。先想清楚你要按行还是按列。
- "越界会报错"——和 7.1.2 一样,不报错。行下标到
rows、或列下标到cols,都在悄悄踩内存。 - "求和变量放在哪都一样"——见上面的实验。"按行分组"的变量必须在行循环里清零。
自测三问(点开对答案)
1. 二维数组怎么取第 i 行第 j 列?——`a[i][j]`,**两对方括号**。 2. `a[i, j]` 等价于什么?——`a[j]`(逗号取末值),取到的是整行而不是一格。 3. "每行求总和"的累加变量应该声明在哪里?——在**外层(行)循环体内**,每进一行重新清零。- ☐ 7.2.3 二维数组的初始化(下一节)
相关笔记
- 二维数组的声明 —— 两对方括号的来历
- 一维数组的引用 —— 越界不报错的老坑
- 循环的嵌套 —— 外圈一格、内圈一整圈
- 逗号运算符 ——
a[i, j]的坑源 - 🔷 C++基础 · 索引 —— 全课路线图