首页 > 编程笔记

C语言二维数组的定义、赋值和初始化

二维数组是相对一维数组来说的,所谓二维数组,就是带有行和列的数组,就像表格一样。

C语言二维数组的定义

C语言二维数组定义的一般形式为:

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

例如:

int a[3][4];   /*定义a为3行4列的数组*/
int b[5][10];  /*定义b为5行10列的数组*/

不能写成下面的形式:

int a[3,4];  /*错误的数组定义*/
int b[5,10];  /*错误的数组定义*/

我们之前了解过一维数组元素在内存中占用一块连续的存储区域,二维数组是什么样的情况?以a[3][4]为例,数组元素在内存中存储的形式如下图所示。

二维数据是按照行存储的,每个整型元素占 4 个字节(数组 a 是 int 类型)。先依次保存第 1 行所有元素,再依次保存第 2 行所有元素……直到所有行元素全部保存。


已知 a[0][0] 在内存中的地址,a[1][2] 的地址是多少呢?计算方法如下。

注意,如果定义了数组 a[3][4],则元素下标的变化范围,行号范围是 0~2,列号范围是 0~3。

C语言二维数组的初始化

同一维数组一样,二维数组的初始化也可以有以下两种形式。

1)先定义再初始化

int a[3][4];
a[0][0]=1;
a[2][3] = 9;

2)定义的同时初始化

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

或者:

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

二维数组在内存中是按照线性顺序存储的,所以行括号可以省去。

还可以这样:

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

或者:

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

省去行数 3 也是可以的,但是列数 4 不能省去。编译器会根据所赋数值的个数及数组的列数,自动计算出数组的行数。

分析下面的二维数组初始化后的值:

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

可以认为二维数组是由 3 个一维数组构成的,每个一维数组有 4 元素,这就可以和一维数组初始化对应上。经过上述初始化,数组 a 元素值的形式如下表所示。

C语言二维数组元素的引用

二维数组元素的操作和一维数组元素的操作相似,一般使用双重循环遍历数组的元素,外层循环控制数组的行标,内层循环控制数组的列标,如下所示:
int i,j;
int array[3][4];
for(i=0;i<3;i++)
{
    for(j=0;j<4;j++)
    {
       array[i][j]=4*i+j;
    }
}
经过上面双循环的初始化操作,数组 array 元素的值是 {0,1,2,3,4,5,6,7,8,9,10,1 1}。

原因是 4*i+j,i 表示行号,j 表示列号,首先赋值 i=0 的行的数组元素值 {0,1,2,3},内层循环结束,接下来外层循环变量 i=1,继续对数组元素第 2 行赋值 {4,5,6,7},这样反复进行,就会得到所有元素的值。

C语言二维数组的应用举例

下面通过两个实际应用的例子,介绍C语言二维数组的使用方法和技巧。

示例1

求一个 3×3 矩阵从左上到右下的对角线元素之和。请看下面代码:
#include <stdio.h>
int main()
{
  float a[3][3],sum=0;
  int i,j;
  printf("请输入3*3个元素:\n");
  for(i=0;i<3;i++)       /*循环输入9个元素*/
  {
     for(j=0;j<3;j++)
        scanf("%f",&a[i][j]);
  }
  for(i=0;i<3;i++)    /*计算对角元素和*/
     sum=sum+a[i][i];
  printf("左上到右下一条对角线元素和为 %6.2f\n",sum);
  return 0;
}
运行结果:

请输入3*3个元素:
9 8 7
3 5 4
1 2 3
左上到右下一条对角线元素和为  17.00

本示例对 3 行 3 列的数组 a 进行双循环依次赋值。由于二维数组在内存中存储的形式是一行结束后再从下一行开头继续存储,呈“Z”字形,因此输入数据的顺序也按照这个方式。

计算二维数组对角元素的和时,对角线元素的特点是行号和列号相同,所以无须使用双重循环遍历数组,使用单循环就足够了,运算时取数组的行号和列号相等即可。

示例2

将一个二维数组的行和列元素互换,存到另一个二维数组中,实现数组的转置。请看下面代码:
#include <stdio.h>
int main(void)
{
  int a[2][3]={{1,2,3},{4,5,6}};   /*数组a*/
  int b[3][2],i,j;
  printf("array a:\n");
  for (i=0;i<=1;i++)
  {
    for (j=0;j<=2;j++)
    {                 
      printf("%5d",a[i][j]);   /*输出数组a*/
      b[j][i]=a[i][j];        /*行列互换存储到数组b中*/
    }
    printf("\n");
  }
  printf("array b:\n");
  for(i=0;i<=2;i++)       /*输出数组b*/
  {
    for(j=0;j<=1;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

行列互换的关键是对下标的控制,如果没有找到正确的方法,那么数组将被弄得一团糟。定义原数组 a 是 a[2][3],是 2 行 3 列,转置后新数组 b 是 b[3][2],是 3 行 2 列。

实现行列互换的代码如下:

b[j][i]=a[i][j];

巧妙地使用行号和列号的交换就可以实现转置。

优秀文章