6.2 怎样定义和引用二维数组

6.2 怎样定义和引用二维数组

在前面的章节中已经提到,有些问题需要用二维数组来处理。比如说,有3个小分队,每个分队有6名队员,我们需要保存这些队员的工资信息供日后查询。此时,我们就需要用到二维数组,如图 6.6 所示。如果我们创建一个名为 pay 的数组,它应该是一个二维数组,第一维用于表示分队编号,第二维用于表示队员编号。例如,pay[1][2] 表示第二分队第三名队员的工资为 1725。

图 6.6:工资表示例

队员1   队员2   队员3   队员4   队员5   队员6
1分队  2456   1847   1243   1600   2346   2757
2分队  2018   1725   2020   2458   1436
3分队  1427   1175   1046   1976   1477   2018

二维数组通常被称为矩阵(matrix),它以行和列的形式排列,这种结构可以帮助我们形象地理解二维数组的逻辑结构。

6.2.1 怎样定义二维数组

二维数组的定义方式和一维数组相似。例如:

float pay[3][6];

以上代码定义了一个 float 类型的二维数组,第一维表示有 3 个元素,第二维表示有 6 个元素。每一维的长度分别用一对方括号括起来。

二维数组的定义格式如下:

类型说明符 数组名[常量表达式][常量表达式];

类型说明符 数组名[常量表达式][常量表达式];

例如:

float n[3.4], b[5.10];  // 错误的数组定义

这行代码定义了两个数组:a 是 3×4(3 行 4 列)的数组,b 是 5×10(5 行 10 列)的数组。需要注意的是,不能在方括号内写两个下标:

a[0] → a[0][0], a[0][1], a[0][2], a[0][3]
a[1] → a[1][0], a[1][1], a[1][2], a[1][3]
a[2] → a[2][0], a[2][1], a[2][2], a[2][3]

二维数组可以看作特殊的一维数组,其每个元素都是一个一维数组。例如,a 可以看作是一个有 3 个元素的一维数组,每个元素都是一个包含 4 个元素的一维数组,如图 6.7 所示。

图 6.7:二维数组的结构

a[0] → a[0][0], a[0][1], a[0][2], a[0][3]
a[1] → a[1][0], a[1][1], a[1][2], a[1][3]
a[2] → a[2][0], a[2][1], a[2][2], a[2][3]

在 C 语言中,二维数组的元素按行存储。在内存中,首先顺序存放第一行的元素,然后存放第二行的元素,以此类推。图 6.8 和图 6.9 显示了二维数组 a[3][4] 在内存中的存放顺序和位置。

图 6.8:二维数组的排列方式

第 0 行元素
a[0][0], a[0][1], a[0][2], a[0][3]
第 1 行元素
a[1][0], a[1][1], a[1][2], a[1][3]
第 2 行元素
a[2][0], a[2][1], a[2][2], a[2][3]

图 6.9:二维数组在内存中的存放位置

2000  a[0][0]
2004  a[0][1]
2008  a[0][2]
2012  a[0][3]
2016  a[1][0]
2020  a[1][1]
2024  a[1][2]
2028  a[1][3]
2032  a[2][0]
2036  a[2][1]
2040  a[2][2]
2044  a[2][3]

C 语言还允许使用多维数组。有了二维数组的基础,掌握多维数组就不难了。定义三维数组的方法如下:

float a[2][3][4];

这段代码定义了一个三维数组 a,它有 2 页,3 行,4 列。多维数组的元素在内存中的排列顺序是:第 1 维的下标变化最慢,最右边的下标变化最快。例如,以上三维数组的元素排列顺序如下:

 

css

Copy code

a[0][0][0] → a[0][0][1] → a[0][0][2] → a[0][0][3] → a[0][1][0] → a[0][1][1] → a[0][1][2] → a[0][1][3] a[0][2][0] → a[0][2][1] → a[0][2][2] → a[0][2][3] → a[1][0][0] → a[1][0][1] → a[1][0][2] → a[1][0][3] a[1][1][0] → a[1][1][1] → a[1][1][2] → a[1][1][3] → a[1][2][0] → a[1][2][1] → a[1][2][2] →

6.2.2 怎样引用二维数组的元素

二维数组中的元素使用数组名和两个下标来表示,格式为:数组名[行下标][列下标]。例如,a[2][3] 表示数组 a 中,第 2 行第 3 列的元素。下标可以是整型表达式,例如:a[2-1][2*2-1]。需要注意的是,不要使用逗号来分隔下标,避免像 a[2, 3]a[2-1, 2*2-1] 这样的表示方式。

数组元素既可以出现在表达式中,也可以被赋值。例如:

b[1][2] = a[2][3] / 2;

注意:在引用数组元素时,务必确保下标值在定义的数组范围内,否则会产生数组越界错误。例如:

int a[3][4];
// 定义一个 3×4 的二维数组 a
a[3][4] = 3; // 错误的操作:不存在 a[3][4] 元素

