《指针类型》PPT课件.ppt

上传人:小飞机 文档编号:5515997 上传时间:2023-07-15 格式:PPT 页数:140 大小:402KB
返回 下载 相关 举报
《指针类型》PPT课件.ppt_第1页
第1页 / 共140页
《指针类型》PPT课件.ppt_第2页
第2页 / 共140页
《指针类型》PPT课件.ppt_第3页
第3页 / 共140页
《指针类型》PPT课件.ppt_第4页
第4页 / 共140页
《指针类型》PPT课件.ppt_第5页
第5页 / 共140页
点击查看更多>>
资源描述

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

1、,第10章 指针类型,10.1 指针与指针变量 10.2 指针与数组 10.3 指针与字符串 10.4 指针与结构体 10.5 指针与链表 10.6 指针与函数 10.7 指针作基类型 10.8 程序设计举例习 题 十,10.1 指针与指针变量,10.1.1 指针变量的定义,1.定义方法 形式:类型标识符*变量标识符;定义存放指定类型数据地址的指针变量。,例如:(1)int*p1,*p2,*p3;定义指向整型数据的指针变量p1、p2、p3。(2)float*q1,*q2,*q3;定义指向实型数据的指针变量q1、q2、q3。(3)char*r1,*r2,*r3;定义指向字符型数据的指针变量r1、

2、r2、r3。,(4)struct date int year;int month;int day;*t1,*t2,*t3;定义指向struct date类型数据的指针变量t1、t2、t3。,说明:(1)指针变量可与普通变量混合定义,指针变量的定义与普通变量的定义用变量名前加“*”区分。例如:int i,*p;/*定义整型变量i,指针变量p*/(2)空指针“NULL”是一特殊的指针数据,表示空地址,相当于整型数据中的0,字符数据中的空格。,(3)指针变量只能用于存放指定类型数据的地址。如以上定义的一些指针变量,p1、p2、p3只能存放整型数据的地址,q1、q2、q3只能存放实型数据的地址,r1、

3、r2、r3只能存放字符型数据的地址,t1、t2、t3只能存放struct date型数据的地址。,(4)指针变量不能直接赋以具体地址值,不能从键盘输入值。指针变量通过间接赋以相关数据的地址,或调用存储空间分配函数得到值。例如:int i,j,k;int*p1=&i,*p2=&j,*p3=&k;/*p1得到i的地址,p2得到j的地址,p3得到k的地址*/,(5)指针类型隐含在指针变量的定义中。例如,在上面定义指针变量p1、p2、p3时,实际上在背后隐含定义了一指向整型数据的指针类型,从形式上可以将int*看成是指向整型数据的指针类型。与数组定义一样,通过typedef可以将指针类型与指针变量分离

4、。例如,上面定义的指针变量p1、p2、p3,可以改用如下形式:typedef int*INTPOINT;INTPOINT p1,p2,p3;,(6)指针变量本身占有2字节的存储空间。(7)“void*”指针类型定义的指针变量,不指向哪一种特定类型的数据,在实际使用时通过强制类型转换成指向特定类型的数据。,2.指针变量所指向的变量特定类型的数据,例如,对指针变量p1、p2、p3,假定已有值,*p1、*p2、*p3代表指针变量p1、p2、p3所指向的数据,也就是p1、p2、p3的值对应的存储单元里存放的数据,称为指针变量所指向的变量,简称指针指向变量。如果指针变量p1、p2、p3分别存放整型变量i

5、、j、k的地址,则p1指向i,p2指向j,p3指向k。图10-1来直观反应指针变量与指针指向变量的关系。,图 10-1,指针指向变量*p1、*p2、*p3相当于整型变量i、j、k。例如:int*p=&i;scanf(“%d”,p);/*等价于scanf(“%d”,&i)*/printf(“%d”,*p);/*等价于printf(“%d”,i)*/,10.1.2 指针的运算,1.引用运算 1)取地址运算(&)取地址运算“&”,对指针变量进行取地址运算,可以得到指针变量本身的地址。,2)取内容运算(*)取内容运算“*”,前称指针运算,用于获取地址数据对应存储单元的内容。取内容运算的优先级与取地址运

