数组类型与指针类型m.ppt

上传人:小飞机 文档编号:6297468 上传时间:2023-10-14 格式:PPT 页数:61 大小:301.49KB
返回 下载 相关 举报
数组类型与指针类型m.ppt_第1页
第1页 / 共61页
数组类型与指针类型m.ppt_第2页
第2页 / 共61页
数组类型与指针类型m.ppt_第3页
第3页 / 共61页
数组类型与指针类型m.ppt_第4页
第4页 / 共61页
数组类型与指针类型m.ppt_第5页
第5页 / 共61页
点击查看更多>>
资源描述

《数组类型与指针类型m.ppt》由会员分享,可在线阅读,更多相关《数组类型与指针类型m.ppt(61页珍藏版)》请在三一办公上搜索。

1、第5章 数组类型与指针类型,5.1 数据类型的构造,*5.3 指针类型,*5.2 数组类型,结束放映,系统预先提供的类型:C语言提供的基本数据类型,大致分为整型、实型、字符型等三大类用户新定义的类型:C语言提供构造新类型的方法,可以在已有数据类型的基础上构造新的数据类型,这种新的类型称为构造类型,根据构造方法的不同分为数组、指针、结构、联合等四种,5.1 数据类型的构造,5.2 数组类型,为什么要用数组?(重点理解),问题:假如现在班级里有100个人,要求用C语言程序来实现求这100个人的数学成绩之和,(想一想怎么写?),使用数组的目的:为了解决这种大量同种类型数据的存储与使用问题,5.2 数

2、组类型,数组类型的定义数组是由一系列同类型的元素(Element)所组成的集合,数组变量名就一个数组中元素的数据类型可以是基本类型,也可以是构造类型,若元素的类型是整型则称为整型数组,若元素类型是结构体类型则称为结构体数组,若元素类型是指针类型则称为指针数组,若成员的类型是数组则称为二维数组,一维数组(重点掌握)当数组中元素的类型不是数组,而是基本类型,或者结构,指针等构造类型时,称为一维数组一维数组变量的定义的格式(掌握)元素数据类型 数组变量名常量或数值表达式注意常量的值表示了数组的大小即元素的个数,必须为正整型(记住:这里数组的大小一定不能是个变量)。如果数组大小是个数值表达式的值是小数

3、,一定先取整,int a7/2 即 a3 数组变量名需要符合标识符命名的要求,不能与已有的变量名或系统关键字相同。,方式1:数组只能在定义的同时对数组整体进行赋初值(而普通变量可以先声明后初始化)格式:数据类型 数组变量名元素个数=元素1初值,元素2初值,.初值用一对括起来。相邻的值之间用逗号隔开例如:int arr10=9,8,7,6,5,4,3,2,1,0;上面定义了一个一维数组,名字为arr,共10个元素。元素的类型为int,初始值为从9到0。以下方式是错误的:int arr10;arr10=9,8,7,6,5,4,3,2,1,0;/errorArr=100;/error,问题:前面我们

4、讲了怎样定义一个一维数组的格式,那么定义完了如何给这个一维数组中的每个元素赋值呢?它的赋值方式和一个普通变量的赋值有什么区别?,方式1注意:使用方式1给数组整体赋值,初值的个数不能超过数组的大小(即可以小于但觉不能大于)int arr10=9,8,7/允许你这里定义了数组为10个元素,但你可以给它赋少于10个的初始值。但至少有一个,那么那些没有得到初始值的元素的值又是多少呢?他们则被编译器初始化为0,但是如果只定义数组,没有对其进行任何初始化,局部变量则是未定义的值(即不可预测的值),全局变量将被编译器自动初始化为0,方式2:先定义,后初始化时只能针对数组中单个的元素进行赋值,而不能进行整体赋

5、值例如 int arr10;arr0=9;arr1=8;.这里需要访问数组中的每个元素,所以需要使用下标来区分数组中的每个元素,下标只能是整形,C语言规定,访问数组中的元素下标从0开始,即第一个元素是 数组名0,方式3:用一个数组给另一个数组赋值例如:int a5=1,2,3,4,5 int b5;怎样用a初始化数组b呢?想一想怎样用程序实现,能否自行编写出来。(提示:使用for循环实现)以下是错误的情况:b=a;/error,一维数组的相关操作举例 例 1:要求从键盘输入5个整数并存储到一个数组中。然后将此数组的内容进行打印输出(怎样实现?想一想),#include void main()i

