1、第9课数组第九章 数组 之前我们只学过单个变量的定义,而有的时候就需要一片连续的存储单元。单个单个的定义第一,分配的内存空间不一定连续,这样指针就不能移动了。第二,单个单个的定义会费时费力。所以这个时候就需要一个东西来满足用用户这样一个需求。数组就在这样的条件下产生了。 数组:多个相同类型的变量被存储在一片连续的存储单元中。9.1一维数组的定义和一维数组元素的引用 一维数组的定义: 当数组中每个元素只带有一个下标时,称这样的数组为一维数组。格式: 类型名 数组名【整型常量表达式】如 int a10 说明:1. 定义了一个名为a的一维数组2. 方括号中的10规定了a数组含有10个元素,它们是(a
2、0. a1. a2. a3.a4.a5. a6. a7. a8. a9)3. 类型名int规定了a数组中每个元素都是整型,在每个元素中只能存放整形数。4. 每个元素只有一个下标,C语言规定每个数组第一个元素的下标总为0(称为数组下界),那么最后一个9(称为数组的下标为上界)5. 在内存中给数组中每个成员开辟了一个存储单元。总计大小:10*4=40字节。这样每当调用数组中的一个成员时就用它们的下标。如 a*注:当同时定义多个数组时彼此之间用,号隔开 如 double w22,v100,u5; 以上定义了三个数组。需要注意的是,【】中的内容只能是整型常量或整型常量表达式。如int a11+22也可
3、以。 一维数组元素的引用格式: 数组下标表达式其实x0,xj,xi+k都是对数组中元素的合法引用形式。但是需要注意的是下标表达式的值必须大于或等于0,并且小于数组上界的数。能过上面知识讲解,大家应该建立以下概念: 1:一个数组元素实质上就是一个变量名,代表内存中一个存储单元。一个数组占有一串连续的存储单元。 2:在C语言中一个数组不能整体引用。不能说用一个数组名就代表整个数组了。这是错误的。因为在C语言中规定数组名是一个地址常量,它代表整个数组的首地址。int *p ;int a10 p=a(p=&a0) a= =&a0 a=10 3:数组元素中下标表达式的值必须是整数。在编写程序时保证数组下
4、标不越界是十分重要的。 a2.5 a10=123 一维数组的初始化 一维数组的始化,其实就是给数组元素赋值。格式: int a8=0,1,2, 4,5,6,7 所赋的值放在等号后的一对花括号中,数值类型必须必须与所说明的类型一致,所赋值之间用逗号隔开。系统会按赋值顺序来自动分配。 当花括号中的值少于数组元素个数时,将自动给数组后面元素赋值0.如 int a10=1这个时候除了a0=1外,其它的都是0;对于字符数组也是一样;char a10=!不够的也会赋值0通过赋初值定义数组的大小C语言中规定,可以通过赋初值来定义数组的大小,这时数组说明符的一对方括号中可以不指定数组的大小。 如 int a=
5、1,1,1,1,1,1,1,1,1,1 这样相当于数组中有了10个元素例题:编写一个程序,通过键盘给数组a中的10个成员赋初值。 #include main()int a10;int i,*p;p=a;for(i=0;i10;i+) scanf(“%d”,p);printf(“ai=%d”,*p); 编写一个程序定义一个含有30个成员的数组。并给其赋值,要求从1这样的奇数开始。当赋值完毕后,按每行10个输出。include #define m 30main()int am;int i,k=1;for(i=0;im;i+) ai=k; k+=2;for(i=0;im;i+) printf(“a%
6、d=%d”,i,ai); if(i+1)%10= =0) printf(“n”);9.2一维数组和指针一维数组和数组元素的地址 前言:定义的数组名可以认为是一个存放地址值的指针变量名,其中的地址值是数组第一个元素的地址,也就是数组所占一串连续存储单元的起始地址。重要的是:这个指针变量中的地址值不可改变,也就是说,不可以给数组重新赋值。因此,也可以认为数组名是一个地址常量。 如:float a10 ,*p,x; 语句a=&x或a+这样的语句都是非法的。因为不能给a重新赋地址值。一旦定义a永远指向a数组的首地址。 虽然不可以改变数组名a中的内容,但可以用对数组名加一个整数的办法,来依次表达该数组中
7、不同元素的地址。 如:int a10,*p; p=a+4p=&a4再如:for(k=0;k10;k+) p=a+k;在循环中并没有改变数组名a中的内容,但通过表达式:a+k逐一给出了a数组中每个元素的地址,使p依次指向a数组中和每一个元素。 如果要能过类似上面的语句给数组中的元素赋值,语句为: for(k=0;k10;k+) scanf(“%d”,a+k); 如有p=a或p=&a0这两个表达式所要表达的意思是一样的。都是指指针P指向了数组a的首地址。所以当要依次访问数组中的每一个元素时可以用以下的两个形式; p+; 或a+k(k的值是不断变化的如上面的for语句一样) 通过数组的首地址引用数组
8、元素a是数组元素的首地址,a(即a+0)的值即等于&a0,则用a+1的值等于&a1.在以前我们学过“间接访问运算符”-“*”来引用地址所在的存储单元。因此对于数组a0,可以用表达式*&a0来引用也可以用*(a+0),还可以用a0来表示。但需要注意的是对于*(p+k)这样的表达式不能这样写*p+k,这样写的话就错了。代表指针取值后再加K的值了。总结:表示数组元素si的表达式应当有 si *(s+i) *(p+i) *pi(但当p=s+2时,p=&a2.*p0就是a2的值了)9.3函数之间对一维数组和数组元素的引用数组元素作实参 每个数组元素实际上代表内存中的一个存储单元,故和普通变量一样,对应的
9、形参必须是类型相同的变量。数组元素的值可以传送给该变量,在函数中只能对该变量进行操作,而不能直接引用数组元素,更不能在函数中改变对应数组元素中的值。数组名作实参 数组名也可以作为实参传送,但数组名是一个地址值,因此,对应的形参就应当是一个指针变量,此指针变量的基类型必须与数组的类型一致。这样就可以通过指针变量来引用调用函数中对应的数组元素,从而达到对调用函数中对应的数组元素进行操作而改变其中的值。例:编写程序,通过一个函数给主函数中定义的数组输入若干大于或等于0的整数,用负数作为输入结束标志,调用另一个函数输出该数组中的数据。#include #define M 100void arrout(
10、int *,int);int arrin(int *);main()int sM,k;k=arrin(s);arrout(s,k);int arrin (int *a)int i,x;i=0;scanf(“%d”,&x);while(x=0)*(a+i)=x;i+;scanf(“%d”,&x);return i;void arrout(int *a,int n)int i;for(i=0;in;i+)printf(i+1)%5=0)?”%4dn”;”%4d”,*(a+i);printf(“n”);当数组名作为实参时,对应的形参除了是指针外,还可以用另外两种形式。 在上面的题目中数组名作为实参时
11、,函数的首部用的是指针arrin(int *a),还可以用以下的形式调用:、 arrin(int *a) arrin(int a) arrant(int aM)9.3.3数组元素地址作为实参 当用数组元素地址作为实参时,因为是地址值,所以对应的形参也应当是基类型相同的指针变量。 例:编写函数,对具有10个元素的char类型数组,从下标为4的元素开始,全部设置星号“*”;保持前4个元素中的内容不变。 假设数组是c10=A,B,C,D,E,F,G,H,I,J 根据题意可以知道想要从E开始后面的全变成*编写一个改变的函数,编写一个输出的函数。#include #define M 10#define
12、B 4void setstar(char *,int);void arrout(char *,int);main()char cM= A,B,C,D,E,F,G,H,I,J ;setstar(&c4,M-B);arrout(c,M);void setstar(char *a,int n)int i;for(i=0;in;i+)*(a+i)=*;void arrout(char *a,int n) int i; for(i=0;in;i+)printf(“%c”,ai);printf(“n”);9.4一维数组应用举例 编写程序,定义一个含有15个元素的数组,并编写函数分别完成以下操作。1, 调用
13、C库函数中的随机函数给所有元素赋以0-49的随机数;2, 输出数组元素中的值。3, 按顺序对每隔三个数求一个和数,并传回主函数。4, 最后输出所有求出的和的值。#include #include “stdlib.h”#define SIZE 15#define N 3void getrand(int *,int);void getave(int * ,int *,int );void priarr(int *,int );main()int xSIZE,wSIZE/N=0;getrand(x,SIZE);printf(“output%d random numbers:n”,SIZE);pria
14、rr(x,SIZE);getave(x,w,SIZE);printf(“Output 5 sum numbers :n”);priarr(w,SIZE/N);void getrand(int *a,int n)int i;for(i=0;in;i+)ai=rand()%50;void getave(int *a,int *b,int n)int i,j,sum;for(sum=0,i=0,j=0;i=n;i+)sum+=ai;if(i+1)%3=0)bj=sum;sum=0j+;void priarr(int *a,int n)int I;for(i=0;in;i+)printf(“%5d”,
15、ai);if(i+1)%5=0)printf(“n”);printf(“n”);例:将数组中的数按颠倒的顺序重新存放。在操作时,只能借助一个临时存储单元,不得另外开辟数组。注意:不是按颠倒的顺序打印数据,而是要求按逆序重新放置数组中的内容。#include #define NUM 8void invert (int *,int);void priout(int *,int);main()int anum=10,20,30,40,50,60,70,80;printf(“输出数组中的内容:”);priout(a,NUM);invert(a,NUM);printf(“输出数组中调换后的内容:”)pr
16、iout(a,NUM);void priout(int s,int n)int i;for(i=0;in;i+)printf(“%4d”,si);printf(“n”);void invert(int *a,int n)int i,j,t;i=0;j=n-1;while(ij)t=ai;ai=aj;aj=t;i+;j-;、9.5二维数组的定义和二维数组元素的引用9.5.1二维数组的定义 当数组中的每个元素带有两个下标时,称这样的数组为二维数组。(在逻辑是可以把二维数组看成一个具有行和列的表格或一个矩阵) 定义语句形式如下: 类型名 数组名常量表达式1常量表达式2 二维数组说明符中必须有用两个方
17、括号括起来的常量表达式,常量表达式的值只能是正整数。如果将二维数组当做矩形来看,那么常量表达式1就是代表行数,常量表达式2就代表列数。 如int a34 a121. 定义了一个名为a的二维数组。2. 数组中的每个元素都是整形3. a数组中共有3*4个元素。4. a数组的逻辑结构是一个具有3行4列的矩阵。 第0列 第1列 第2列 第3列第0行 a00 a01 a02 a03第1行 a10 a11 a12 a13第2行 a20 a21 a22 a23其实对于二维数组来说,我们还可以理解为一个特殊的一维数组。如上,将此二维数组中的第0行可以看为一个名为a0的一维数组的几个成员。同理对另外几行也成立。
18、9.5.2二维数组元素的引用 引用二维数组元素时必须带有两个下标,引用形式如下:数组名下标表达式1下标表达式2int a34在这样定义的二维数组中,有 a01 aij ai+kj+k 注意:引用二维数组元素时,一定要把两个下标分别放在两个方括号肉。不可以定成a0,1 aI,j ai+k,j+k9.5.3二维数组的初始化1.所赋值个数与数组元素的个数相同 int a43=1,2,3,4,5,6,7,8,9,10,11,12;2.每行所赋值个数与数组中元素的个数不同。 int a43=1,2,4,5,7,10;3.所赋值行数少于数组行数int a43=1,2,4,5;5. 赋值时省略行花括号对in
19、t a43=1,2,3,4,5;9.5.4通过赋值定义二维数组的大小int a=1,3,3,3,3,34对于二维数组,只可以省略第一个方括号中的常量表达式,而不能省略第二个方括号中的常量表达式int a3=1,2,4,5,7,10;当用以下形式赋值时:int a3=1,4,6,7,23,25,17,18;一维大小按以下规则决定:1, 当初值的个数能被第二维的常量表达式的值除尽时,所得商数就是第一维的大小。2, 当初值的个数不能被第二维的常量表达式的值除尽时。则第一维的大小=所得的商+19.5.5 二维数组的定义和数组元素引用举例通过键盘给2*3的二维数组输入数据,第一行赋值1,2,3,第二行赋
20、值10,20,30然后按行输出此二维数组#includemain()int a23,i,j;printf(“Enter data by line :n”);for(i=0;i2;i+) for(j=0;j3;j+)scanf(“%d”,&aij);printf(“Output a 2-dimension array :n”);for(j=0;j2;j+) for(i=0;i3;i+) printf(“%4d”,aij); printf(“n”);9.6二维数组和指针9.6.1二维数组和数组元素的地址先给出以下定义: int *p,a34;1. 二维数组a由若干个一维数组组成像上面定义的数组a,
21、我们可以理解为由a0、a1、a2三个元素组成,而他们又分别是一个一维数组 通过前面我们学过的知识可以知道,数组名是一个地址,其值是第一个元素的地址,此地址的基类型就是数组元素的类型。而在二维数组中同样a0、a1、a2都是一维数组名,同样也代表了一个不可变的地址常量。由于它是一个常量,所以这样就错了:a0+。而a0+1这就是代表向后移动一个单位长度。 对于有一个指针变量P的基类型与ai相同,则p=ai这是正确的。2. 二维数组名也是一个地址常量二维数组名同样也是一个存放地址常量的指针,其值为二维数组中第一个元素的地址。以上a的值与a0的值是相同的。 a0 a+0 第0行的首地址 a1 a+1 第
22、1行的首地址像他们这样的,还有一个另外的名称-行地址。所以二维数组名应理解为一个行指针。inta34 a0=a3. 二维数组元素的地址用以下的五种方式表示:&aijai+j*(a+i)+j&a00+4*i+ja0+4*i+j9.6.2通过地址引用二维数组元素若有以下定义: int a34则a数组元素可以用一下五种表达式来引用:aij*(ai+j)*(*(a+i)+j)(*(a+i)j*(&a00+4*i+j)9.6.3通过建立一个指针数组引用二维数组元素int *p3,a32,i,j;说明符*p3中,也遵照运算符的优先级,一对的优先级高于*号,因此p首先与结合,构成p3,说明了P是一个数组名,
23、系统将为它开辟3个连续的存储单元,在它前面的*号则说明了数组p是批针类型,它的每个元素都是基类型为int的指针。 如有: for(i=0;i3;i+) pi=ai 这就意味着每一个指针都指向了a数组中的每行的开头。000110112021所以对于数组a中的元素,我们也可以通过这样的指针来表示了0129.6.4通过建立一个行指针引用二维数组元素 若有以下定义: int a32 ,(*prt)2为什么要先加一个()?这是因为想要*先与prt结合,说明prt是一个指针变量。然后再与2结合,说明指针变量prt的基类型是一个包含有两个int元素的数组。 因为prt与a的类型相同,所以prt=a就是一个合
24、法表达式。当prt指向a数组的开头时,可以通过以下形式来引用aij*(prti+j)*(*(prt+i)+j)(*(prt+i)jprtij9.7二维数组名和指针数组作为实参 9.7.1二维数组名作为实参时实参和形参之间的数据传递 当二维数组名作为实参时,对应的形参必须是一个行指针变量。 假设有这样的一个二维数组名作为实参double aMN fun(a)这个时候对应的函数首部应写成以下几种形式 fun(double (*a)N) fun(double aN) fun(double aMN)一定要注意列下标不能丢。9.7.2指针数组作为实参时,实参和形参之间的数据传递 当指针数组名作为实参时,
25、对应的形参应当是一个指向指针的指针如: double *psMfun(ps)则fun函数的首部应写成以下几种形式fun(double *aM)fun(double *a )fun(double *a)9.8二维数组程序举例编写程序,通过调用随机函数给5*6的二维数组元素赋值10-40内的整数,并求出每行元素的平均值。#include #include #define M 6#define N 5void getdata(int (*)M);void lineave(intM,float *);void outdata(intNM,float *);main()int rNM;float ave
26、N;getdata(r);lineave(r,ave);outdata(r,ave);void gaetdata(int(*sp)M)int i,j,x;for(i=0;in;i+)j=0;while(j10)spij=x;j+;void lineave(int sM,float *a)int i,j;for(i=0;iN;i+)ave=0.0;for(j=0;jM;j+)ave=ave+sij;ai=ave/M;void outdata(int spNM,float a)int i,j;printf(“output the result:n”);for(i=0;iN;i+) for(j=0;
27、jM;j+)printf(“%4d”,spij);printf(“:%6.2n”,ai);putchar(“n”)第九章 数组一、选择题 9.1 若已定义:int a=0,1,2,3,4,5,6,7,8,9,*p=a,i;其中0i=9,则对a数组元素的引用不正确的是A) ap-a B) *(&ai) C) pi D) *(*(a+i) 9.2 以下程序段数组所有元素输入数据,应在下划线填入的是A) a+(i+) B) &ai+1 C) a+i D) &a+imain() int a10,i=0;while(i10) scanf(%d,); 9.3 以下程序的输出结果是 A) 3 B) 4 C) 1 D) 2main() int a10=1,2,3,4,5,6,7,8,9,10,*p=a; printf(%dn,*(p+2); 9.4 以下程序的输出结果是A) 不确定的值 B) 3 C) 2 D) 1mai
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1