printf("theresultis:
\n");
for(i=1;i<=4;i++)
printf("%d:
%d\n",i,c[i]);
printf("\n");
}
7.2二维数组
一、二维数组中的基本语法
1.二维数组的定义语法
数据类型数组名[整型常量表达式1][整型常量表达式2];
说明:
二维数组有两维长度,用整型常量表达式1的值表示第一维长度,用整型常量表达式2的值表示第一维长度2。
例如,inta[3][4],b[4][5];
2.二维数组的语法本质
使用二维数组时要注意,其实C语言中并没有真正的二维数组,二维数组只不过是数组中的数组,即二维数组是由若干一维数组组成的特殊数组。
对于前面定义的二维数组a,由于它的第一维长度为3,所以数组a是由3个一维数组组成的,这3个一维数组的名字分别是a[0],a[1]和a[2]。
数组a的第二维长度说明组成a的每个一维数组又分别拥有4个数组元素,例如,一维数组a[0]包括的4个元素为a[0][0]、a[0][1]、a[0][2]、a[0][3];a[1]包括的4个元素为a[1][0]、a[1][1]、a[1][2]、a[1][3];
a[2]包括的4个元素为a[2][0]、a[2][1]、a[2][2]、a[2][3]。
【例7.3】验证二维数组是特殊的一维数组。
#include
main()
{
inta[3][4];
printf("sizeof(a)=%d\n",sizeof(a));
printf("sizeof(a[0])=%d\n",sizeof(a[0]));
}
通常情况下,我们都是直观地理解二维数组:
数组a为3×4(3行4列)的二维数组,数组b为4×5(4行5列)的二维数组。
3.二维数组元素内存分布
例如,shorta[3][4];数组a中有12个元素,每个元素占2个字节,所以系统需为数组a分配连续的24个字节。
先为一维数组a[0]中的元素a[0][0]~a[0][3]各分配2字节,接下来的8个字节依次分配给a[1][0]~a[1][3],a[2][0]~a[2][3]获得最后的8个字节。
【例7.4】验证在为二维数组元素分配内存字节数时遵循行优先的原则。
#include
main()
{
shorta[2][4];
printf("a[0][0]=%#x\n",&a[0][0]);
printf("a[0][1]=%#x\n",&a[0][1]);
printf("a[0][2]=%#x\n",&a[0][2]);
printf("a[0][3]=%#x\n",&a[0][3]);
printf("a[1][0]=%#x\n",&a[1][0]);
printf("a[1][1]=%#x\n",&a[1][1]);
printf("a[1][2]=%#x\n",&a[1][2]);
printf("a[1][3]=%#x\n",&a[1][3]);
}
4.二维数组的初始化
只要理解二维数组是由若干一维数组构成的,就不难理解二维数组的初始化语法了。
(1)用多个初始化列表初始化二维数组中的每个一维数组
例如,inta[3][4]=
{
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
说明:
在给一维数组初始化时,我们可以省略数组中某些元素的初值,例如:
intb[4]={1,2};则b[2]和b[3]的初值就为0,同理有,inta[3][4]={{1},{5,6},{9,10,11}};
【课内思考题7.3】设inta[4][2009];怎样将数组a的所有元素初始化为0?
(2)用一个初始化列表初始化二维数组
例如,inta[3][4]={1,2,3,4,5,6,7};
(3)省略二维数组第一维长度
例如,inta[][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
当用一个初始化列表初始化二维数组并且省略该二维数组的第一维长度的情况下,例如inta[][4]={1,2,3,4,5,6,7};如果计算其第一维长度?
答案是[初值个数/第二维长度]。
数组a的第二维长度应为2。
二、二维数组应用举例
【例7.5】遍历二维数组
#include
#defineN3
#defineM4
main()
{
inta[N][M];/*行下标范围:
0~N-1,列下标范围:
0~M-1*/
inti,j;
/*外循环遍历二维数组每一行*/
for(i=0;ifor(j=0;jscanf("%d",&a[i][j]);
for(i=0;i{
for(j=0;jprintf("%-5d",a[i][j]);
printf("\n");
}
}
【例7.6】在二维数组a中选出各行最大的元素,组成一个一维数组b。
#include
main()
{
inta[3][4]={
{3,6,-1,4},
{0,-2,7,3},
{-5,8,3,9}
};
intb[3];
inti,j;
for(i=0;i<3;i++)
{
/*从一维数组a[i]中找出最大值,存储到b[i]*/
intindex=0;
for(j=1;j<4;j++)
if(a[i][j]>a[i][index])index=j;
b[i]=a[i][index];
}
for(i=0;i<3;i++)
printf("%d",b[i]);
printf("\n");
}
【例7.7】求矩阵中值最大的元素
#include
#defineN3
#defineM4
main()
{
inta[N][M];
inti,j;
intmax,row,col;
for(i=0;ifor(j=0;jscanf("%d",&a[i][j]);
max=a[0][0];row=0;col=0;
for(i=0;ifor(j=0;jif(a[i][j]>max)
{
max=a[i][j];
row=i;col=j;
}
printf("max=%d,row=%d,col=%d\n",max,row+1,col+1);
}
7.3字符数组
一、字符数组的相关语法
1.使用字符数组存储若个字符
C语言字符数组的基本使用方法和前面介绍的一维数组和二维数组类似。
只是数组类型变为char,数组中的每个元素相当于一个字符变量,可以存储一个字符的ASCII码。
【例7.8】字符数组的初始化、输入与输出。
#include
#defineN5
main()
{
chars1[]={'J','i','a','X','i','n','g'};/*s1省略数组长度定义*/
chars2[10]={'H','a','n','g','Z','h','o','u'};/*s2[8]和s2[9]中存储'\0'*/
chars3[4][8]={
{'W','e','n','Z','h','o','u'},/*s3[0][7]存储'\0'*/
{'T','a','i','Z','h','o','u'},/*s3[1][7]存储'\0'*/
{'N','i','n','g','','b','o'},/*s3[2][7]存储'\0'*/
{'H','u','','Z','h','o','u'}/*s3[3][7]存储'\0'*/
};
chars4[N];
inti;
for(i=0;ifor(i=0;iprintf("\n");
for(i=0;iprintf("%c",s1[i]);
printf("\n");
for(i=0;s2[i]!
='\0';i++)
printf("%c",s2[i]);
for(i=0;i<4;i++)
{
intj=0;
while(s3[i][j]!
='\0')
{
printf("%c",s3[i][j]);
j++;
}
printf("\n");
}
}
说明:
在给一维字符数组或者二维字符数组中某个一维字符数组初始化时,若省略了某些元素的初值,这些字符数组元素中存放字符'\0'。
2.使用字符数组存储字符串
其实在C语言中,字符数组主要被用于存储由若干字符组成的字符串。
(1)一维字符数组存储一个字符串
例如,charstr[]={"Iamhappy"};或charstr[]="Iamhappy";其中str[10]中存放字符串结束符'\0'的ASCII码。
用一个字符串初始化字符数组的做法等价于抽取一个字符串中的每个字符(包括串结束符)放在初始化列表中去初始化字符数组。
例如,charstr[]={'I','','a','m','','h',
'a','p','p','y','\0'};
字符数组中所存储的字符串长度和字符数组本身的长度不并一致。
有如下数组定义:
charstr1[10]="china";
charstr2[]="abcde";
charstr3[]="abc\0d\0e";
charstr4[]="";
chars[16]="4$*0;\0p\0+\0";
【课内思考题7.4】请大家分析以上这些字符数组中所存储的字符串的串长和这些字符数组的长度?
(2)二维字符数组存储多个字符串
例如,charss[4][9]={"WenZhou","TaiZhou","HangZhou","HuZhou"};
说明:
二维字符数组是由多个一维字符数组组成,每个一维字符数组可以单独存储一个字符串,所以一个二维数组能存储多个字符串。
值得注意的是,二维字符数组的第二维长度至少应该是所存储的所有字符串中最大的串长加1。
3.单个字符串的输入与输出
通过gets函数(或scanf函数)实现字符串的输入,输入的字符串存储在某个字符数组中;通过puts函数(或printf函数)输出字符数组中字符串。
#include
#defineN20
main()
{
chars1[N],s2[8];
gets(s2);/*scanf("%s",s2);*/
puts(s2);/*printf("%s",s2);*/
}
说明:
用函数scanf实现输入的缺点是,用户输入的字符串不能包含空格。
因为空格被当作输入结束处理,这种情况下就只能用函数gets实现输入了。
另外,水平制表和回车也被认为是输入结束。
4.多个字符串的输入与输出
#include
#defineM3/*存储M个字符串*/
#defineN10/*单个字符串的最大长度不能超过N-1*/
main()
{
charss[M][N];
inti;
for(i=0;ifor(i=0;i