6、nt a5;int i;for(i=0;i5;i+)printf(please input the%d data:,i+1);scanf(%d,例2 求上一题目中数组a中元素的最大值的下标,并打印输出此下标和对应的元素的值(怎样修改),void main()int maxIndex=0;int a5=1,2,3,4,5;int i;for(i=0;i amaxIndex)maxIndex=i;printf(the maxIndex is%dn,maxIndex);printf(the array max value is%dn,amaxIndex);,例3 要求实现在一个数组中查找一个值,这个

7、值由用户输入,判断此值是否在数组中(怎样实现),void main()int value;int a5=1,2,3,4,5;int i;int flag=0;scanf(%d,例4 要求实现对一个数组元素进行逆序存放(怎样实现)例如 int a5=1,2,3,4,5 逆序存放后内容变成 a5=5,4,3,2,1,void main()int a5=1,2,3,4,5;int i=0;int j=4;int temp;while(i j)temp=ai;ai=aj;aj=temp;i+;j-;/下面内容请自行编写使用for循环遍历输出数组的内容,例5 要求使用选择法对一个数组元素进行从小到大的排

8、序,最后将排序后的结果进行输出(怎样实现?)例如 int a5=5,2,4,3,1 排序后内容变成 a5=1,2,3,4,5,void main()int i,j,smallIndex=0;int temp;int a5=5,2,4,3,1;for(i=0;i4;i+)smallIndex=i;for(j=i+1;j5;j+)if(aj asmallIndex)smallIndex=j;temp=ai;ai=asmallIndex;asmallIndex=temp;,例6 利用数组获得20项Fibonacci数列元素,即后一项为前两项之和,开始两项为1,可得序列为1,1,2,3,5,8,#in

9、clude void main()int i,f20=1,1;for(i=2;i=19;i+)fi=fi-2+fi-1;for(i=0;i=19;i+)printf(%d/n,fi);,数组的存储(掌握)数组的存储涉及两个问题:每个成员要有存储空间且每个成员可以通过下标找到存储空间的位置。数组的存储方法:分配连续的一块内存区域能够存放得下所有的元素,然后将数组成员按下标顺序连续存放,零号成员存放在这块内存区的最前面,所以数组的实质是内存中一段连续的存储区域,假设内存地址为start,由于每个成员所占的存储空间大小是相同的,假设为m个字节,这时i号成员的内存地址就等于start+m*i。,定义了

10、一个10个元素的int数组,占据的内存空间,10*4个字节,每4个字节空间就代表着一个元素,数组访问越界问题:,越界?越谁的界?当然是内存。一个变量存放在内存里,你想读的是这个变量的内存空间,结果却读过头了,很可能读到了另一个变量的头上。这就造成了越界。数组的访问越界问题,看如下代码:int arr10,i;for(i=1;i=10;i+)printf(“%d”,arri);,这里访问数组的元素已经越界了!但是编译器不提示错误,即编译器不进行数组访问越界的检查。但这明明是个错误,所以一个隐秘的错误就包含到了你的程序中,这是非常可怕的事,当程序运行起来后,有可能会出现莫名奇妙的错误。错误表现不定

11、,有问题的代码,数组访问越界问题:,为什么数组访问越界会造成莫名其妙的错误?前面我们讲过数组的实质是一段连续的内存空间。然后,我们可以通过指定数组下标来访问这块内存里的不同位置。因此,当你的下标过大时,访问到的内存就不再是这个数组“份内”的内存。你访问的,将是其它变量的内存了。举个例子数组就像一排的宿舍,假设有5间,你住在第2间;如果你晚上喝多了,回来时进错了房间,只要你进的还是这5间,那倒不会有大事,可是若是你“越界”了。竟然一头撞入第6间这第6间会是什么?很可能它是走廊的尽头,结果你一头掉下楼,这在生活中很不幸,可对于程序倒是好事了,因为错误很直接(类似直接死机),你很容易发现。可是,如果

12、第6间是?据我所知,第6间可能是厕所,也可能是女生宿舍。所以数组访问下标越界问题,程序会表现出不可预知的错误。,这个问题:怎样解决?,数组与指针变量(掌握)数组名是数组中第一个元素的内存地址即首地址,是地址。指针变量是存放某种类型变量地址的变量,所以指针变量能保存数组的首地址,那么这时指针变量就指向了这个数组 前面已经介绍了使用下标访问数组元素,使用指针变量也可以访问数组元素。分为两步:(1)建立指针变量,取得数组中第一个元素的地址;(2)重复通过指针加1来获得下一个数组元素的指针。第一步获取指针可以通过两种方式一种是利用取址运算(&)获得元素的指针,另一种是直接通过数组名获得第一个元素的指针

13、,采用指针方式访问数组元素求Fibonacci数组中前20个项。#includevoid main()int i,f20=1,1,*p;/*通过*定义指针变量p/p=,注意:p-2中的2是地址偏移量,表示p的内容-2个元素大小的内存空间,例 有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。a数组已经按照从小到大的顺序排列好,加入数保持有序的方法是先将所有大于该数的元素后移一格,再将该数放到这些数的前面。,新元素X,程序如下:#include void main()int a11=1,4,6,9,13,16,19,28,40,100;int i,number;printf(

14、original array is:n);for(i=0;i=0;i-)if(ainumber)ai+1=ai;else break;ai+1=number;for(i=0;i11;i+)printf(%5d,ai);printf(n);,一维数组作为参数(掌握)一维数组实参采用地址传递方式,提供给形参的不是数组的所有元素值,而是一个简单的数组零号元素的地址。通过形参中的地址可以找到一维数组实参的所有元素的存储空间,函数中可以直接访问这些元素空间。为了函数可以检查越界错误,可以将数组大小作为函数参数一并传递。形参定义方式可以是一维数组定义形式,也可以省略定义中的数组大小,还可以直接定义为指针类

15、型,这三种方式含义是一样的。调用函数时提供的一维数组实参就是待传递数组的第一元素的地址,一般直接将数组名作为实参。,例 编写一个函数实现将一维数组的内容倒置,该功能前面已进行过讲解,请自行写一下试一试,【例5.8】编写一个自定义函数可以查找任意数组中是否存在一个特定数据。#include int search(int s10,int x)int i;for(i=0;i10;i+)if(si=x)break;if(i10)return 1;else return 0;void main()int a10,i,e;printf(Enter the array:n);for(i=0;i10;i+)s

16、canf(%d,二维数组(理解)具有两个下标的数组称为二维数组 通常,二维数组可看成是数学中的矩阵,因此,习惯上将第一维下标称为行标,第二维下标称为列标。二维数组变量的定义:元素类型 数组名常量表达式1常量表达式2=初始值表;说明:元素类型是构成数组的数据成员的类型。常量表达式1和常量表达式2分别代表行标和列标的大小,它们均从0开始。,二维数组实质:我们可以把一个二维数组a看作是一种特殊的一维数组,而这个一维数组的元素又是一个一维数组。例如a34 a0=a00,a01,a02,a03 a1=a10,a11,a12,a13 a2=a20,a21,a22,a23 a0,a1,a2分别是三个一维数组

17、的数组名,实际的二维数组存储也是按一维数组的存储方式存储的。这里的二维数组默认按照行的顺序存储,二维数组变量的初始化(1)按维给二维数组赋初值,(推荐使用,清楚直观)例如:int A34=1,2,3,4,5,6,7,8,9,10,11,12;(2)可以将所有数据写在一个花括号内,按存放顺序连续赋初值(此方法编程中不推荐使用)例如:int A34=1,2,3,4,5,6,7,8,9,10,11,12;(3)如果能提供所有数组元素的初始值,则定义数组时只需要提供第二维大小,第一维可以省略 例如:int A4=1,2,3,4,5,6,7,8,9,10,11,12;,二维数组的基本操作举例【例5.11

18、】编程将矩阵A转置后存放到矩阵B中,即Bji=Aji。#includevoid main()int A34,B43,i,j;for(i=0;i3;i+)for(j=0;j4;j+)scanf(“%d”,字符数组与字符串(重点掌握)字符串常量字符串常量使用双引号界定,字符串常量的存储是采用连续的字符后跟一个结束标志零(即字符0)的方法,这样,提供一个字符串只需提供该串的串首指针(地址)即可 示例:C Language在内存保存的情况如下,字符串变量字符串变量C语言中不能直接定义,需要通过使用字符数组来模拟定义,通常的方法有两种。(1)字符数组变量法例如:char str=“C Language”

19、;/由系统计算长度(2)字符指针变量法例如:char*str=C Language;说明:1)要使用该数组中的每个字符,可以使用下标运算 来完成。2)字符数组常被作为一个整体,看作字符串变量来使用,为便于操作,提供了一批字符串函数对其处理。3)字符串常量和字符串变量名实质上只提供了字符串的首地址,它们参加的各种运算实际上是一种指针性质的运算。,要求实现一个让字符串倒序存放的功能说明:字符串倒序是将串中字符左右颠倒,如abc则变成cba。(此题的解题方法在一维数组部分已讲解过能否自行实现?)#include void main()char str=The quick brown fox jump

