1、第 8章 数组类型 第第 8章章 数组类型数组类型 8.1 一维数组一维数组 8.2 二维数组与多维数组二维数组与多维数组 8.3 字符数组与字符串字符数组与字符串 8.4 重命名类型重命名类型 8.5 程序设计举例程序设计举例 第 8章 数组类型 8.1 一维数组一维数组 8.1.1 一维数组的定义一维数组的定义 形式:类型标识符 数组名常量;类型标识符描述的是数组分量的类型,是定义数组类型的基类型,可以是任何类型。数组名代表数组所占存储空间的首地址。常量表示数组的长度,即数组中分量的个数。第 8章 数组类型 例如,定义数组,描述下列数据:(1)100个整数:int num100;(2)10
2、00个学生C语言课程的成绩:float ccj1000;(3)一年中每月的天数:int month12;(4)100种商品的价格:float price100;(5)500个字符类型的数据:char ch500;第 8章 数组类型 说明:(1)数组名命名规则和变量名命名规则相同,都遵循标识符命名规则。(2)数组的长度可以用符号常量描述,但不能用变量,C语言不提供动态数组。(3)数组以线性方式将数组分量依次存储,所占空间等于各分量所占空间之和,即数组分量个数乘以基类型数据所占空间。第 8章 数组类型 8.1.2 一维数组的引用一维数组的引用 数组元素称为下标变量,下标变量通过数组名、下标表达式和
3、中括号运算来描述。下标变量的形式为:数组名下标表达式 例如,对以上定义的num数组、ccj数组,num数组的100个分量为num0、num1、numi、num99,每个分量存放一个整数,numi相当于一个int型变量;ccj数组的1000个分量为ccj1、ccj2、ccji、ccj999,每个分量对应一个学生的成绩,ccji相当于一个float型变量。第 8章 数组类型 说明:(1)下标的取值范围从0到数组长度减1。(2)下标变量相当于基类型变量。(3)下标往往对应于循环控制变量,通过循环、通过下标的变化完成数组所有元素的操作,即整个数组的操作。(4)下标往往隐含有特定的含义。(5)对于下标出
4、界,C语言不进行语法检查。第 8章 数组类型 如果希望下标为i的分量对应第i个数据,可将定义数组的大小增1,如:int num101;float ccj1001;100个整数用num数组的分量num1、num2、num1、num100描述,numi对应于第i个整数。1000个学生的C语言成绩用ccj数组的分量ccj1、ccj2、ccji、ccj1000描述,ccji对应于第i个学生的成绩。第 8章 数组类型 8.1.3 一维数组的初始化一维数组的初始化 初始化形式:存储类别 类型 数组名常量=常量1,常量2,常量n;初始化数据用花括号括起。第 8章 数组类型 例如:(1)static int
5、month12=31,29,31,30,31,30,31,31,30,31,30,31;month0=31,month1=29,month2=31,month3=30,month4=31,month5=30,month6=31,month7=31,month8=30,month9=31,month11=30,month12=31 (2)static char ch5=a,e,i,o,u;ch0=a,ch1=e,ch2=i,ch3=o,ch4=u 第 8章 数组类型 说明:(1)对静态存储数组和外部存储数组,默认初值为0。(2)可以只给一部分数组元素初始化。例如:static int a 50=
6、70,75,60,80,90;相当于a0=70,a1=75,a2=60,a3=80,a4=90,后面没有给出的数组元素之值全部为0。第 8章 数组类型 (3)对数组中全部元素给定初值,可以不给定数组长度,它的长度为后面给出的初值个数。例如:static float x=1.5,2.5,3.5,4.5,5.5;数组x有5个数组元素x0、x1、x2、x3、x4,长度为5。(4)若仅给部分数组元素赋值,则不能省略数组长度。第 8章 数组类型 例例 8 1 求10个数的最大值与最小值,10个数用数组描述。/*程序8 1 求10个数的最大值与最小值*/main()float a10;int i;floa
7、t max=-1e20,min=1e20;for(i=0;i=9;i+)/*输入 10 个数*/scanf(%f,&ai);for(i=0;imax)max=ai;if(aimin)min=ai;printf(最大值=%f,最小值=%f,max,min);第 8章 数组类型 例例 8 2 求某班50个学生C语言课程的平均成绩及每个学生与平均成绩之差。/*程序8-2求C语言课程的平均成绩及每个学生与平均成绩之差*/main()float ccj51;/*C语言成绩数组*/int i;float tcj=0.0;float av,cav51;/*平均成绩av,与平均成绩之差数组cav*/for(i
8、=1;i=50;i+)/*输入每个学生成绩*/第 8章 数组类型 printf(请输入第%d个学生成绩:,i);scanf(“%f”,&ccji);for(i=1;i=50;i+)/*求平均成绩*/tcj+=ccji;av=tcj/50;for(i=1;i=50;i+)/*求与平均成绩之差*/cavi=ccji-av;printf(C语言课程的平均成绩=%5.2fn,av);/*输出*/for(i=1;i=50;i+)printf(第%d个学生与平均成绩之差=%5.2n,i,cavi);第 8章 数组类型 例例 8-3 用一维数组求Fibonacci数列前20项,要求每行输出5个数。/*程序8
9、-3,求Fibonacci数列前20项*/main()static int a20=1,1;/*存放Fibonacci数列前20项的数组*/int i;for(i=2;i20;i+)fi=fi-1+fi-2;printf(Fibonacci数列前20项如下:n);for(i=2;i20;i+)printf(%8d,fi);if(i%5=0)printf(n);/*if语句用来控制换行*/*程序8-3,求Fibonacci数列前20项*/main()static int a20=1,1;/*存放Fibonacci数列前20项的数组*/int i;for(i=2;i20;i+)fi=fi-1+fi
10、-2;printf(Fibonacci数列前20项如下:n);for(i=2;i20;i+)printf(%8d,fi);if(i%5=0)printf(n);/*if语句用来控制换行*/第 8章 数组类型 运行结果:Fibonacci数列前20项如下:1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 第 8章 数组类型 8.1.4 一维数组作函数参数一维数组作函数参数 例例 8-4 将例8-2中求C语言课程平均成绩改用函数实现。函数如下:float avf(xcj)/*求C语言课程平均成绩*/float xc
11、j51;int i;float sum=0.0,tav;for(i=1;i=50;i+)sum+=xcji;tav=sum/50;return(tav);第 8章 数组类型 主函数中调用函数avf()来求平均成绩:av=avf(ccj);此时,实参数组为ccj,对应的形参数组为xcj,调用时将实参数组ccj首地址传递给形参数组xcj。请注意本例中数组的第一个分量ccj0、xcj0无意义。对形参数组可以不指定数组大小,在定义数组时数组名后跟空的中括号。在函数中另设一个参数,传递数组元素的个数。如此在函数中实现变相动态数组。第 8章 数组类型 例例 8-5 将上例中函数延伸考虑为求n个学生C语言课
12、程平均成绩。函数如下:float avf(xcj,n)/*求n个学生C语言课程平均成绩*/float xcj,n;int i;float sum=0.0,tav;for(i=1;i=n;i+)sum+=xcji;tav=sum/n;return(tav);第 8章 数组类型 8.2 二维数组与多维数组二维数组与多维数组 8.2.1 二维数组的定义二维数组的定义 形式:类型标识符 数组名常量1常量2;n维数组的定义形式:类型标识符 数组名常量1常量2常量n;类型标识符描述的同样是数组分量的类型,是定义数组类型的基类型,可以是任何类型。数组名代表数组所占存储空间的首地址。常量分别表示数组相应维的长
13、度,数组长度以及数组中分量个数分别等于常量1、常量2、常量n。第 8章 数组类型 (1)上述100个班,每班50个学生一门课程的成绩,定义如下二维数组描述:float cj10050;/*第一维对应班级,第二维对应学生*/(2)1000个学生,30门课程的成绩,定义如下二维数组描述:float acj100030;/*第一维对应学生,第二维对应课程*/(3)上述某高校社会实践调查数据,定义如下三维数组描述:int b323;/*第一维对应年级,第二维对应性别,第三维对应交通工具*/第 8章 数组类型 8.2.2 二维数组的引用二维数组的引用 下标变量的形式为:数组名下标表达式1下标表达式2 多
14、维数组下标变量的形式为:数组名下标表达式1下标表达式2 下标表达式n 例如,对以上定义的acj数组3000个分量分别为:acj00、acj01、acj029、acj10、acj11、acj129、acj9990、acj9991、acj99929,左边下标变化最慢,右边下标变化最快,右边下标变化一遍,左边下标才变化一次。每个分量对应一个学生一门课程的成绩,acjij相当于一个float型变量。第 8章 数组类型 说明:(1)每个下标的取值范围从0到数组长度减1,下标变量同样相当于基类型变量。(2)对于多维数组整体操作的完成需用多重循环,一个下标对应于一重循环控制变量。二维数组的整体操作用两重循环
15、完成,外重循环对应下标1,内重循环对应下标2。(3)其它类似于一维数组处理。第 8章 数组类型 8.2.3 二维数组的初始化二维数组的初始化 初始化形式:存储类别 类型 数组名下标1下标2=常量1,常量2,常量n;例如:static int a34=1,2,3,4,5,6,7,8,9,10,11,12;a00=1,a01=2,a02=3,a03=4,a10=5,a11=6,a12=7,a13=8,a20=9,a21=10,a22=11,a23=12 第 8章 数组类型 说明:(1)二维数组的初始化可以分行进行。例如,上面的a数组初始化还可以表示为:static int a34=1,2,3,4,
16、5,6,7,8,9,10,11,12;而定义4行3列的b数组可以表示为:static int b43=1,2,3,4,5,6,7,8,9,10,11,12;(2)可以只对数组中部分元素初始化。例如:a00=1,a01=2,a10=5,a20=9,其它分量初值取默认值,为0。第 8章 数组类型 (3)如果对二维数组中全部元素初始化,则定义数组时第一维的长度可以省略,但第二维的长度不能省略。例如:static int a34=1,2,3,4,5,6,7,8,9,10,11,12;可以写成 static int a 4=1,2,3,4,5,6,7,8,9,10,11,12;但不能写成 static
17、int a =1,2,3,4,5,6,7,8,9,10,11,12;因为两个维数都省略时,可以理解为1*12、12*1、3*4、4*3、2*6、6*2等多种形式,会发生混淆,故只能省略第一个维数。第 8章 数组类型 (4)如果对二维数组按行进行初始化,则定义数组时第一维的长度也可以省略。例如:static int a 4=1,2,5,9;对于二维数组与多维数组作函数参数跟一维数组作函数参数类同处理,但对形参数组,只有第一维的大小可以省略,第二维及其它高维的大小均不能省略。第 8章 数组类型 例例 8-6 从键盘输入50个学生8门课程成绩,求每个学生的总成绩与平均成绩。/*程序8-6,求总成绩及
18、平均成绩*/main()float cj519;int i,j;float tcj51,acj51;void tcjf();void acjf();for(i=1;i=50;i+)/*输入成绩*/printf(请输入第%d个学生8门课程成绩:,i);for(j=1;j=8;j+)scanf(%f,&cjij);第 8章 数组类型 tcjf(cj,tcj);/*调用函数tcjf()求总成绩*/acjf(tcj,acj);/*调用函数acjf()求平均成绩*/printf(所求学生总成绩与平均成绩如下:n);/*输出处理结果*/for(i=1;i=50;i+)printf(第%d个学生总成绩=%6
19、.2f,平均成绩=%5.2fn,tcji,acji);void tcjf(xcj,xtcj)/*求总成绩函数*/float xcj519,xtcj51;int i,j;for(i=1;i=50;i+)for(xtcji=0.0,j=1;j=8;j+)xtcji+=xcjij;void acjf(xtcj,xacj)/*求平均成绩*/float xtcj51,xacj51;int i;for(i=1;i=50;i+)xacji=xtcji/8;第 8章 数组类型 例例 8-7 编写程序,求两个34的整数矩阵之和。/*程序8-7,求两个34的矩阵之和*/main()int a34,b34;int
20、i,j;int c34;for(i=0;i3;i+)/*输入矩阵a*/for(j=0;j4;j+)scanf(%d,&aij);for(i=0;i3;i+)/*输入矩阵b*/for(j=0;j4;j+)scanf(%d,&bij);for(i=0;i3;i+)/*计算矩阵c*/for(j=0;j4;j+)第 8章 数组类型 cij=aij+bij;printf(所求和矩阵如下:n);/*输出处理结果*/for(i=0;i3;i+)/*输出矩阵c*/for(j=0;j=0&linei=a&linei=A&linei=Z)num1+;else num2+;printf(数字字符数=%d字母字符数=
21、%d其它字符数=%d,num0,num1,num2);第 8章 数组类型 例例 8-10 求80个字符串中的最大者。main()char str8020;/*假定字符串的最大长度不超过20个字符*/int i;char mstr20;for(i=0;i20;i+)gets(stri);strcpy(mstr,str0);for(i=1;i0)strcpy(mstr,stri);printf(字符串中的最大者=%s,mstr);第 8章 数组类型 8.4 重命名类型重命名类型 8.4.1 重命名类型方法重命名类型方法 一般形式:typedef 已有类型 新类型名;如:(1)typedef int
22、 integer;/*重命名整型*/integer i,j;第 8章 数组类型(2)typedef int COUNT;/*命名一计数类型COUNT*/COUNT n1,n2;(3)typedef int NUM100;/*命名一整型数组类型NUM*/NUM n;(4)typedef char STRING81;/*命名一字符串类型STRING*/STRING str1,str2;(5)typedef struct int day;int month;int year;DATE;/*命名一结构体类型DATE*/DATE date1,date2;第 8章 数组类型 8.4.2 重命名类型的作用重
23、命名类型的作用(1)有利于加强数据描述的针对性,增加程序的可读性。(2)有利于程序的通用和移植。(3)有利于减少程序书写的工作量。第 8章 数组类型 8.4.3 几点说明几点说明 (1)用typedef只能对已有类型增加一个名字,而不能自己去创造一个新的类型。(2)用typedef可以对各种已有类型增加新的类型名,但不能用来定义变量。(3)重命名类型,可以将数组类型与数组变量分离开来。(4)重命名类型与编译预处理不同,是在编译时处理,实际上也并不是作简单的字符串替换。(5)常将一些常用的重命名类型单独放一文件中,需要时用include指令将它们包含至程序中。第 8章 数组类型 8.5 程序设计
24、举例程序设计举例 例例 8-11 求n个实数的和、积、最大值、最小值。/*程序8-11,求n个数的和、积、最大值、最小值*/define N 100main()float aN;int n;int i;float sf();float mf();float max();float min();scanf(%d,&n);for(i=1;i=n;i+)scanf(%f,&ai);第 8章 数组类型 printf(和=%8.3fn,sf(a,n);printf(积=%8.3fn,mf(a,n);printf(最大值=%8.3fn,max(a,n);printf(最小值=%8.3fn,min(a,n)
25、;float sf(xa,xn)/*求和*/float xa;int xn;int i;float s=0;for(i=1;i=xn;i+)s+=xai;return(s);第 8章 数组类型 float mf(xa,xn)/*求积*/float xa;int xn;int i;float m=1;for(i=1;i=xn;i+)m*=xai;return(m);float max(xa,xn)/*求最大值*/float xa;int xn;int i,k=1;/*k存放最大值下标*/for(i=1;ixak)k=i;return(xak);第 8章 数组类型 float min(xa,xn)
26、/*求最小值*/float xa;int xn;int i,k=1;/*k存放最小值下标*/for(i=1;i=xn;i+)if(xaixak)k=i;return(xak);第 8章 数组类型 例例 8-12 给定一43的整数矩阵,求矩阵中最小值及最小值所在行、列号。/*程序8-12,求矩阵中最小值及位置*/main()int a43;/*存放矩阵*/int i,j;int min,row,col;/*存放最小值及最小值所在行、列号*/for(i=0;i4;i+)/*输入矩阵*/for(j=0;j3;j+)scanf(%d,&aij);row=0;col=0;min=a00;/*初始化最小值
27、及最小值所在行、列号*/for(i=0;i4;i+)/*求最小值及最小值所在行、列号*/for(j=0;j3;j+)if(aijmin)min=aij;row=i;col=j;printf(最小值为%d,处在%d行%d列,min,row,col);第 8章 数组类型 例例 8-13 将n个实数由大到小排序。void sort1(a,n)/*选择排序函数*/float a;int n;int k,i,j;/*k最大值下标,i,j循环控制变量*/float t;/*中间变量,用于两个数的交换*/for(i=0;in-1;i+)k=i;/*求最大值下标*/for(j=i+1;jak)k=j;t=ai
28、;ai=ak;ak=t;/*进行交换*/第 8章 数组类型 算法二:冒泡排序。void sort2(a,n)/*冒泡排序函数*/float a;int n;int i;/*一轮比较的循环控制变量*/int flag;/*标志变量,为1有交换,为0无交换*/float t;/*中间变量,用于两个数的交换*/doflag=0;/*先假定无交换,已排好序*/for(i=0;iai)t=ai;ai=ai+1;ai+1=t;/*进行交换*/flag=1;/*有交换,标志变量的值改变为1*/while(flag=1);第 8章 数组类型 例例 8-14 筛法求21000之间的所有素数。/*程序8-14,筛
29、法求2至1000之间的所有素数*/main()int a1000;/*筛子数组*/int i;int minp,double;/*minp筛选种子,double倍数*/int n=0;/*素数个数,用于输出格式控制*/for(i=2;i1000;i+)/*建立筛子*/ai=1;minp=2;/*筛选种子初始化*/while(minp500)/*完成整个筛选*/double=2*minp;/*倍数初始化*/第 8章 数组类型 while(double1000)/*完成一轮筛选*/adouble=0;/*筛去当前倍数*/double+=minp;/*计算下一个倍数*/do/*计算下一轮筛选种子*/
30、minp+;while(aminp=0);printf(2至1000之间的所有素数如下:n);for(i=2;i1000;i+)if(ai=1)printf(%6d,i);n+;if(n%5=0)printf(n);/*5个素数输出在一行*/第 8章 数组类型 例例 8-15 求101000之间的回文数。/*程序8-15,求101000之间的回文数*/main()int i,x;int a8,j;int b,e;int flag;for(i=10;i0)aj=x%10;x/=10;j+;第 8章 数组类型 flag=1;/*先假定i为完数*/b=0;e=j-1;while(bx)e=d;els
31、e b=d;while(be&!KG-*4flag);if(flag=0)k=0;/*没找到*/return(k);第 8章 数组类型 例例 8-17 某班有50个学生,期终考试8门课程。求每个学生总成绩、平均成绩,并按总成绩高分到低分输出。/*程序8-17,成绩处理程序*/char st5112;/*采用外部数组实现数据传递*/float cj519;float tacj513;main()void input();/*调用函数申明*/void count();void sort();void output();input();/*调用输入函数*/count();/*调用计算函数*/sort
32、();/*调用排序函数*/output();/*调用输出函数*/第 8章 数组类型 void input();/*输入函数*/int i,j;for(i=1;i=50;i+)printf(请输入第%d个学生姓名,成绩:n);scanf(%s,sti);for(j=1;j=8;j+)scanf(%f,&cjij);void count();/*计算函数*/int i,j;for(i=1;i=50;i+)第 8章 数组类型 tacji1=0;for(j=1;j=8;j+)tacji1+=cjij;tacji2=tacji1/8;void sort()/*排序函数*/int i,flag;char
33、ts12;float tc;doflag=0;for(i=1;itacji1)strcpy(ts,sti);strcpy(stI,sti+1);第 8章 数组类型 strcpy(sti+1,st);/*交换姓名*/for(j=1;j=8;j+)/*交换8门课程成绩*/t=cjij;cjij=cji+1j;cji+1 j=t;t=tacji1;tacji1=tacji+11;tacj i+11=t;/*交换总成绩*/t=tacji2;tacji2=tacji+12;tacj i+12=t;/*交换平均成绩*/flag=1;while(flag=1);第 8章 数组类型 void output()/*输出函数*/int i;printf(50个学生成绩处理结果如下:n);printf(姓名 课程1 课程2 课程3 课程4 课程5 课程6 课程7 课程8 总成绩 平均成绩 名次n);for(i=1;i=50;i+)printf(%8s,sti);for(j=1;j=8;j+)printf(%7.2f,cjij);printf(%7.2f%7.2f%5d,tacji1,tacji2,i);printf(n);