根据定义,数组 a 中“行下标”的有效范围是 0~2,“列下标”的有效范围是 0~3。因此,a[3][4] 超过了数组的有效范围。

提示:请严格区分定义数组时使用的 a[3][4] 和引用数组元素时的 a[3][4]。在定义数组时,a[3][4] 表示数组的维数和每一维的大小;而引用元素时,a[3][4] 中的 3 和 4 是元素的下标值,表示数组第 4 行第 5 列的元素(数组的行序号和列序号都是从 0 开始的)。

6.2.3 二维数组的初始化

可以使用“初始化列表”来初始化二维数组:

  1. 按行赋初值:例如:

    int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
    

    这种方式很直观,每一对花括号中的数据都会被赋值给相应的行。例如,第一个花括号内的数值赋给第 1 行,第二个花括号内的数值赋给第 2 行,以此类推。

  2. 所有数据在一个花括号内:例如:

    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    

    该方式的效果和上面相同,但建议优先使用第一种方式,因为每一行都有独立的花括号,界限明确。如果所有数据都放在一个花括号内,容易遗漏数据或出错。

  3. 部分元素赋初值

    只为各行的某些元素赋初值,其他元素自动为 0。例如:

    int a[3][4] = {{1}, {5}, {9}};
    

    这只对每行的第 1 列(下标为 0)赋值,其他列会自动初始化为 0。结果如下:

    1 0 0 0
    5 0 0 0
    9 0 0 0
    

    或者只给某行的某些列赋初值,例如:

    int a[3][4] = {{1}, {0, 6}, {0, 0, 11}};
    

    初始化后的数组元素为:

    1 0 0 0
    0 6 0 0
    0 0 11 0
    

    这种方法在非 0 元素较少时非常方便,不必为所有的 0 元素都手动赋值。

  4. 省略第一维长度

    如果为所有元素赋值,则可以省略第一维的长度,但第二维的长度不能省略。例如:

    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int a[][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    

    这两种方式的效果相同,系统会根据总元素数量和第二维的长度来计算第一维的长度。这里共有 12 个元素,每行 4 列,因此可以确定行数为 3。

    如果只对部分元素赋初值且省略第一维长度,仍需按行初始化。例如:

    int a[][4] = {{10, 0, 3}, {}, {0, 10}};
    

    这样,系统可以知道数组共有 3 行。

通过这些初始化方法,C 语言的二维数组定义和初始化方式非常灵活。它使用 a[][] 这种两个方括号的方式,让初始化清晰易懂,方便使用且不容易出错。

6.2.4 二维数组程序举例

例 6.4:将一个二维数组的行和列元素互换,存储到另一个二维数组中。

解题思路:定义两个数组:a 为 2 行 3 列,用于存储指定的 6 个数;b 为 3 行 2 列,初始时为空。只需将 a[i][j] 元素存储到 b[j][i] 中。通过嵌套 for 循环完成。

程序代码

#include <stdio.h>

int main() {
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int b[3][2], i, j;

    // 输出数组 a
    printf("Array a:\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 3; j++) {
            printf("%5d", a[i][j]);
            b[j][i] = a[i][j];  // 将 a[i][j] 的值赋给 b[j][i]
        }
        printf("\n");
    }

    // 输出数组 b
    printf("Array b:\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 2; j++) {
            printf("%5d", b[i][j]);
        }
        printf("\n");
    }

    return 0;
}

运行结果

Array a:
    1    2    3
    4    5    6
Array b:
    1    4
    2    5
    3    6

例 6.5:在一个 3×4 的矩阵中,找出值最大的元素,以及其所在的行号和列号。

解题思路:用“打擂台算法”来找到矩阵中的最大值。首先,让 a[0][0] 作“擂主”,把它赋值给变量 max,作为当前已知的最大值。然后让下一个元素 a[0][1]max 比较,如果 a[0][1]max 大,则将 a[0][1] 赋给 max,并记下其所在的行号和列号。循环比较完所有元素,max 就是最大值。

程序代码

#include <stdio.h>

int main() {
    int i, j, row = 0, column = 0, max;
    int a[3][4] = {{1, 2, 3, 4}, {9, 8, 7, 6}, {-10, 10, -5, 2}}; // 定义并初始化数组

    // 假定 a[0][0] 是最大值
    max = a[0][0];

    // 遍历二维数组,找出最大值
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 4; j++) {
            if (a[i][j] > max) {
                max = a[i][j]; // 更新最大值
                row = i; // 记录最大值的行号
                column = j; // 记录最大值的列号
            }
        }
    }

    // 输出最大值及其所在行号和列号
    printf("max = %d\nrow = %d\ncolumn = %d\n", max, row, column);

    return 0;
}

运行结果

max = 10
row = 2
column = 1

最大值是 10,在数组 a 的第 3 行第 2 列,即 a[2][1]。

 

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值