20、s over the lazy dog.;int i=0,n;char temp;n=sizeof(str)-1;/*字符个数*/while(in)temp=stri;stri=strn;strn=temp;i+;n-;printf(%sn,str);,字符串做函数参数【例5.19】求字符串长度(长度不包括0)#include int mystrlen(char*s)int i;for(i=0;*s!=0;s+,i+);/知道0在字符串中的作用了吗?return i;void main()char str=Computer Science;printf(%dn,mystrlen(str);,【

21、例5.20】比较两个字符串的大小#include int mystrcmp(char*s1,char*s2)for(;*s1!=NULL,字符串的标准函数(string.h)(会使用以下库函数)1strlen函数其函数原型为:int strlen(char*s);其功能是:根据字符指针s所指向的字符串(提供的字符序列要以0结尾),返回其中字符个数。2strlwr函数其函数原型为:char*strlwr(char*s);其功能是:将字符指针s所指向的字符串中所有字母均变成小写字母,将该串的首地址作为字符指针返回。,3strupr函数其函数原型为:char*strupr(char*s);其功能是:

22、将字符指针s所指向的字符串中所有字母均变成大写字母,将该串的首地址作为字符指针返回。4strcmp函数其函数原型为:int strcmp(const char*s1,const char*s2);其功能是:将字符指针s1和s2所指向的字符串进行比较,如果对应的每个字符均相同而且长度也相等,则函数返回0,否则以不相同位置的字符的ASCII码相减,返回差,其规律为:(1)返回值0,表示s1串大于s2串。(2)返回值0,表示s1串小于s2串。,5strcpy函数其函数原型为:char*strcpy(char*dest,const char*src);其功能是:将字符指针src所指向的串复制到dest

