7.2 二维数组的定义和引用
考点3 二维数组的定义及其元素的引用
1.二维数组的定义
在C语言中,二维数组中元素排列的顺序是:按行存放,即在内存中先按顺序存放第一行的元素,再存放第二行的元素。因此,二维数组元素的存储与一维数组元素存储相类似,总是占用一块连续的内存单元。
二维数组的一般形式为:
类型说明符 数组名[常量表达式][常量表达式];
例如:intc[3][4];
定义c为3 ×4(3行4列)的数组。注意:不能写成c[3,4]。C语言对二维数组采用这样的定义方式:可以把二维数组当作是一种特殊的一维数组。
例如,可以把c看成是一个一维数组,它有3个元素c[0]、c[1]、c[2],每个元素又是一个包含4个元素的一维数组。可以把c[0]、c[1]、c[2]看做是3个一维数组的名字。
真考链接
考点3偏难,属于重点理解重点掌握知识点。在选择题中的考核概率为90%。在操作题中,主要出现在编程题中,一般用于处理数据比较多的实际问题,考核概率为20%。
2.二维数组元素的引用
二维数组的表示形式为:
数组名[下标表达式1][下标表达式2]
数组的下标可以是整型表达式,如 c[3-1][3 ×2-2]。
数组元素可以出现在表达式中,也可以被赋值,如a[1][3] =b[3][2]/2。
小提示
定义数组时用的c[3][4]和引用元素时的c[3][4]的区别:前者用来定义数组的维数和各维的大小,共有3行4列;后者中的3和4是下标值,c[3][4]代表该数组中的一个元素。如果a[3][4]是二维数组中最后一个元素,那么该数组共有4行5列。
真题精选
【例1】有以下程序,最后输出的值为( )。
main()
{ int a[4][4] = {{1,4,3,2},{8,6,5,7},{3,7,2,5},{4,8,6,1}},i,j,k,t;
for(i = 0;i <4;i++)
for(j = 0;j < 3;j++)
for(k = j+1;k <4;k++)
if(a[j][i] > a[k][i])
{t=a[j][i];a[j][i] =a[k][i];a[k][i] =t;}
for(i=0;i<4;i++)printf("% d,",a[i][i]);
}
A.1,6,5,7 B.8,7,3,1 C.4,7,5,2 D.1,6,2,1
【答案】A
【解析】本题用多重for循环的嵌套来实现对二维数组的按列排序。利用最外层循环来实现对列的控制。内部循环利用选择法对数组元素按照从小到大的顺序进行排列,最后输出对角线上的元素值。
【例2】若二维数组a有m列,则在a[i][j]之前的元素个数为( )。
A.j*m+i B.i*m+j C.i*m+j-1 D.i*m+j+1
【答案】B
【解析】在C语言中,由于二维数组在内存中是按照行优先的顺序存储的(即先顺序存储第0行元素,再存第1行元素,依次类推),且下标的起始值为0,因此在a[i][j]之前的元素有i*m+j个。
【例3】以下程序的输出结果是( )。
#include <stdio.h>
main()
{ int i,x[3][3] ={1,2,3,4,5,6,7,8,9};
for(i=0;i<3;i++)
printf("% d,",x[i][2-i]);
}B.1,4,7,
A.1,5,9, C.3,5,7, D.3,6,9,
【答案】C
【解析】本题考查了二维数组的初始化赋值问题,读者需要清楚地了解在二维数组中逻辑存放结构的情况。
【例4】以下不能正确定义二维数组的选项是( )。
A.inta[2][2] ={{1},{2}}; B.inta[][2] ={1,2,3,4};
C.inta[2][2] ={{1},2,3}; D.inta[2][] ={{l,2},{3,4}};
【答案】D
【解析】C语言中明确规定,在定义二维数组时,后一个下标值不能省略,否则将无法判定数组中某一行的元素个数。
【例5】请编写函数fun(),其功能是:找出2*M整型二维数组中最大元素的值,并将此值返回调用函数。
注意:部分源程序给出如下。
请勿改动主函数main()和其他函数中的任何内容,仅在函数fun()的花括号中填入你编写的若干语句。
试题程序
#define M 4
#include <stdio.h>
int fun(int a[][M])
{
}
void main()
{ int arr[2][M] ={5,8,3,45,76,-4,12,82};
printf("max=% d\n",fun(arr));
}
【答案】int fun(int a[ ][M])
{ int i,j,max=a[0][0];
for(i=0;i<2;i++)
for(j=0;j<M;j++)
if(max<a[i][j])
max=a[i][j];
return max;
}
【解析】本题要求数组的最大值,需要运用循环语句,因为数组是二维数值,所以应使用两层加for循环嵌套。使用for循环语句时需要注意循环变量的取值范围。
对于此类求最大值或最小值的问题,可以采用逐个比较的方式,要求对数组中所有元素遍历一遍,并且从中找出数组最大值或最小值。首先定义变量max存放在数组中的第一个元素的值,然后利用for循环逐个找出数组中的元素,并与max比较,如果元素值大于max,则将该值赋予max,循环结束后max的值即为数组最大值,最后将该值返回。
考点4 二维数组的初始化
真考链接
考点4 属于重点掌握知识点。尤其要注意数组下标是从0开始的,这一点在引用数组里的元素时要注意。对此知识点的考查主要以选择题的形式出现,考核概率为40%。
可以在定义二维数组的同时给二维数组的各元素赋初值。例如:
float m[2][2] ={{1.5,3.2},{0.8}};
全部初值放在一对花括号中,每一行的初值又分别括在一对花括号中,之间用逗号隔开。当某行一对花括号内的初值个数少于该行中元素的个数时,系统将自动地给后面的元素补初值0。同样,不能跳过每行前面的元素而给后面的元素赋初值。
数组是一种构造类型的数据。二维数组可以看做是由一维数组的嵌套而构成的。如果一维数组的每个元素又都是一个数组,就组成了二维数组(前提是各元素类型必须相同)。
由此也可以这样分析,一个二维数组也可以分解为多个一维数组。C语言允许这样分解二维数组,如a[3][4]可分解为3个一维数组,其数组名分别为a[0],a[1],a[2]。对这3个一维数组不需另做说明即可使用。这3个一维数组都有4个元素,一维数组a[0]的元素为a[0][0],a[0][1],a[0][2],a[0][3]。必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量。
对于一维数组,可以在数组定义语句中省略方括号中的常量表达式,通过所赋初值的个数来确定数组的大小;对于二维数组,只可以省略第一个方括号中的常量表达式,而不能省略第二个方括号中的常量表达式。例如:
int a[ ][3] ={{1,2,3},{4,5},{6},{8}};
a数组的第一维方括号中的常量表达式省略,在所赋初值中,含有4个花括号,则第一维的大小由花括号的个数来决定。因此,该数组其实是与a[4][3]等价的。当用以下形式赋初值时:
int c[][3] ={1,2,3,4,5};
第一维的大小按以下规则决定:
(1)当初值的个数能被第二维的常量表达式的值除尽时,所得商数就是第一维的大小。
(2)当初值的个数不能被第二维的常量表达式的值除尽时,则:
第一维的大小 =所得商数+1
因此,按此规则,以上c数组第一维的大小应该是2,也就是说语句等同于intc[2][3] ={1,2,3,4,5};。
小提示
如果一个二维数组的最后一个元素的下标是a[5][5],则说明此二维数组有6行6列。即要注意,数组的下标是从0开始的。
常见问题
在程序中定义一个数组用来存储数据,通常会给其所有元素赋初值为0,为什么?
如果定义了一个数据而未给其赋初值,系统会自动给其赋随机值,为了避免在运算中造成不必要的麻烦,通常给其赋初值,这也是一个良好的编程习惯。
真题精选
【例1】下面程序输出的结果是( )。
main()
{ int i;
int a[3][3] = {1,2,3,4,5,6,7,8,9};
for(i=0;i<3;i++)
printf("% d ",a[2-i][i]);
}
A.159 B.753 C.357 D.591
【答案】B
【解析】本题用循环的方法考查对数组概念的掌握。首先,当i=0时,数组中的位置是a[2][0] =7,当然,如果用排除法,就不用考虑后面的循环,因为在4个选项中,第1个数为7的选项只有B。本题执行第2次循环时,i的值为1,则printf函数中的数组指向为a[1][1] =5,依次循环,可求出答案。
【例2】以下数组定义错误的是( )。
A.intx[][3] ={0}; B.intx[2][3] ={{1,2}, {3,4}, {5,6}};
C.intx[][3] ={{1,2,3}, {4, ,5 6}}; D.intx[][3] ={1,2,3,4,5,6};
【答案】B
【例3】以下能正确定义数组并正确赋初值的选项是( )。
【解析】二维数组的初始化有以下几种形式:①分行进行初始化;②不分行的初始化;③部分数组元素初始化;④省略第一维的定义,不省略第二维的定义。选项B等号右边分了3行,大于等号左边数组的行数。
A.intN=5,b[N][N]; B.inta[1][2] ={{1},{3}};
C.intc[2][] ={{1,2},{3,4}}; D.intd[3][2] ={{1,2},{3,4}};
【答案】D
【解析】选项A中,数组的下标应为整型变量;选项B的行下标应为2;选项C的列下标不能省略。
【例4】以下能对二维数组a进行正确初始化的选项是( )。
A.inta[2][] ={{1,0,1},{5,2,3}}; B.inta[][3] ={{1,2,3},{4,5,6}};
C.inta[2][4] ={{1,2,3},{4,5},{6}}; D.inta[][3] ={{1,0,1},{},{1,1}};
【答案】B
【解析】本题考查了对二维数组初始化的基本语法问题,读者需要清楚地了解初始化二维数组的基本格式。
【例5】已知int类型的变量占4个字节有下面的程序段:
main()
{ int a[ ][3] ={{1,2,3},{4,5},{6},{8}};
printf("% d",sizeof(a));
}
则程序段的输出结果是( )。
A.12 B.24 C.48 D.64
【答案】C
【解析】程序通过赋初值的方式定义了4行3列的数组,则大小为12,而一个int变量占4个字节,所以程序输出48。
【例6】有以下程序:
main()
{
int m[][3] ={1,4,7,2,5,8,3,6,9};
int i,j,k=2;
for(i=0;i<3;i++)
{printf("% d ",m[k][i]);}
}
执行后输出的结果是( )。
A.456 B.258 C.369 D.789
【答案】C
【解析】本题的功能是输出m[2][0],m[2][1]和m[2][2]。
【例7】下列给定程序中,函数fun()的功能是:求ss所指字符串数组中长度最短的字符串所在的行下标,作为函数值返回,并把其串长放在形参n所指的变量中。ss所指字符串数组中共有M个字符串,且串长小于N。请在标号处填入正确的内容,使程序得出正确的结果。
注意:部分源程序给出如下。不得增行或删行,也不得更改程序的结构。
试题程序
#include <stdio.h>
#include <string.h>
#define M 5
#define N 20
int fun(char(*ss)[N],int *n)
{ int i,k=0,len= N;
for(i=0;i<【1】;i++)
{ len=strlen(ss[i]);
if(i==0)*n=len;
if(len【2】*n){
*n=len;
k=i;
}
}
return(【3】);
}
main()
{ charss[M][N] ={"shanghai","guangzhou "," beijing "," tianjing ","chongqing"};
int n,k,i;
printf("\nThe original strings are:\n");
for(i=0;i<M;i++)puts(ss[i]);
k=fun(ss,&n);
printf(" \nThe length of shortest string is:% d\n",n);
printf("\nThe shortest string is:% s\n",ss[k]);
}
【答案】【1】M 【2】 < 【3】k
【解析】本题考查:for循环语句的循环条件;if语句条件表达式;return语句完成函数值的返回。
标号【1】:题目指出ss所指字符串数组中共有M个字符串,所以for循环语句的循环条件是i<M。
标号【2】:要求长度最短的字符串,*n中存放的是已知字符串中长度最短的字符串的长度,这里将当前字符串长度与*n比较,若小于*n,则将该长度值赋给*n,因此,if语句的条件表达式为len<*n。
标号【3】:将最短字符串的行下标作为函数值返回,变量k存储行下标的值。