C++二维数组的定义和使用(入门必读)
平时大家提到的数组,通常指的是一维数组,它只有一个下标,常用来存储线性的数据,比如 {1,2,3,4,5}。
而在实际的应用中,有的数据用线性结构不好表示,例如下面的矩阵:
二维数组是常见的多维数组,常用于矩阵运算、图像处理和游戏开发等多个领域。虽然可以定义三维、四维甚至更高维数的数组,但实际用得也少。
定义二维数组的语法格式如下:
例如,定义一个 3 行 4 列的整数二维数组:
二维数组可以看做是将一维数组作为数组元素的一维数组,其初始化可以看做多个一维数组的初始化。
初始化二维数组的格式如下:
访问二维数组元素的格式如下:
例如:
例如:
在内存空间中,二维数组是一行一行连续存储的,也就是说先存放 a[0] 行,再存放 a[1] 行,再存放 a[2] 行,以此类推。
下面的程序中,分别定义一个长度为 9 的一维数组和一个 3×3 的二维数组,然后输出其各元素的地址:
而在实际的应用中,有的数据用线性结构不好表示,例如下面的矩阵:
1 0 0 0 1 0 0 0 1这是一个 3 行 3 列的矩阵。当然可以用一个长度为 9 的数组来存储这些数据,但是却不能表现出数据的逻辑结构。因此 C++ 语言允许构造多维数组,多维数组元素有多个下标,以标识在数组中的位置。
二维数组是常见的多维数组,常用于矩阵运算、图像处理和游戏开发等多个领域。虽然可以定义三维、四维甚至更高维数的数组,但实际用得也少。
二维数组的定义
二维数组的定义与一维数组相似,也需要指定数组元素的类型。不同的是,二维数组需要两个大小参数,分别表示数组的行数和列数。定义二维数组的语法格式如下:
类型 数组名[行数][列数];其中,行数和列数必须是程序编译时可以计算出的值,要么是常量,要么是常量表达式。
例如,定义一个 3 行 4 列的整数二维数组:
int num[3][4];
二维数组的初始化
二维数组在定义的时候也可以直接初始化。二维数组可以看做是将一维数组作为数组元素的一维数组,其初始化可以看做多个一维数组的初始化。
初始化二维数组的格式如下:
类型 数组名[行数][列数]= { {值, 值, ......}, {值, 值, ......}, ...... }里面的花括号中的值分别用来初始化二维数组的每一行,即第一个花括号中的值初始化第一行,第二个花括号中的值初始化第二行,不足的部分用 0 来补齐。
1) 完全初始化
手动指定二维数组中全部元素的值,例如:int num[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };完全初始化二维数组时,可以省略每一行元素的大括号:
int num[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
2) 部分初始化
如果没有为所有元素提供初始值,则剩余元素会被初始化为零。例如:int num[3][4] = { {1, 2, 3}, {5, 6} };num 数组中存储的元素分别是:
1 2 3 0 5 6 0 0 0 0 0 0
3) 行大小自动推断
可以让编译器自动推断二维数组的行数。例如:int num[][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; // 编译器自动推断行数为 3
注意,只能省略二维数组的行数,列数不能省略。
二维数组的使用
使用二维数组主要涉及访问、修改和遍历数组中的元素。1) 访问数组元素
同一维数组一样,使用下标访问二维数组中的每个元素,不过要使用两个下标,分别指明元素所在的行号和列号。访问二维数组元素的格式如下:
数组名[行号][列号];同一维数组的访问一样,这两个下标都需要是整型常量或者变量。例如:
#include <iostream> int main() { int num[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int value = num[1][2]; // 访问第二行第三列的元素 std::cout << value << std::endl; return 0; }输出结果为:
7
2) 修改数组元素
要想修改二维数组中某个元素的值,只能通过下标的方法先找到要操作的元素,然后再进行处理。例如:
#include <iostream> int main() { int num[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; std::cout << "修改前:" << num[1][2] << std::endl; num[1][2] = 100; // 修改数组中第二行第三列的元素 std::cout << "修改后:" << num[1][2] << std::endl; return 0; }输出结果为:
修改前:7
修改后:100
3) 遍历数组元素
遍历二维数组,通常借助嵌套的循环结构实现。例如:
#include <iostream> int main() { int num[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; //嵌套的循环结构遍历 num 数组 for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { std::cout << num[i][j] << " "; } std::cout << std::endl; } return 0; }输出结果为:
1 2 3 4
5 6 7 8
9 10 11 12
二维数组的底层存储
虽然可以用二维数组来表示一个矩阵,但系统并不允许程序按照这种方式存储数据。二维数组的行、列表现形式只是便于对二维数组的理解,事实上二维数组的存储和一维数组一样,都是线性的结构。在内存空间中,二维数组是一行一行连续存储的,也就是说先存放 a[0] 行,再存放 a[1] 行,再存放 a[2] 行,以此类推。
下面的程序中,分别定义一个长度为 9 的一维数组和一个 3×3 的二维数组,然后输出其各元素的地址:
#include <iostream> int main() { // 定义一个长度为 9 的一维数组 int array1D[9]={1,2,3,4,5,6,7,8,9}; // 定义一个 3×3 的二维数组 int array2D[3][3]={1,2,3,4,5,6,7,8,9}; // 输出一维数组的各个元素的地址 std::cout << "一维数组的元素地址和值:\n"; for(int i = 0; i < 9; i++) { std::cout << "array1D[" << i << "]: " << &array1D[i] <<" " << array1D[i] << std::endl; } // 输出二维数组的各个元素的地址 std::cout << "\n二维数组的元素地址和值:\n"; for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { std::cout << "array2D[" << i << "][" << j << "]: " << &array2D[i][j] <<" " << array2D[i][j] << std::endl; } } return 0; }运行结果为:
array1D[0]: 012FFB90 1 array1D[1]: 012FFB94 2 array1D[2]: 012FFB98 3 array1D[3]: 012FFB9C 4 array1D[4]: 012FFBA0 5 array1D[5]: 012FFBA4 6 array1D[6]: 012FFBA8 7 array1D[7]: 012FFBAC 8 array1D[8]: 012FFBB0 9 二维数组的元素地址和值: array2D[0][0]: 012FFB64 1 array2D[0][1]: 012FFB68 2 array2D[0][2]: 012FFB6C 3 array2D[1][0]: 012FFB70 4 array2D[1][1]: 012FFB74 5 array2D[1][2]: 012FFB78 6 array2D[2][0]: 012FFB7C 7 array2D[2][1]: 012FFB80 8 array2D[2][2]: 012FFB84 9从结果中可以看到,在内存的存储方式上,一维数组和二维数组是相同的。对于程序里定义的二维数组来说,元素 array2D[0][2] 和元素 array2D[1][0] 是相邻的。