23、所指向的字符型内存空间中,并且将dest串的首地址作为字符型指针返回。6strcat函数其函数原型为:char*strcat(char*dest,const char*src);其功能是:将字符指针src所指向的串连接到dest所指向的字符串的后面的剩余内存空间中,并且将目的串dest的首地址作为字符型指针返回。,7strstr函数其函数原型为:char*strstr(const char*s1,const char*s2);功能是:在字符指针s1所指向的串中查找s2所指向的字符串是否出现,若s2串在s1串中出现了,则返回在s1中出现的位置指针,否则返回NULL指针。,5.3 指针类型,1、什

24、么是指针指针就是地址。C语言将这种地址也看成是数据,有直接使用和间接使用两种使用方法。直接使用:直接使用地址本身,得到结果仍是指针。间接使用:通过地址找到内存中的单元,然后访问该单元。2、什么是指针变量是用于保存地址的变量。,下图例示指针变量与一般变量的区别,指针的表示指针变量的定义基类型*指针变量名=初始化值;说明:基类型是指针所指向的内存单元的类型。指针变量名前面必须通过*号标识,不能与保留字和其它变量同名。初始化值是内存单元的地址,该内存单元必须是基类型,省略时指针变量中为随机值。NULL是空指针常量,值为零,可以作为作为指针变量的初值。,示例:指针变量的合法的定义形式:int*p1;f

25、loat*p2;int i,j,*p3=,指针的操作指针的操作有两类:直接使用指针本身作为数据值进行操作得到的结果仍然是指针,间接使用指针访问指针所指向的内存单元得到的结果是内存单元的值。指针的直接操作取址与赋值:。,指针的间接操作间接操作指针是指通过指针访问所指向的内存单元的过程具体步骤如下:1)先通过指针的直接操作计算得到内存单元的地址2)再通过间接访问运算符*访问该地址所指向的内存单元,例如,int i,*p1=,指针的使用(1)&*p1的结果如果要在例5.27中显示&*p1的结果该使用指针格式符还是整型格式符?由于p1指向了整型变量j,*p1的结果是间接访问变量j,&*p1的结果则是取

26、变量j的地址,即:&*p1=&(*p1)=&(j)=&j=p1 因此结果是指针,应该使用指针格式符%p。,指针的使用(2)*&i的结果如果要在【例5.27】中显示*&i的结果该使用指针格式符还是整型格式符?&i的结果是整型变量i的地址,*&i的结果间接访问&i指针所提向的整型变量i,即*&i=*(&i)=*(p2)=&p2=i 因此结果是整型值,应该使用整型格式符%d。,指针的使用(3)*p1+与(*p1)+的结果前者是先做+再做*运算,后者则相反。先看前者。*p1+相当于*(p1+),该表达式的含义是首先取*p1的值(即变量j的值60),然后再有p1=p1+1。再看后者。由于指针变量p1指向

