《二级c语言第七章指针.ppt》由会员分享,可在线阅读,更多相关《二级c语言第七章指针.ppt(61页珍藏版)》请在三一办公上搜索。
1、第七章 指针,内蒙古科技大学工程训练中心,什么是指针?,为了有效的管理各存储单元,我们为每个存储单元进行编号,这个编号就是地址。,地址又称为指针,指针就是存储单元的地址。pointer,内存中有许多存储单元,存储单元用来存放数据。,3050,3052,3054,什么是指针变量?,我们把存储单元地址作为其值的变量,叫做指针变量。,内存中用户数据区,i,j,k,3050,3052,3054,p,用取地址符号“&”来获取地址。p&j;p&i;p&k;,指针变量,如果一个指针变量存放了另一个变量的地址,则形象地称指针变量指向那个变量。,指针变量的定义,指针的定义格式:基类型*指针变量名,*在定义指针变
2、量时和使用指针变量时含义不同。,如:int*p;float*f;char*c;,基类型:用来说明指针要指向的变量类型。不同类型的变量在内存中所占的字节数是不同的。,当进行指针运算时,如指针移动1,系统内部的地址则根据基类型的不同移动不同的字节数,所以必须指定指针变量的基类型。,指向简单变量的指针,如:int a,b,c,*p1,*p2;,10,a=10;b=20;c=30;,20,30,指针变量的三种赋值方式:,1、p1NULL;或 p1=0;,0,2、p1&a;,1000,3、p2p1;,1000,也可以在定义的同时赋值:int a,*p=,指向简单变量指针的使用,如果指针变量p1、p2、p
3、3分别存放整型变量i、j、k的地址,则称p1指向i,p2指向j,p3指向k。如图来直观反应指针变量与指针指向变量的关系。,指针变量的*(取内容)运算:*p1、*p2、*p3,相当于整型变量i、j、k。,int i,*p=&i;scanf(“%d”,p);printf(“%d”,*p);,int i;scanf(“%d”,&i);printf(“%d”,i);,例如:,指针法,变量法,指针的运算,1、引用运算(运算符&、*)(1)取地址运算(&),countptr,count,运算符&称为取地址运算符,它只能作用在变量上,而不能作用在常量或表达式上。它返回的是该变量在内存中的地址。例如:,则语句
4、“countptr=”就是把变量count的地址赋给了指针变量countptr。这时可以说变量countptr指向了变量count,其关系如下所示:,如果有语句:int*countptr,count=7;countptr=,(2)取内容运算(*),如:int a,*p=&a;*(&a)就是a,&(*p)就是p;p指向a,*p与a等价。,取内容运算符“*”,用于获取地址数据对应存储单元的内容。对指针变量进行取内容运算可以得到指针变量所指向的数据。,取内容运算的优先级与取地址运算优先级相同,也为第2级,结合性亦为右结合。取内容运算与取地址运算实质上是一对互逆运算。,#include void ma
5、in()int i,j,sum;int*p,*q;/*定义指针变量*/p=&i;q=&j;/*建立关联*/scanf(%d,%d,p,q);sum=*p+*q;/*使用指针变量*/printf(%d,%dn,*p,*q);printf(和=%d n,sum);,范例1:利用指针,求两个整数的和。,#include void main()char c=a;char*p=&c;printf(%c,%c n,c,*p-32);,范例2:指针运算示例。,#include void main()int a,b,*p,*p1,*p2;scanf(%d,%d,p1,a,范例3:用指针实现两个数由大到小的输出
6、。,2、算术运算 指向数组的指针(1)加减运算 加减运算常用于数组的处理。对指向一般数据的指针,加减运算无实际意义。,float a10,*p=a,*x;x=p+3;/*实际上是p加上3*4个字节赋给x,x依然指向数组的第四个分量*/,int a10,*p=a,*x;x=p+3;/*实际上是p加上3*2个字节赋给x,x指向数组的第四个分量*/,对于不同基类型的指针,指针变量“加上”或“减去”一个整数n所移动的字节数是不同的。例如:,(2)自增自减运算 指针变量自增、自减运算具有上述运算的特点,但有前置后置、先用后用的考虑,务请小心。例如:,*p+相当于*(p+)。*(p+)与(*p)+中的“+
7、”含义不同,前者表示地址自增,后者表示当前所指向的数据值自增。,int a10,*p=a,*x;x=p+;/*x指向数组的第一个元素,p指向数组的第二个元素*/x=+p;/*x、p均指向数组的第三个元素*/,点击 move,进一步了解指针移动。,3.关系运算 两指针的关系运算表示两指针的先后位置关系,一般用于数组处理。除空指针外,不能进行指针与一般数值的关系运算。,变量,a0,地址,1000,1002,1004,1006,1008,内容,a1,a2,a3,a4,p1,p2,1008,1000,(3)指针相减 指针相减得到两指针之间数据的个数,一般用于数组处理。,对数组数据(即数组元素)的操作,
8、可以利用指向数组元素的指针变量来完成,具体步骤如下:第一步:定义基类型与数组类型相同的指针变量。即定义指向数组元素的指针变量。第二步:在指针变量与要处理的数组(元素)之间建立关联。即将相应数组的首地址(或元素地址)赋给指针变量。第三步:使用指针变量的各种运算来实现对各个数组元素的具体操作。,指向一维数组的指针变量,例如,要利用指针处理整型数组a:(1)int a10,*p;/*定义指针变量*/,return,1000,(2)p=a;或 p=&a0;/*建立关联*/,(1)int a10,*p;/*定义指针变量*/(2)p=a;或p=&a0;/*建立关联*/(3)*p即a0,*(p+i)即ai。
9、p+i是下标为i 的数组元素地址,即&ai。*p+是p当前指向的数组元素的下一个元素。,由此得到处理数组的指针法。,数组名法,与指针法相类似的是处理数组的位移法,或称首地址法或数组名法。通过数组的首地址计算出下标为i的数组的元素地址(a+i),那么*(a+i)即ai。注意区别:指针法中p是变量,用来存放数组元素的地址。位移法中a是常量,代表数组的首地址。,方法一:下标法实现数组的输入、输出,范例3:分别用下标法、指针法、位移法输入、输出数组元素。,#include void main()int a10;int i;for(i=0;i=0;i-)printf(%3d,ai);,方法二:指针法实现
10、数组的输入、输出,#include void main()int a10;int i,*p;/*定义指针变量*/p=a;/*建立关联*/for(i=0;i=a;p-)/*使用*/printf(%3d,*p);,方法三:位移法实现数组的输入、输出,#include void main()int a10;int i;for(i=0;i=0;i-)printf(%3d,*(a+i);,#include void main()int a10,i;for(i=0;i=0;i-)printf(“%4d”,ai);,#include void main()int a10,i;for(i=0;i=0;i-)p
11、rintf(“%4d”,*(a+i);,#include void main()int a10,i,*p=a;for(i=0;i=a;p-)printf(“%4d“,*p);,下标法,位移法,指针法,指针移动示例,#include void main()int a6,i,*p;p=a;for(i=0;i6;i+)scanf(“%d”,p+);printf(“n”);for(i=0;i6;i+,p+)printf(“%d”,*p);,a0,a5,p=a;,使用指针变量时应注意的问题:,指针变量的值可以改变。要注意指针变量的当前值。注意指针变量的运算,如先使p指向数组a的首地址(即p=a),则:p
12、+,使p指向下一个元素a1。如果接着执行*p,则取出a1的值。*p+等价于*(p+)作用是:先得到p指向的变量的值(即*p),然后再将p+1=p*(p+)*(+p)的作用不同,前者是先取*p的值,然后使p加1,而后者是先使p加1,再取*p(*p)+表示p所指向的元素的值加1如p当前指向a数组中的第i个元素(即:p=&ai),则:*(p-)相当于ai-先对p进行*运算,再使p自减(指向ai-1)*(+p)相当于a+i 先使p自加,再作*运算*(-p)相当于a-i 先使p自减,再作*运算,综合举例:,练习题,(1)设有定义:int n1=0,n2,*p=,(2)若有定义:int x=0,*p=的输
13、出结果是 A)随机值 B)0 C)x的地址 D)p的地址,(3)有以下程序 main()int a10=1,2,3,4,5,6,7,8,9,10,*p=程序运行后的输出结果是 A)16 B)10 C)8 D)6,作业,1、区别书本113页例7.1与例7.2之间不同。2、熟练掌握书本116页例7.5。用指针变量法改写改进的选择排序程序。3、预习:指向二维数组的指针 指向字符串的指针,用指针变量可以指向一维数组中的元素,当然也可以指向二维数组中的元素。,二维数组元素的地址,设有一个二维数组,它的定义形式为:int a34=1,3,5,7,9,11,13,15,17,19,21,23;,二维数组可以
14、看成数组名分别为a0、a1、a2的一维数组。,指针与二维数组,从二维数组的角度看,a代表二维数组首元素的地址,而现在的首元素不是一个整型变量,而是一个由4个整型数组成的二维数组。因此a代表的是首行(第0行)的首地址,a+1代表的是第1行的首地址,a+2代表的是第2行的首地址。,a0、a1、a2是一维数组,而数组名表示数组首元素的地址,因此a0代表一维数组a0中第0列元素的地址(&a00),a1&a10,a2&a20。,那么列指针如何表示?,a0+0、a0+1、a0+2、a0+3分别是a00、a01、a02、a03元素的地址,,a0和*(a+0)等价,a1和*(a+1)等价,ai和*(a+i)等
15、价。因此a0+1和*(a+0)+1的值都是&a01,a1+1和*(a+1)+1的值都是&a11 不要把*(a+1)+1写成*(a+1+1),得到了数组元素的地址,如想得到其值,在其地址前加一个“*”就可得到数组元素的值。如a0+1和*(a+0)+1都是a01的地址,则*(a0+1)和*(*(a+0)+1)是a01的值。*(ai+j)和*(*(a+i)+j)是aij的值。切记:*(a+i)和ai等价,main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;printf(%d,%dn,a,*a);printf(%d,%dn,a,*(a+0);printf(%d,%
16、dn,例题一 输出二维数组有关的值,#include void main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;int*p,i,j;for(i=0;i3;i+)for(j=0;j4;j+)printf(%4d,aij);printf(n);for(p=a0;pa0+12;p+)printf(%4d,*p);printf(n);,例题二 用指针变量输出数组元素的值,指向二维数组的指针,为了便于访问二维数组,c语言专门设置了指向由n个元素组成的一维数组的指针,定义格式为:类型(*指针名)常量表达式;,如:int(*p)4;说明p指向包含4个整型元素的一维数
17、组。P只能指向一维数组。p+1指向下一个一维数组。即指针移动的不是一个元素,而是一行元素。,如:int a4;/*a有四个元素,每个都为整型*/int(*p)4;/*p有四个元素,每个都为整型,p所指的对象是有4个整型元素的数组。*/,因此,这种类型的指针变量与二维数组名的作用相同,若有p=a,则i行j列的元素地址为*(p+i)+j,即 aij与*(*(p+i)+j)等效,int a33=1,2,3,4,5,6,7,8,9,(*p)3;int i=1,j=2;p=a;printf(“%d”,*(*(p+i)+j);,例题一 用指针变量访问二维数组。,例题二 用指针变量求出二维数组中的最大值。,
18、#include void main()int a34=1,2,3,4,5,6,7,8,9,10,11,12,i,j,(*p)4;int max;p=a;max=*p;for(i=0;imax)max=pij;printf(“%d”,max);,字符串的表示形式,用字符数组存放一个字符串,然后输出该字符串。#include void main()char c=“I have a book!”;printf(“%s”,c);,c是数组名,它代表数组元素的首地址。c&c0、c+1&c1、c+i&ci*(c+3)是c3,c,c0,c13,c12,c11,c10,c9,c8,c7,c6,c5,c4,c
19、3,c2,c1,c14,字符串与指针,用字符指针指向一个字符串,可以不定义字符数组,而定义一个字符指针,用字符指针指向字符串中的字符。,main()char*str=“I have a book!”;printf(“%s”,str);,str,此时定义了一个字符指针变量str,用字符串常量对它进行初始化。C语言对字符串常量按字符数组处理,在内存中开辟一个字符数组用于存放该字符串。对字符指针变量的初始化,实际是把字符串第一个元素的地址赋给str,使得一个字符指针指向一个字符串。也可以采用下面的方式:,char*str;str=I have a book!;,例题一:用字符指针实现字符串的复制,#
20、include void main()char b40,*a=“I have a book!”;char*p1,*p2;p1=a;p2=b;printf(“%s”,p1);while(*p1!=0)*p2=*p1;p1+;p2+;*p2=0;printf(“%s”,b);,a p1,b p2,区别字符指针变量和字符数组:,字符数组由若干个元素组成,每个元素中存放一个字符,而字符指针变量中存放的是地址。定义了字符数组之后,只能对各个数组元素赋值,不能用下面方法对字符数组赋值:char str80;str=“I have a book!”;而对指针变量,可以采用下面方法赋值:char*a;a=“I
21、 have a book”;赋给a的不是字符,是字符串的首地址。对字符指针变量赋初值 char*a=“I have a book”等价于 对数组初始化 char str=“I have a book”不等价,char*a;a=“I have a book”;,char str20;errorstr=“I have a book”,如果定义一个字符数组c10,它有确定的地址,在编译时为它分配10个字节的连续内存单元。如果定义一个字符指针变量,则给指针变量分配 2 个字节的内存单元,其中可以存放一个字符变量的地址。指针变量的值可以改变,而数组名虽代表地址,但它是常量,它的值不可以改变。用指针变量指
22、向一个格式字符串,可以用它代替printf函数中的格式字符串。,char*format;format=“a=%d,b=%fn”;printf(format,a,b);printf(“a=%d,b=%dn”,a,b);,例题二:将字符数组a中的ASCII为奇数的字符复制到b数组中去。,#include void main()char a=“I am a student”,b20;char*p,*q;p=a;q=b;while(*p!=0)if(*p%2!=0)*q=*p;q+;p+;*q=0;printf(“%s”,b);,指针数组,指针变量可以同其它变量一样作为数组的元素,由指针变量组成的数组
23、称为指针数组,组成数组的每个元素都是相同类型的指针。指针数组说明的形式为:类型名*数组名常量表达式;例如:int*p4;,这是定义了一个整型指针数组p,数组元素p0、p1、p2、p3均为指向整型数据的指针。,注意:不要写成 int(*p)4,这是指向整个一维数组的指针变量。,例题三:用指针输出字符串数组,#include void main()char week=Sun,Mon,Tue,Wed,Thu,Fri,Sat;int i;for(i=0;i7;i+)printf(%sn,weeki);,#include void main()char*str=“I have a book!”;prin
24、tf(“%s”,str);,指向指针的指针,使用另一个指针来指向指针数组中的元素,那么这个指针就是指向指针的指针。定义格式:类型*指针变量名例如:char*p;*p相当于*(*p),(*p)是字符型指针变量,*(*p)是指向字符型指针的指针。再如:int*p;*p相当于*(*p),(*p)是整型指针变量,*(*p)是指向整型指针的指针。,#include void main()int a=1,2,3,4,5,6,7,8,9,10,i;int*num10,*p;for(i=0;i10;i+)numi=,a,a0,p,num9,num0,a9,a2,a1,2000,num,3000,p,num1,
25、1、分析以下程序运行结果:#include void main()int x,*p;p=,练习题,10,10,25,3、分析以下程序运行结果:#include void main()int a4=0,1,2,3,*p;p=,1,0 2 4 6 8 10 12 14 16 18,5、矩阵的转置,1 2 34 5 67 8 9,1 4 72 5 83 6 9,6、冒泡法排序,#includemain()int a10=2,1,5,3,10,8,68,4,9,11;int i=0,j=0,t=0;clrscr();for(i=0;iaj+1)t=aj;aj=aj+1;aj+1=t;for(i=0;i
26、10;i+)printf(%d,ai);,a1,a7,a0,a1,a2,a3,a4,a5,a6,a7,a8,7、将一数组元素的数值按照逆序重新存放。,#define N 9#includevoid main()int a9=1,2,3,4,5,6,7,8,9,temp,i,j,m;printf(The original array:n);for(i=0;iN;i+)printf(%5d,ai);printf(n);m=(N-1)/2;for(i=0;i=m;i+)j=N-1-i;temp=ai;ai=aj;aj=temp;printf(The invert array:n);for(i=0;i
27、9;i+)printf(%5d,ai);printf(n);,数组元素逆序存放,8.有一n个元素的整型数组。编写程序使前面元素的数值按顺序向后移动m个位置,而后面m个数值变成前面m个数值。,a0,a1,a2,a3,a4,a5,a6,a7,a8,#define N 9#includevoid main()int a9=1,2,3,4,5,6,7,8,9,b9,temp,i,j,m=3;printf(The original array:n);for(i=0;i=0;i-)ai+3=ai;for(i=0;i3;i+)ai=bi;printf(The invert array:n);for(i=0;
28、i9;i+)printf(%5d,ai);printf(n);,#include#includevoid main()char*q=ab*cde*fg*;char b20,*p;int i,j,len;len=strlen(q);i=0;for(p=q+len-1;*p=*;p-)i+;for(j=0;jlen-i;j+)bj=qj;bj=0;printf(len=%d,i=%d,%s,len,i,b);,9.若有字符串“ab*cde*fg*”,删除字符串最后的“*”,删除后的字符串为“ab*cde*fg”。,10.已知字符串s1和s2,先求其长度,若长度不等,在字符串左侧用“*”补齐,并输出
29、字符串;否则直接输出字符串。,#include#includevoid main()char*p=abc,*q=bsddsfsdfsd,b10,*t=b;int i,j,k=0,m;clrscr();i=strlen(p);j=strlen(q);m=ij?i-j:j-I;for(k=0;kj?strcat(t,q):strcat(t,p);ij?printf(%s,%s,p,t):printf(%s,%s,q,t);,11.从字符串s1中找出子串s2出现的次数。如s1为“dddsdfsded”,s2为“sdf”,则查找结果为1。,#include#includevoid main()char
30、*s1=dddsdfsded,*s2=sdf;int k,m,count=0;clrscr();k=strlen(s2);for(;*s1!=0;)m=0;while(*s1=*s2,指针的概念 二 指针的定义与使用指针与一维数组指针与二维数组,总结,int*p,i;p=,int*p,a10;p=a;,p+i和a+i都是ai的地址*(p+i)或*(a+i)是数组元素ai pi与*(p+i)等价,a0和*(a+0)等价,因此a0+1和*(a+0)+1的值都是&a01 不要把*(a+1)+1写成*(a+1+1),1.a0+0、a0+1分别是a00、a01元素的地址,,得到了数组元素的地址,如想得到其值,在其地址前加一个“*”就可得到数组元素的值。如a0+1和*(a+0)+1都是a01的地址,则*(a0+1)和*(*(a+0)+1)是a01的值。*(ai+j)和*(*(a+i)+j)是aij的值。切记:*(a+i)和ai等价 2.int a34,*p;3.指向一维数组的指针 int a23,(*p)3=a;printf(%d,*(*(p+1)+1);,1、字符串与指针 char*p=“abc”;printf(“%c”,*(p+1);2、指针数组 int*p=“def”,”av”,”cccd”;printf(“%s”,p1);,写出以下两组程序段的屏幕输出结果:,谢 谢 大 家!,