6、算优先级相同,也为第2级,结合性亦为右结合。对指针变量,进行取内容运算可以得到指针变量所指向的数据。取内容运算与取地址运算实质上是一对互逆运算。例如:int a,*p=&a;*(&a)就是a,&(*p)就是p;p指向a,*p与a等价。,2算术运算 指针变量可以进行有限的算术运算。1)加减运算 指针变量“加上”或“减去”一个整数n,相当于指针变量加上或减去n个指针所指向数据的存储单位,即指针由当前指向位置向后或向前移动n个指针所指向数据的存储单位。加减运算常用于数组的处理。对指向一般数据的指针,加减运算无实际意义。例如:int a10,*p=a,*x;x=p+3;/*实际上是p加上3*2个字节赋

7、给x,x指向数组的第三个分量*/,对于不同基类型的指针,指针变量“加上”或“减去”一个整数n所移动的字节数是不同的。例如:float a10,*p=a,*x;x=p+3;/*实际上是p加上3*4个字节赋给x,x依然指向数组的第三个分量*/,2)自增自减运算 指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。例如:int a10,*p=a,*x;x=p+;/*x指向数组的第一个分量,p指向数组的第二个分量*/x=+p;/*x、p均指向数组的第二个分量*/*p+相当于*(p+)。*(p+)与(*p)+含义不同,前者表示地址自增,后者表示当前所指向的数据自增。,3)指

8、针相减 指针相减得到两指针之间数据的个数,一般用于数组处理。,3.关系运算 两指针的关系运算表示两指针的先后位置关系,一般用于数组处理。除空指针外,不能进行指针与一般数值的关系运算。,10.1.3 利用指针处理简单数据,通过指向简单数据的指针变量来处理数据的步骤是:(1)定义以相应简单数据类型为基类型的指针变量。即定义指向简单数据的指针变量。(2)在指针变量与要处理的数据之间建立关联。只需将相应数据的地址赋给指针变量。(3)使用指针所指向的变量来完成数据处理。,例如,要利用指针处理float数据x:(1)float*p;(2)p=&x;(3)*p即x,例 10-1 利用指针,求两个整数的和。/

9、*程序10-1,利用指针,求两个整数的和*/main()int i,j;int*p,*q;/*定义指针变量*/int sum;p=&i;q=&j;/*建立关联*/scanf(%d,%d,p,q);sum=*p+*q;/*使用*/printf(%d,%dn,*p,*q);printf(和=%dn,sum);,例 10 2 指针运算示例。/*程序10-2,指针运算*/main()char c=a;char*p=&c;int a1,a2;int*p1,*p2;a1=100;p1=&a1;a2=(*p1)/3+7;p2=&a2;printf(a1=%d,a2=%d,*p1=%d,*p2=%dn,a1,

10、a2,*p1,*p2);a1=(*p1)+;a2=*p2+;,printf(a1=%d,a2=%d,*p1=%d,*p2=%dn,a1,a2,*p1,*p2);printf(%c,%cn,c,*p);运行结果:a1=100,a2=40,*p1=100,*p2=40 a1=101,a2=40,*p1=101,*p2=随机值(p2指向a2后一个数据单元)a,a,10.1.4 指针作函数参数,例 10 3 将两个整数按从小到大的顺序输出。,先定义一个函数,用指针变量作参数,实现两个数的交换,然后在主函数中调用它,完成两个整数从小到大的顺序输出。,/*程序10-3,将两个整数顺序输出*/void ex

11、chang(p1,p2)/*交换两个数*/int*p1,*p2;int p;p=*p1;*p1=*p2;*p2=p;/*结果通过*p1、*p2带回*/,main()int a,b;int*r,*s;scanf(%d,%d,&a,&b);r=&a;s=&b;if(ab)exchang(r,s);printf(%d,%dn,a,b);输入数据:9,4运行结果:4,9,说明:(1)若在函数中交换指针变量的值,则实参r、s并不改变,指针参数亦是传值。例如:int*p;p=p1;p1=p2;p2=p;不要希望如此能完成处理。,(2)函数中交换值时不能使用无值的指针变量作临时变量。例如:int*p;*p=