27、j,故*p1实际上就是j,因此就有以下等式成立:(*p1)+=j+(*p1)+是先取*p1的值(即j的值,初值为60),然后再有j的值从60增加到了61。,指针的使用(4)&p1的结果&p1的结果是指针变量p1的地址,因此可以使用指针格式符%p来显示。由于该地址的基类型是指针类型,因此该地址是二级指针,即指向的内存单元是指针类型。该指针不能赋值给指针变量p2,因为p2的基类型是整型而不是指针类型。,【例5.28】请给出下面程序的运行结果。#includevoid main()int i=50,j=60,*p,*p1=运行结果如下:50606050,再看几个示例:int A10,*p=A,*q,

28、i=5;1)*p整型指针变量p初始化时赋值为一维数组名A,即A数组中第一元素A0的地址,*p的结果是间接访问p所指向内存单元,即A0。2)*(p+i)同上,p的结果是A0的地址,p+i的作用是调整指针,结果是数组元素A0后面排在第i个位置的数组元素的地址,即Ai的地址,*(p+i)的结果是间接访问指针p+i所指向的内存单元Ai。,再看几个示例:int A10,*p=A,*q,i=5;3)q=语句后如前3)所述,指针变量q通过赋值得到了A5的地址,q+的结果是q加1之前的地址值,仍然是A5的地址,*(q+)的结果是间接访问指针q+所指向的内存单元A5。最后指针变量q会由于+运算增1指向A6的地址

29、,但这不会影响*(q+)的结果。,再看几个示例:int A10,*p=A,*q,i=5;5)*(+q)当执行q=语句后如前3)所述,指针变量q通过赋值得到了A5的地址,+q的结果是修改q,使指针变量q加1,这时q指向A5的下一个单元A6,所以结果是A6的地址,*(+q)的结果是间接访问指针+q所指向的内存单元A6。6)*(A+i)数组名A表示了数组中第一元素的地址,即A0的地址,A+i是指针操作,结果是数组中A0元素之后排在第i个位置的数组元素的地址,即Ai的地址,*(A+i)的结果是间接访问指针A+i所指向的内存单元Ai。,再看几个示例:int A10,*p=A,*q,i=5;7)pi指针变

30、量名p后跟下标操作是一种合法的操作,表示间接访问指针p+i所指向的内存空间,由于p初始化为A0的地址,p+i的结果是A0后第i个数组成员Ai的地址,因此,pi的结果是间接访问数组成员Ai。,指针作为参数地址传递方式是将实参指针赋值给形参指针变量,形参指针变量和实参指针所指向的内存单元是同一个,通过间接访问形参指针变量就能使用该内存单元,数组类型的函数参数采用这种传递方式。使用指针变量作为函数参数可以修改主程序中的内存单元,通过这种方式可以使函数返回多个值,方便了函数的使用。如果修改的主程序中的内存单元是指针类型的,则函数参数需要使用二级指针形参。函数的返回值也可以是指针,指针所指向的单元必须在

31、函数调用结束后仍然存在,不要返回函数中建立的局部变量的地址。,【例5.29】指针参数的使用。#include void swap(int*p1,int*p2)/*注意1*/int temp;temp=*p1;*p1=*p2;*p2=temp;void main()int i=50,j=60;if(ij)swap(,指针数组(理解)讲完了数组与指针,我们来理解一下什么是指针数组 一个数组的元素都是指针型,则称为指针数组。指针数组的定义形式为:类型名*数组名数组长度;例如:int*p4;,【例】有若干个字符串,输出其中最长的字符串。#include main()char*p=teacher,boo

32、k,pascal,hello,and,computer design;char*q;int i;q=p0;for(i=1;istrlen(q)q=pi;printf(%sn,q);,函数指针(了解)函数指针是指函数代码在内存中的开始地址。函数名就是一种函数指针,在函数名后跟一对园括号界定的若干个实际参数就可以从函数代码的开始地址执行函数,称为函数的调用.函数指针变量的定义返回值类型(*函数指针变量名)(参数类型表);说明:参数类型表可以省略,表示该函数指针变量是无参的,这种参数格式的函数指针变量可以接收任意参数格式的函数指针,即对函数的参数个数、顺序及类型均没有要求。返回值类型可以是void表示无返回值。,【例5.34】函数指针变量的使用。#includeint max(int x,int y)int temp;if(xy)temp=x;else temp=y;return(temp);void main()int(*pmax)(int,int);/*注意1:定义函数指针变量*/int i=50,j=60;pmax=max;/*注意2*/printf(%dn,(*pmax)(i,j);/*注意3*/,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号