12、*p1;*p1=*p2;*p2=*p;p无值,*p无意义,问题由此产生。,10.2 指针与数组,10.2.1 指向一维数组的指针变量,可以利用指向一维数组的指针变量,完成数组数据的操作处理,具体步骤如下:(1)定义与数组相同基类型的指针变量。即定义指向数组的指针变量。(2)在指针变量与要处理的数组(元素)之间建立关联。只需将相应数组的首地址赋给指针变量。(3)使用指针所指向的变量来完成数组元素(数组)的操作处理。,例如,要利用指针处理整型数组a:(1)定义指针变量:int*p;。(2)建立关联:p=a;或p=&a0;。p+i是下标为i的数组分量的地址。(3)使用:*p即a0,*(p+i)即ai

13、。*p+是p当前指向的数组分量的下一个分量。如此得到处理数组的指针法。,与指针法相类似的是处理数组的位移法,或称首地址法。通过数组的首地址计算出下标为i的数组的元素地址(a+i),*(a+i)即ai。指针法中p是变量,用来存放数组元素的地址。位移法中a是常量,代表数组的首地址。,例 10-4 分别用下标法、指针法、位移法输入、输出数组元素。方法一:,/*程序10 4 1,下标法实现数组的输入、输出*/main()int a10;int i;for(i=0;i10;i+)scanf(%d,&ai);printf(n);for(i=0;i10;i+)printf(%3d,ai);,方法二:/*程序

14、10 4 2,指针法实现数组的输入、输出*/main()int a10;int i,*p;/*定义指针变量*/p=a;/*建立关联*/for(i=0;i10;i+)scanf(%d,p+);printf(n);for(p=a;pa+10;p+)/*使用*/printf(%3d,*p);,方法三:/*程序10 4 3,位移法实现数组的输入、输出*/main()int a10;int i,;for(i=0;i10;i+)scanf(%d,&ai);printf(n);for(i=0;i10;i+)printf(%3d,*(a+i);,10.2.2 数组作函数参数,例 10 5 求n个整数的最大值、

15、最小值。求n个数的最大值的一般方法我们已非常熟悉,在这里主要考察引入指针处理数组后,数组作函数参数的应用。假定不超过100个数,数据输入输出在主函数中完成,求最大值、最小值用一个函数完成,n个数用参数传递,最大值、最小值使用全局变量。,方法一:形参用指针,实参用数组名。程序如下:/*程序10 5 1,求n个整数的最大值、最小值*/define L 100int max,min;main()int aL;int n,i;void max-min();printf();scanf(%d,&n);printf(请输入%d个数:,n);,for(i=0;imax)max=*(p+i);if(*(p+i

16、)min)min=*(p+i);,运行结果:请输入数的个数n:6请输入6个数:32 54 7 88 13 49最大值=88,最小值=7,方法二:形参用数组,实参用指针。程序如下:/*程序10 5 2,求n个整数的最大值、最小值*/define L 100int max,min;main()int aL,*p;int n,i;void max-min();printf(请输入数的个数n:);scanf(%d,&n);printf(请输入%d个数:,n);for(i=0;in;i+)scanf(%d,&ai);,p=a;max-min(p,n);/*调用函数*/printf(最大值=%4d,最小值

17、=%4dn,max,min);void max-min(b,x)/*求最大值、最小值函数*/int b,x;int i;max=min=b0;/*最大值、最小值初始化为第一个数据*/for(i=1;imax)max=bi;if(bimin)min=bi;,方法三:形参用指针,实参用指针。程序如下:,/*程序10 5 3,求n个整数的最大值、最小值*/define L 100int max,min;main()int aL,*p;int n,i;void max-min();printf(请输入数的个数n:);scanf(%d,&n);printf(请输入%d个数:,n);for(i=0;in;

18、i+)scanf(%d,&ai);,p=a;max-min(p,n);/*调用函数*/printf(最大值=%4d,最小值=%4dn,max,min);void max-min(q,x)/*求最大值、最小值函数*/int*q,x;int i;max=min=*q;/*最大值、最小值初始化为第一个数据*/for(i=1;imax)max=*(q+i);if(*(q+i)min)min=*(q+i);,10.2.3 指向二维数组的指针变量,1.二维数组的指针,对于二维数组,相当于一张二维表格,存储按行按列存放。二维数组具有首地址、行地址、元素地址等相关指针。数组名代表首地址,称为二维数组的指针;行

19、地址是二维数组中一行的首地址,二维数组中一行相当于一个一维数组;元素地址是二维数组的具体分量地址。,例如,对二维整型数组a45,相当于下面的二维数据表:第0列 第1列 第2列 第3列 第4列 第0行:a00,a01,a02,a03,a04,相当于一维数组a0第1行:a10,a11,a12,a13,a14,相当于一维数组a1第2行:a20,a21,a22,a23,a24,相当于一维数组a2 第3行:a30,a31,a32,a33,a34,相当于一维数组a3,(1)a代表整个二维数组的首地址,也就是第 0 行的首地址。也可用a0、&a00表示。(2)ai代表第i行的首地址。整个二维数组也相当于一个

20、一维数组a0、a1、a2、a3,基于一维数组的处理方法,第i行的首地址还可用*(a+i)、a+i、&ai、&ai0表示。请注意*a表示 0 行首地址,而非a00。,(3)ai+j代表aij的地址。aij的地址还可用*(a+i)+j表示。请注意aij的地址不能用(a+i)+j表示,因为此时实际表示的是第(i+j)行的地址。aij相对a00的绝对地址可用a0+i*5+j计算。如果每行有m个元素,aij相对a00的绝对地址可用a0+i*m+j计算。当然&aij是我们早就知道的aij的地址。,(4)基于上面的分析,引入指针后,二维数组的分量aij可表示成:aij*(ai+j)*(*(a+i)+j)*(

21、a0+i*m+j)相应得到处理二维数组的多种形式位移法。,例10-6 输出一个指定的二维数组。程序如下:/*程序10-6,输出一个指定的数组*/main()static int a45=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;int i,j;for(i=0;i4;i+)for(j=0;i5;j+)printf(%6d,*(a0+i*5+j);printf(n);,运行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 输出语句也可以是:printf(%6d,*(*(a+i)+j

22、);,2.指向二维数组元素的指针变量,利用指向二维数组元素的指针变量,可以完成二维数组数据的操作处理,这也就是处理二维数组的指针法。(1)定义与数组相同基类型的指针变量。(2)在指针变量与要处理的数组(元素)之间建立关联。(3)使用指针所指向的变量来完成数组元素(数组)的操作处理。,例 10 7 输出同例10 6指定数组。/*程序10 7,输出指定数组*/main()static int a45=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;int*p;for(p=a0;pa0+20;p+)if(p-a0)%5=0)printf(n);/

23、*每行输出5个元素*/printf(%6d,*p);,运行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20,3指向整个一维数组的指针变量 一个二维数组相当于多个一维数组。通过指向整个一维数组的指针变量,也可以完成对二维数组数据的操作处理,这也是处理二维数组的指针法。例如:int(*p)5;定义了一个指向具有5个分量的一维数组的指针变量p,p的增值以指向的一维数组为单位,一维数组的5个分量可用(*p)0、(*p)1、(*p)2、(*p)3、(*p)4表示。a是上面定义的数组,如果p=a,则p+i指向a数组的第i行,*(p+i)+j指向a数

24、组的第i行第j列分量,*(*(p+i)+j)即aij。,例10-8 输出上例二维数组中某行某列分量的值。采用指向整个一维数组的指针变量来处理。程序如下:/*程序10-8,输出上例二维数组中某行某列分量的值*/main()static int a45=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;int i,j;int(*p)5;/*定义指向整个一维数组的指针变量p*/p=a;/*建立关联*/scanf(%d,%d,&i,&j);printf(a%d%d=%d,i,j,*(*(p+i)+j);/*输出aij*/,输入数据:3,4 运行结果:

25、a34=12 请注意:(1)定义指向整个一维数组的指针变量必须用“()”,否则定义的是指针数组,指针数组在本章10.7节中做了介绍。(2)指向整个一维数组的指针变量不能指向数组的元素,只能指向二维数组的行。,10.3 指针与字符串,10.3.1 字符串的指针表示,例10-9 字符串的指针表示。main()char*str1;char*str2=computer;scanf(%s,str1);printf(%s,str1);printf(%sn,str2);输入数据:HUNAN运行结果:HUNAN computer,说明:(1)char*str=computer;等价于:char*str;str

26、=computer;实际是将字符串computer的首地址赋给了字符类型的指针变量str。(2)printf(%sn,str);自动转换成:for(str=computer;*str!=0;str+)printf(%c,*str);(3)可以用下标形式引用字符串中的字符,如str0表示c,str5表示t。(4)用指针表示字符串比用数组表示字符串更常用。,例 10 10 字符串的复制。方法一:字符串用字符数组表示,字符数组用位移法处理。程序如下:/*程序10 10 1,字符串的复制*/main()char ss=C LANGUAGE,ts20;int i;for(i=0;*(ss+i)!=0;i

27、+)*(ts+i)=*(ss+i);*(ts+i)=0;printf(原字符串ss=%sn,ss);printf(目标字符串ts=%sn,ts);运行结果:原字符串ss=C LANGUAGE目标字符串ts=C LANGUAGE,方法二:字符串用字符指针表示。程序如下:/*程序10 10 2,字符串的复制*/main()char ss=C LANGUAGE,ts20;char*ps,*pt;ps=ss;pt=ts;for(;*ps=0;ps+,pt+)*pt=*ps;*pt=0;printf(原字符串ss=%sn,ps);printf(目标字符串ts=%sn,pt);,10.3.2 字符串(指针

28、)作函数参数,例10-11 自定义求字符串长度的函数。函数如下:int len(str)/*求字符串长度的函数*/char str;char*p=str;int l=0;while(*p!=0)l+;p+;return(l);,或直接用字符指针作函数参数,函数如下:,int len(ps)/*求字符串长度的函数*/char*ps;int l=0;while(*ps!=0)l+;p+;return(l);,例10-12 用函数实现字符串的复制。函数如下:void copy(from,to)/*字符串复制函数*/char*from,*to;for(;*from!=0;from+,to+)*to=*

29、from;*to=0;,调用时对应实参可以是字符数组,也可以是字符类型的指针。for语句还可改写成:(1)for(;(*to=*from)!=0;from+,to+);(2)for(;(*to+=*from+)!=0;);(3)for(;(*to+=*from+););也可改用while语句:(1)while(*from!=0)to+=from+;(2)while(*to+=*from+)!=0);(3)while(*to+=*from+);,10.3.3 字符指针变量和字符数组的区别,(1)字符数组由若干个元素组成,每个元素中存放字符串的一个字符,而字符指针变量中存放的是字符串的首地址。(2

30、)初始化方式不同。对字符数组初始化要用static存储类别,在编译时进行。而对字符指针变量初始化不必加static,在实际执行时进行。(3)赋值方式不同。对字符数组不能整体赋值,只能转化成份量,对单个元素进行。而字符指针变量赋值可整体进行。例如:char s10;s=C+;/*错,s是常量,怎能被赋值*/,(4)在定义一个字符数组时,编译时即已分配内存单元,有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,但该指针变量具体指向哪个字符串,并不知道,即指针变量存放的地址不确定。例如:char s10;char*p;scanf(%s,s);/*正确*/scanf(%s,p);/*非常

31、危险,p的值动态*/,(5)字符指针变量的值可以改变,字符数组名是一个常量,不能改变。例如,有简单程序:main()char*s=china man;s+=6;printf(%s,s);运行结果:man,10.4 指针与结构体,10.4.1 指向结构体数据的指针变量,对使用指针来处理数据读者应有了一些体会,即先定义一以数据或元素类型为基类型的指针变量;其次在定义的指针变量与要处理的数据之间建立关联,让指针变量指向要处理的数据;然后引用指针指向变量来完成数据的处理。,例 10 13 指向结构体变量的指针变量的应用示例。假设有一结构体,包含某人的姓名和年龄,用指向结构体变量的指针变量完成输出处理。

32、程序如下:,/*程序10 13,指针应用于结构体*/main()struct person char*name;int age;someone;,struct person*p;/*定义结构体类型的指针变量*/someone.name=张三;/*假定姓名为张三*/someone.age=20;p&someone;/*建立关联,*p即someone*/printf(姓名=%s,年龄=%dn,(*p).name,(*p).age);/*等价于printf(姓名=%s,年龄=%dn,someone.name,someone.age);*/运行结果:姓名=张三,年龄=20,运行结果:姓名=张三,年龄=

33、20 说明:(1)在用指向结构体的指针变量描述结构体的分量时必须使用“()”。如不使用“()”,像上例中的“*p.name”,由于“.”运算的优先级比“*”高,这时实际表示的是“*(p.name)”。(2)结构体变量的指针是指结构体变量的首地址,而不是变量中某成员的地址。指向结构体的指针变量不能指向结构体的成员。例如:p=&someone.name;/*错误*/,(3)引入指向结构体的指针变量后,为了书写方便和直观使用,C语言提供指向结构体成员的运算“”来得到结构体的成员。“”运算符由“”和“”复合组成,运算优先级与“.”运算相同。例如,pname、page即someone.name、some

34、one.age。至此,我们有以下三种形式来引用结构体成员:结构体变量.成员名(*结构体指针).成员名 结构体指针成员名,例 10 14 对上例,考虑三个人组成的结构体数组的处理。程序如下:,/*程序10 14,结构体数组的指针处理*/struct personchar*name;int age;struct person sp3=张三,18,李四,19,王五,20;main(),struct person*p;printf(姓名 年龄n);for(p=sp,p name,p-age);运行结果:姓名 年龄 张三 18 李四 19 王五 20,10.4.2 指向结构体的指针作函数参数,例 10

35、15 有40个学生,每个学生包括学号、姓名及成绩,用函数输出成绩最高的学生数据。,/*程序10 15指向结构体的指针作函数参数例*/struct studentint num;char*name;float score;void print(p)/*输出函数*/struct student*p;/*结构体指针作函数参数*/,printf(%d%s%f n,p num,p name,p score);int maxi(p)/*求最高分学生序号的函数*/struct student*p;int i,t;t=0;for(i=1;i*(p+t).score)t=i;return(t);,main()s

36、truct student stu40;int i,k;for(i=0;i40;i+)scanf(%d%s%f,&stui.num,stui.name,&stui.score);k=maxi(stu);/*结构体数组作函数参数*/print(&stuk);/*结构体指针作函数参数*/,10.5 指针与链表,链表与数组不同,是一种动态地进行存储分配的数据结构,表中各元素在内存中可以不连续存放。要查找某一元素,必须先找到上一个元素,根据它提供的下一元素地址才能找到下一个元素。如果不知道第一个元素的地址,则整个链表无法访问。故一般在链表的开头设立头指针,存放第一个元素的内存地址。这样,整个链表就可以

37、从头到尾访问。链表的访问只能从头到尾,故是一种顺序访问,而非随机访问。在结构体中,若只有一个指针成员域,则得到的链表为单链表;若有多个指针成员域,则得到的链表为多重链表。,10.5.1 单链表的数据描述,一般形式:struct 结构体名成员及类型说明;struct 结构体名*指针域;,struct linklistint data;struct linklist*next;struct linklist*head;,指针域成员用于存放下一个数据的地址,由此完成链表中数据请读者注意,定义指针域成员时,结构体“struct 结构体名”的描述并没完成,这实际上形成一种递归定义的结构体类型。C语言允许

38、在定义结构体时这样做,以完成对链表等数据结构的数据描述。,图10-2 单链表,链表中的一个数据称为一个结点。其中,head为头指针,存放链表的第一个结点地址,表示链表的开始。结点A1、A2、An的data域值a1、a2、an为整数;next域存放下一个数据的地址,即A1结点的next域存放A2结点的地址,A2结点的next域存放A3结点的地址,依此类推。最后,An结点后已无结点,其next域为空指针NULL。NULL表示链表结束。,10.5.2 单链表的建立,(1)malloc(size)在内存的动态存储区申请一个长度为size字节的连续空间。(2)calloc(n,size)在内存的动态存储

39、区申请n个长度为size 字节的连续空间,函数返回值为分配空间的首地址。若此函数未被成功执行,函数返回值为0。(3)free(p)释放由指针p所指向的存储单元,而存储单元的大小是最近一次调用malloc()或calloc()函数时所申请的存储空间。,1.头插法,例 10 16 用头插法建立一些正整数链表。,/*程序10 16,用头插法建立一些正整数链表*/main()struct linklist int data;/*数据域*/struct linklist*next;/*指针域*/;struct linklist*head,*p;/*head头指针,p申请单元指针*/head=NULL;/

40、*空链表*/,/*申请空间,并将指针强制转换成所指向的结构体类型*/p=(struct linklist*)malloc(sizeof(struct linklist);scanf(%d,&pdata);/*得到数据,放结点数据域*/while(pdata0)pnext=head;/*建立链接,当前结点指针域存放下一结点地址*/head=p;/*用头指针保存当前结点*/*为下一个结点申请空间*/p=(struct linklist*)malloc(sizeof(struct linklist);scanf(%d,&pdata);/*得到新结点数据*/,2.尾插法,若将链表的左端固定,链表不断向

41、右延伸,这种建立链表的方法称为尾插法。尾插法建立链表时,头指针固定不动,故必须设立一个搜索指针,向链表右边延伸,则整个算法中应设立三个链表指针,即头指针head、搜索指针p2、申请单元指针p1。尾插法最先得到的是头结点。,例10-17 用尾插法建立一些正整数链表。/*程序10 17,用尾插法建立一些正整数链表*/main()struct linklist int data;struct linklist*next;,struct linklist*head,*p1,*p2;head=NULL;/*空链表*/p1=(struct linklist*)malloc(sizeof(struct li

42、nklist);/*申请空间*/scanf(%d,&p1-data);/*得到数据*/while(p1-data0)if(head=NULL)head=p1;else p2-next=p1;/*建立连接*/p2=p1;/*保存当前结点*/*为下一个结点申请空间*/p1=(struct linklist*)malloc(sizeof(struct linklist);scanf(%d,&p1data);/*得到下一个结点数据*/p2next=NULL;/*最后的尾结点指针域为空指针*/,10.5.3 单链表的基本操作,注意两点:(1)将链表传递进函数,只需将链表头指针传递进函数。函数的形参对应实

43、参头指针。(2)对链表的访问用条件循环控制,循环的条件是结点的指针域非空。,1.输出链表中所有结点void print(struct linklist*head)/*输出链表所有结点*/struct linklist*p;p=head;/*p指向链表第一个结点*/while(p!=NULL)printf(%d,p-data);p=p-next;/*p指向下一个结点*/,2.统计链表中结点个数只需将上述输出结点改成计数即可。int count(struct linklist*head)/*统计链表中结点个数*/int n=0;struct linklist*p;p=head;while(p!=N

44、ULL)n+;p=p-next;return(n);,3.插入操作,void ins(struct linklist*head,int i,int x)/*插入结点*/int j;struct linklist*p,*q;p=head;j=1;while(p!=NULL)&(jnext;j+;q=(struct linklist*)malloc(sizeof(struct linklist);/*产生插入结点*/q-data=x;q-next=p-next;/*q插入p之后*/p-next=q;,4.删除操作,假设删除链表中第i个结点,先找到第i-1个结点和第i个结点,然后将第i+1个结点链接

45、在第i-1个结点后,再释放第i个结点所占空间,完成删除操作。,void del(struct linklist*head,int i)/*删除结点*/int j;struct linklist*p,*q;p=head;j=1;while(p!=NULL)&(jnext;j+;if(p=NULL)printf(找不到结点!);else q-next=p-next;/*删除第i个结点*/free(p);,双链表有两个指针域,一个指针指向左边结点,一个指针指向右边结点,用头指针表示开始结点,用尾指针表示结尾结点。例如:最简单的双链表可用如下递归结构体描述:struct linklist int da

46、ta;struct linklist*llink,*rlink;struct linklist*head,*rear;,10.6 指针与函数,10.6.1 指向函数的指针变量,1.定义指向函数的指针变量 形式如下:类型标识符(*变量标识符)();类型标识符是指针变量所指向的函数类型,变量标识符是指向函数的指针变量名。例如:int(*p)();,说明:(1)定义指向函数的指针变量,可以指向一类函数。(2)定义指向函数的指针变量时,括号不能省略。例如,int*p()定义的是指针函数头,返回值是指向整型数据的指针值,而不是指向函数的指针变量。(3)对指向函数的指针变量p,p+i、p+、p-等运算无意

47、义。,2.让指针变量指向函数 定义了指向函数的指针变量,就可以在指针变量与特定函数之间建立关联,让指针变量指向特定函数。建立关联的方法为:指针变量=函数名;说明:(1)指针变量只能指向定义时所指定的一类函数。(2)一个指针变量可以先后指向多个不同的函数。,3.利用指针实现函数调用 指针变量一旦指向某函数,利用指针所指向的变量可以实现函数调用。调用形式:(*指针变量)(实参表);,例 10 18 通过指针调用函数。/*程序10 18,通过指针调用函数,求两个数的最大值*/float max(x,y)/*求两个数的最大值*/float x,y;float z;z=(x=y)?x:y;return(

48、z);main()float(*p)();/*定义指向一类实型函数的指针变量*/float a,b;float m;scanf(%d,%d,&a,&b);p=max;/*建立关联*/m=(*p)(a,b);/*利用指针实现函数调用*/printf(a=%d,b=%d,max=%dn,a,b,m);,10.6.2 指向函数的指针变量作函数参数,例 10 19 编制程序,调用一个多功能函数,对于最大值函数参数,求两个数的最大值;对于最小值函数参数,求两个数的最小值。,程序如下:/*程序10-19,指向函数的指针变量作函数参数例*/main()int maxf(),minf(),fun();int

49、a,b;int max,min;scanf(%d,%d,&a,&b);max=fun(a,b,maxf);/*多功能函数求最大值*/min=fun(a,b,minf);/*多功能函数求最小值*/printf(最大值=%d,max);printf(最小值=%d,min);,int maxf(x,y)/*最大值函数*/int x,y;if(xy)return(x);else return(y);int minf(x,y)/*最小值函数*/int x,y;if(xy)return(x);else return(y);int fun(x,y,p)/*多功能函数*/int x,y;int(*p)();/

50、*p参数为指向整型函数的指针变量*/int result;result=(*p)(x,y);/*通过指针调用函数*/return(result);,输入数据:28,32 运行结果:最大值=32 最小值=28 第一次调用fun()函数时,除了将a、b的值传递给x、y外,还将函数maxf()的入口地址(maxf)传递给指向函数的指针变量p,这时函数fun()中的(*p)(x,y)相当于maxf(x,y)。第二次调用fun()函数时,a、b的值同样传递给x、y,另将函数minf()的入口地址(minf)传递给指向函数的指针变量p,这时函数fun()中的(*p)(x,y)相当于minf(x,y)。,1

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

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


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号