《(中职)C语言程序设计模块八电子课件.pptx》由会员分享,可在线阅读,更多相关《(中职)C语言程序设计模块八电子课件.pptx(54页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、YCF正版可修改PPT(中职)C语言程序设计模块八ppt电子课件LOGO指针模块88.1指针的基本概念在计算机中,所有数据都是存放在存储器中的。各数据类型占用不等的内存单元,如int型占2 B、long型占4 B等。在16位环境中,规定指针占2 B的内存单元,以此为基准,32位环境中为4 B,64位环境中为8 B。指针理解如图8-1所示。图8-1指针理解8.1指针的基本概念(1)内存单元:一般把1个字节(1 B)作为一个内存单元(8 bit)。数据以二进制码形式存储于内存单元中。(2)指针及指针值:给每个内存单元编号(如1000),就可以快速准确地找到该内存单元。这个编号也称地址,这种地址就是
2、指针。因此,指针值就是地址。(3)指针变量:把指针保存于某个变量中,这个变量称为指针变量。上图中,数组a有6个元素值,p为指针变量,保存有6个地址,这6个地址分别对应6个元素值的内存单元。通过这6个地址,就能快速地找到数组a的6个值。因而,p是指向数组a的指针。一个指针是一个地址,是常量;而一个指针变量却可以被赋予不同的指针值,是变量。因此,严格地说,指针和指针变量并不是同一个概念。而在日常中,为了称呼方便,我们常把指针变量称为指针。读者对此应有清晰的认识。8.2指针变量的定义和初始化一般指针变量值初始化为单变量地址:int*p,a;p=&a;/*定义一个整型指针p,该指针指向整型变量a的地址
3、*/写为一行就是:int a,*p=&a;指针变量值初始化为单变量地址时,不要忘了“&”运算符。再如:float m,*pf=&m;8.2.1一般指针变量的定义与初始化8.2指针变量的定义和初始化8.2.2一维数组指针变量的定义与初始化一维数组指针变量值初始化时,只需指向数组名即可,因为数组名即为该数组首元素首地址。int a10,*p;p=a;/*定义一个一维数组指针p,该指针指向一维数组a*/因为数组名代表首元素首地址,因此p=a等价于p=&a0。写为一行就是:int a10,*p=a;再如:float b5,*pf=b;由此可见:数组名、指针及第1个元素首地址均指向同一个内存单元。8.2
4、指针变量的定义和初始化8.2.3二维数组指针变量的定义与初始化定义规则:类型(*指针变量名)长度长度指的是二维数组的列数。int a23,(*p)3;p=a;/*定义二维数组指针p,该指针指向二维数组a*/写为一行就是:int a23,(*p)3=a;要特别注意的是:不能忘记(),否则就变成了指针数组(后述)。区分:int a23,*p3;/*这里p是指针数组名而不是数组指针*/8.2指针变量的定义和初始化8.2.4字符串指针变量的定义与初始化依上得知:字符串指针就是字符数组的首地址。char*p,c8;p=c;/*定义字符串指针p,该指针指向字符数组c的首地址*/写成一行就是:char c8
5、,*p=c;在定义字符串指针变量时,可以给该指针变量初始化字符串,但要明白的是:该指针变量不是“存放”字符串,而是指向字符串的首地址。char*q,*p=How are you;q=Nice to meet you;这里定义了两个字符串指针,p指向字符串How are you的首地址(元素H的地址),q指向字符串Nice to meet you的首地址(元素N的地址)。8.2指针变量的定义和初始化8.2.4字符串指针变量的定义与初始化最后需要指出的是:(1)指针变量在使用前必须初始化,否则会影响程序的运行,甚至崩溃。(2)指针变量的初始化只有三种情况:赋地址。赋空值。例如,“int a,*p=
6、NULL;”,赋空值表示不指向任何内存单元。赋0,如“int a,*p=0;”。(3)任何指针只能指向其同类,即指针变量的类型必须和其指向的变量类型一致。8.2指针变量的定义和初始化函数指针,顾名思义,就是指向函数的指针。1.函数指针的定义类型(*函数指针变量名)();注意两个()都不能少。例如,“int(*p)();”定义一个函数指针p,该指针指向一个返回值为int型的函数;“float(*p1)(float);”定义一个函数指针p1,该指针指向一个具有float形参,返回值为float型的函数。2.函数指针的初始化假设有float型函数fm()和fn()。函数名是函数的入口地址,同数组名一
7、样,是常量。函数指针的初始化就是指向函数名。同样,函数指针与其指向的函数必须是同一类型的。例如:float(*p1)(float),(*p2)(float);p1=fm;p2=fn;写为一句就是:float(*p1)(float)=fm,(*p2)(float)=fn;8.2.5函数指针的定义与初始化8.3指针的运算指针的运算总体上表述为以下三个方面:(1)指针本身只有两个运算符。&取地址取变量地址。*取内容取指针所指向变量的内容。8.3指针的运算(2)指针的数学运算。指针的数学运算指的是指针的加减运算。必须理解以下几点:指针的加减运算只针对数组而言,其他类型指针的加减运算无意义。举例有“in
8、t a5=1,2,3,4,5,*p=a;”。a.p+2的含义并不是0+2,而是指向a0后2个元素即a2的首地址,但指针位置没有移动。b.p+的含义是引用p的当前值之后(先运算)指针移向下一个元素(再自增),指针位置移动到了a1。c.-p的含义是指针先移向上一个元素(先自减)。同一指针在数组内的加减运算同上。举例有“int a5=1,2,3,4,5,*p=a,*p1=&a4;”。a.p1-p是成立的,结果为4,意为两个指针之间的元素个数。b.p1+p是无意义的,即指向同一数组的两个指针相加是没有意义的。8.3指针的运算(3)指针之间的关系运算。p1=p2,指针p1,p2指向同一内存单元(或元素地
9、址)。p1p2,指针p1处于高地址位置。p1p2,指针p1处于低地址位置。只有同类型的指针才能进行比较。8.3指针的运算8.3.1指针内存地址考查及指针类型的转换1.指针内存地址考查(1)指针偏移量的计算。举例有“int a20=1,2,3,4,5,*p=a;float b10,*p1=b;”。下面的四个例子举的是单独存在的情况:“p+;”:指针移动到a1位置处,指向该元素首地址,偏移量为“1sizeof(int)=12=2”,即2个字节。“p+3;”:指针指向a3元素首地址,偏移量有“3sizeof(int)=32=6”,即6个字节;但指针p还停留在a0,指向a0首地址。“p1+2;”:指针
10、指向b2元素首地址,偏移量有“2sizeof(float)=24=8”,即8个字节;但指针p还停留在b0,指向b0首地址。“p1+;”:指针移动到b1位置处,指向该元素首地址,偏移量为“1sizeof(float)=14=4”,即4个字节。8.3指针的运算8.3.1指针内存地址考查及指针类型的转换(2)内存地址的运算。以上面为例,若int型指针p地址为ffea,float型指针p1地址为ffec:同上面一致,下面的四个例子举的是单独存在的情况:p+:ffea+12=15 15 14 10+2=15 15 14 12=ffec。p+3:ffea+32=15 15 14 10+6=15 15 15
11、 0=fff0(十六进制,逢16进1,下同)。p1+2:ffec+24=15 15 14 12+8=15 15 15 4=fff4。p1+:ffec+14=15 15 14 12+4=15 15 15 0=fff0。在实际运用中,要根据指针的实际情况来计算偏移量。例如,“int a20=1,2,3,4,5,*p=a;”,若指针p的地址为ffea,则p+;p+3;这时指针p的偏移量应该是fff0。8.3指针的运算8.3.1指针内存地址考查及指针类型的转换2.指针类型的强制转换指针的转换指的是指针类型的强制转换,如把字符串型指针p强制转换为整型,即(int*)p。指针类型被强制转换以后要注意其位移
12、长度的变化。注意:指针移动的长度是其数据类型的长度;16位环境下指针内存长度规定都是2个字节,用sizeof()运算符可以查看。因此,不要把二者混淆。#include int main()char*p=123456789;int*x;/*整型指针变量,2 B(字节),起始位0*/8.3指针的运算8.3.1指针内存地址考查及指针类型的转换char*m;/*字符型指针变量,1 B(字节),起始位0*/int*y;/*整型指针变量,2 B(字节),起始位0*/x=(int*)p;/*字符指针强制转换为整型指针赋给x*/y=(int*)p;/*字符指针强制转换为整型指针赋给y*/x+;/*整型指针下移
13、1次,2 B(字节),位置到3*/x+;/*再下移1次,2 B,位置到5*/x+;/*再下移1次,2 B,位置到7*/printf(%sn,x);/*输出789*/printf(%sn,y);/*输出123456789*/m=(char*)x;/*整型指针强制转换为字符型指针赋给m*/m+;/*下移1位,到8*/printf(%s,m);/*输出89*/8.3指针的运算8.3.2一般指针变量的运算示例1:#include int main()int a=5,*p,x;p=&a;/*取变量a的地址给指针p*/x=*p;/*对指针p取内容,将结果赋给变量x*/printf(%d-%d,x,*p);
14、/*输出5-5*/示例2:#include int main()int a=100,*p1,*p2,x;p1=&a;/*取变量a的地址给指针p1*/p2=p1;/*p1赋给p2,则p2也指向了变量a的地址*/x=*p2;/*对指针p2取内容,取得100,赋给x*/a=20;printf(x=%dn,x);/*输出x=100*/printf(x=%d,*p2);/*这里的*p2在a=20之后,输出x=20*/8.3指针的运算8.3.2一般指针变量的运算示例3:#include int main()int a=10,b=20,s,t,*p1,*p2;p1=&a;p2=&b;s=*p1+*p2;/*
15、取内容求和运算,s得30*/t=*p1*p2;/*取内容求积运算,t得200*/printf(s=%d,t=%dn,s,t);/*输出s=30,t=200*/由此可见,如果有变量x及指向变量y的指针p:int x,y,*p;p=&y;“x=y;”则等价于“x=*p;”。“y+;”则等价于“(*p)+;”。“x=y+1;”则等价于“x=(*p)+1;”。8.3指针的运算8.3.3指向一维数组的指针运算示例1:#include int main()int a5=4,5,0,6,8,*p,*p1;p=a;printf(%dn,*p);/*依前所述,这里*p其实就是*(&a0),即对首元素地址进行取内
16、容运算,输出4*/p=p+1;/*p+1指的是指针向右移1位,到了地址&a1*/printf(%dn,*p);/*等同于*(&a1),输出5*/p1=p+;/*先运算再自增,p1获得地址&a1,指针8.3指针的运算8.3.3指向一维数组的指针运算p增1,指向了a2的地址&a2*/printf(%dn,*p1);/*等同于*(&a1),输出5*/p=+p;/*先自增再运算,*p在前面已指向了&a2,这里再增1,则指向了&a3*/printf(%dn,*p);/*等同于*(&a3),输出6*/printf(%dn,*(+p);/*指针p再增1,指向了&a4,*(&a4)运算,结果为8*/print
17、f(%d,*(p-2);/*p指向的是&a4,p-2意为指针向后退2位,到&a2,*(&a2)运算,结果为0*/p=&a4;/*强制指针p直接指向&a4*/printf(%d,*p);/*等同于*(&a4),输出8*/8.3指针的运算8.3.3指向一维数组的指针运算示例2:#include int main()int a5=4,5,0,6,8,*p;p=a+1;/*指针初始化指向地址&a1*/printf(%dn,*(a+3);/*数组名是首元素首地址,向右移3,到&a3 这个地址,取内容,即6*/printf(%dn,a3);/*直接输出a3这个元素的值,即6*/printf(%dn,*(&
18、a3);/*对a3地址取内容运算,即6*/printf(%dn,*(p+3);/*指针向右移3到&a4,取内容即8*/8.3指针的运算8.3.3指向一维数组的指针运算上面两个例子充分体现了指向一维数组的指针运算,可以归纳如下:(1)数组名、数组指针和首元素地址都指向同一个内存单元,运算时可得以下等价关系(每一列对应的内容是等价的,见表8-1)。在“int a10,*p=a;”中:取一例说明(前提是保证指针p指向数组名a):等价地址:a+1=p+1=&a0+1=&a1;等价取值:*(a+1)=*(p+1)=*(&a0+1)=*(&a1)。表8-1指向一维数组的指针运算8.3指针的运算8.3.3指
19、向一维数组的指针运算(2)根据上述知识,对数组的赋值便有三种方法,即元素赋值法、地址法和指针法。8.3指针的运算8.3.4指向二维数组的指针运算掌握了一维数组指针的运算,学习二维数组指针的运算就比较容易了。因为二维数组本质上是多个一维数组的集合。1.二维数组元素地址取值运算假设有34矩阵b,指针p指向这个矩阵,即“int b34,(*p)4=b;”,i代表行变量,j代表列变量。二维数组行列地址取法过程及取值过程如下:(1)二维数组的数组名代表二维数组的首地址,这个首地址具体来说就是第0行的首地址。例如,在本例中,数组名b代表b+0(第0行)的首地址。以此类推,可知:第0行首地址:b+0(首组名
20、b);第1行首地址:b+1;第2行首地址:b+2;第i行首地址:b+i。8.3指针的运算8.3.4指向二维数组的指针运算(2)对行地址进行“*”运算,得到第x行第0列的元素地址:第0行第0列的元素地址:*(b+0),即b0;第1行第0列的元素地址:*(b+1),即b1;第2行第0列的元素地址:*(b+2),即b2;第i行第0列的元素地址:*(b+i),即bi。(3)二维数组的元素地址由行+列构成:第0行第0列的元素地址:*(b+0)+0,即b0+0,即&b00;第0行第1列的元素地址:*(b+0)+1,即b0+1,即&b01;第1行第1列的元素地址:*(b+1)+1,即b1+1,即&b11;第
21、1行第2列的元素地址:*(b+1)+2,即b1+2,即&b12;第i行第j列的元素地址:*(b+i)+j,即bi+j,即&bij。8.3指针的运算8.3.4指向二维数组的指针运算(4)对地址进行“*”运算(取内容运算)即可得到该地址指向的元素的值:对第1行第1列的元素地址取值:*(*(b+1)+1),即*(b1+1),即*(&b11);对第2行第2列的元素地址取值:*(*(b+2)+2),即*(b2+2),即*(&b22);对第i行第j列的元素地址取值:*(*(b+i)+j),即*(bi+j),即*(&bij)。用二维数组指针变量取代数组名,对第i行第j列的元素地址取值,即为:*(*(p+i)
22、+j),即*(pi+j),即*(&pij);完全等同于*(*(b+i)+j),即*(bi+j),即*(&bij)。以下列34矩阵为例(int b34,(*p)4=b;),对元素取值举例(见表8-2)8.3指针的运算8.3.4指向二维数组的指针运算表8-2元素取值举例8.3指针的运算8.3.4指向二维数组的指针运算指针数组,意即数组的元素均为指针。(1)指针数组的定义方法。类型*指针数组名数组长度例如,“int*p4;”定义了一个名为p的带4个整型指针元素的指针数组。一定要把它和数组指针区别开来。“int(*p)4;”定义了一个名为p的数组指针,4为所指向数组的列数。2.指针数组8.3指针的运算
23、8.3.4指向二维数组的指针运算(2)指针数组的初始化。给指针数组初始化时,如果指向二维数组,赋的是二维数组每一行的首地址。例如:static int a33=1,2,3,4,5,6,7,8,9;int*p=a0,a1,a2;其元素值如下:(3)指针数组的运算。8.3指针的运算8.3.4指向二维数组的指针运算【例8-1】指针数组元素取值运算示例。#include int main()static int a33=1,2,3,4,5,6,7,8,9;int*p=a0,a1,a2;printf(%d-%dn,*p0,*p1);/*这里*p0等价于*a0,*p1等价于*a1,意为对一、二行首元素首地
24、址进行取值运算,输出14*/printf(%d-%d,*(p0+1),*(p1+2);/*这里*(p0+1)等价于*(a0+1),从第1行首元素地址右移1位进行取值,即值2;*(p1+2)等价于*(a1+2),从第2行首元素地址右移2位进行取值,即值6,输出26*/由上可知,由于指针数组里存放了每一行的首地址,在对数组元素进行取值时,只需将指针数组元素移动到相应的元素位置,再对该地址进行“*”取值运算即可。8.3指针的运算8.3.4指向二维数组的指针运算3.数组指针和指针数组取值示例#include int main()static int a34=1,2,3,4,5,6,7,8,9,10,(
25、*p1)4=a;int*p2=&a00;int*p3=a0,a1,a2;printf(%d,*(*(p1+1)+1);/*p1数组指针,等同于*(&a11),输出6*/printf(%d,(*(p1+1)2);/*p1数组指针,等同于a12,输出7*/printf(%d,*(p2+7);/*p2元素指针,初值为指向第1个元素地址,移动7个位置,到8*/8.3指针的运算8.3.4指向二维数组的指针运算 printf(%d,*(p32+1);/*指针数组元素,从第3行首地址右移一个,输出10*/printf(%d,*(a+1)1);/*变址运算符高于取值运算符*,对地址(a+1)变址,加1,实际变
26、成了a+2,*(a+2)为第3行首地址,输出9/要注意上例中的变址运算符,它排在最高级,其运算就是在原址上加减。上例中:“printf(%d,*(a+1)1);”就是在原址(a+1)的基础上加1,变为(a+2)。“printf(%d,*(a+1)-1);”就是在原址(a+1)的基础上减1,变为(a+0),即a。8.3指针的运算8.3.5指向字符串的指针运算字符串指针与其他指针的运算最大的差别就在于:(1)无须用“*”取内容运算符。因为一个字符就是一个存储单元,而且是连续的。(2)取得了某个地址,便可输出该地址后面的字符串(字符串以0结束为准)。例如:#include int main()cha
27、r str1=We are all students,*p1=str1;char str2=s,o,r,r,y,0,*p2=str2;char str3=A,b,o,y,0,*p3=str3;char*p4=This is a book;static char str420=good,year,book,high school;char*p=str40,str41,str42,str43;8.3指针的运算8.3.5指向字符串的指针运算printf(%sn,str1);/*数组名为首元素首地址,输出“We are all students”这个串*/printf(%sn,p1);/*p1指针指向
28、str1,输出“We are all students”这个串*/printf(%sn,p1+3);/*从首地址右移3个位置到a这个元素值地址,输出“are all students”*/printf(%sn,str1+3);/*从首地址右移3个位置到a这个元素值地址,输出“are all students”*/printf(%sn,str2);/*输出首地址后面的串,即“sorry”*/printf(%sn,p2);/*p2指针指向str2,输出“sorry”*/printf(%sn,p2+2);/*p2指针右移2位到r这个位置,输出“rry”*/printf(%sn,str3);/*首地址
29、,输出“A boy”*/printf(%sn,p3);/*首地址,输出“A boy”*/printf(%sn,p3+2);/*指针右移2位到b,输出“boy”*/printf(%sn,p4);/*指针p4代表首元素首地址,输出“This is a book”*/8.3指针的运算8.3.5指向字符串的指针运算printf(%sn,p4+5);/*从首地址右移5个位置到i,输出“is a book”*/printf(%sn,p3);/*指针数组元素,指向str43,输出“high school”*/printf(%sn,p3+5);/*指针数组元素,从第4行首地址向右移动5个位置到s,输出“sch
30、ool”*/printf(%sn,p1+1);/*指针数组元素,从第2行首地址向右移动1个位置到e,输出“ear”*/说明:(1)字符串指针变量存放的是字符串首元素首地址,而不是整个字符串。这一点一定要注意理解。(2)在没有指定字符数组长度时,以单个字符赋值给字符数组时,末尾必须加0,以示赋值完整。若指定了长度且进行了完整赋值,就不必赋0。8.3指针的运算8.3.6二级间址1.二级间址的含义前面的指针学习均是单级间址,也就是一级指针,一个指针变量中存放一个目标变量地址。例如,“int*p=&a;”指针p只存放变量a的地址。所谓二级间址,其意是通过一个指针指向另一个指针达到访问变量地址的目的,也
31、可称为二级指针。更通俗地讲就是指向指针的指针。要注意的是:二级指针不能跳过一级指针直接取值,表示如下:p是一级指针,pp是二级指针,pp指向p,p指向数组a。2.二级指针的定义类型*指针变量名例如,“int*p;”。8.3指针的运算8.3.6二级间址3.二级指针运算示例通过二级指针运算循环输出数组元素值。#include int main()int a5=8,6,7,9,10,i,*p=a;/*定义p为一级指针,指向数组a*/int*pp=&p;/*定义pp为二级指针,指向p的地址*/for(i=0;i5;i+)printf(%d,*(*pp+i);/*这里*pp取得p地址,+i则是对地址位移
32、,最后*取内容*/putchar(n);for(i=0;i5;i+,p+)printf(%d,*pp);/*对上面的p+进行循环取地址、取内容运算*/由上可知:二级指针的运算是先通过对一级指针进行“*”取地址内容运算,再进行一次“*”取元素值内容运算。以上面的二级指针pp为例进行说明:*pp:取得一级指针的地址;*pp:对一级指针指向的元素地址取内容。8.3指针的运算8.3.6二级间址8.3指针的运算8.3.7指向函数的指针运算函数指针指向函数名。关于函数名,在前面已有叙述。函数名是函数的入口地址,同数组名一样,是常量。有时需要交换函数名来进行运算,这时就要用到函数指针了。因为函数名是常量,是
33、不能直接交换的,而函数指针是变量,因而可以通过函数指针进行函数名的交换。下例就是通过函数指针交换了函数名,从而改变了运算结果。#include float fm(float n)returnn*n;float fn(float n)return2*n;int main()8.3指针的运算8.3.7指向函数的指针运算float(*p1)(float),(*p2)(float),(*t)(float),x,y;/*定义三个函数指针,其中t作为临时指针*/p1=fm;p2=fn;x=p2(p1(2);/*先p1(2)调用,即fm(2),得4。再p2(4),即fn(4),得8*/t=p1;p1=p2;
34、p2=t;/*通过函数指针交换了函数名,即p1指向了fn,p2指向了fm*/y=p2(p1(2);/*交换后的运算,p1(2)即fn(2),得4。p2(4)即fm(4),得16*/printf(x=%.0f,y=%.0f,x,y);/*输出:x=8,y=16*/8.3指针的运算8.3.8函数调用中的地址传递在函数调用过程中,当作为形参的指针调用实参时,获取的是地址,或者说传递的只能是地址。因此,形参和实参指向的都是同一个地址,具体来说,就是相同的内存单元。因而,如果有值的变化,不分形参和实参,本质上就是同一段内存值的变化。比较下面地址传递和值传递的运算结果:8.3指针的运算8.3.8函数调用中
35、的地址传递8.3指针的运算8.3.8函数调用中的地址传递在下面的程序中,分多种情况在主函数中输出x,y的值,查看其变化。#include int fun(int*x,int*y)int t;t=*x;*x=*y;*y=t;/*x=5,y=3,通过t交换了值*/y=x;*x=*y;*y=*x;/*x=3,y=5,x地址给了y,此时只有x这一段内存在活动,仍然为3,y没有参加活动,不变,仍为5*/x=y;*y=*x;*x=*y;/*x=3,y=5,y地址给了x,此时只有y这一段内存在活动,仍然为5,x没有参加活动,仍然为3*/*x=*y;*y=*x;/*x=5,y=5*/int main()int
36、 x=3,y=5,*p1=&x,*p2=&y;fun(p1,p2);printf(x=%d y=%dn,x,y);putchar(n);8.4指针的应用【例8-2】提取字符串中的数字字符。提取字符串2you38are85a12student6l9中的数字字符。#include void f(char*p)char ch100;/*用于存放数字字符*/long a100;/*用于存放转化后的数学字符*/int k=0,sign=0,j=0;static long s;do s=0;if(*p&*p=0&*p=9)sign=1;/*数字字符标记为1*/chk+=*p;/*数字字符保存到字符数组ch
37、中,注意k运算后会再增1*/else if(sign=1)/*对数字字符进行求和运算*/8.4指针的应用int i;for(i=0;ik;i+)/*不能写成i=k,因为k+自增了1位,超出了数组ch的下标范围*/s=s*10+chi-0;/*把字符转化为数学数字(如38转为38)*/aj+=s;/*保存到long数组a中,j也要自增1*/k=0;/*必须重新赋0,回到上面的if中*/sign=0;/*标记复位*/p+;/*最后一个字符参与了运算后,p+意味着指针p实际上已移到了0符处。因至少还要做一次循环,故指针p到了结尾符0后面*/while(*(p-1)!=0);/*所以此处只能写p-1*
38、/for(k=0;kj;k+)printf(%ld,ak);int main()char*p=2you38are85a12student6l9;f(p);输出结果:2388512698.4指针的应用【例8-3】插入字符串。把字符串good插入字符串luck之前。其原理是通过指针移动、对指针取元素值等移动相应位置的元素,腾出内存单元,再在这个内存单元中插入字符。#include#include void f(char ch,char*p)int i;char*q,*t=ch;for(i=0;istrlen(ch)/2;i+)t+;/*i=t)/*向后移动字符,腾出一个空间*/*(q+1)=*q;
39、/*先移动0符*/8.4指针的应用【例8-3】插入字符串。把字符串good插入字符串luck之前。其原理是通过指针移动、对指针取元素值等移动相应位置的元素,腾出内存单元,再在这个内存单元中插入字符。#include#include void f(char ch,char*p)int i;char*q,*t=ch;for(i=0;istrlen(ch)/2;i+)t+;/*i=t)/*向后移动字符,腾出一个空间*/*(q+1)=*q;/*先移动0符*/8.4指针的应用q-;/*指针前移一个,上面又移动一个字符,当q=t时,q-到了a6处,以此类推*/q+;/*q重到a7处,以此类推*/*q=*p
40、;/*在a7处放入1个字符,以此类推*/t+;/*数组ch下移1个位置到ch8,仍然是l处,以此类推*/p+;/*串good下移1个位置到o处,以此类推*/printf(%s,ch);int main()char ch20=Its a luck day;char*p=good;f(ch,p);8.4指针的应用【例8-4】统计母串中的子串。输入一个母串,再输入一个子串,统计出母串中有多少个这样的子串。#include int isfun(char a*a,char b*b)while(*a=*b&*a&*b)/*母串元素内容和子串元素内容相等且母、子串未到0*/a+;b+;/*地址同步右移*/i
41、f(*b=0)return 1;/*如果子串能移动到0处,说明找到了一个和子串相同的串,返回1*/return 0;/*找不到返回0*/int numfun(char a,char b)char*p=a;/*指针p指向母串*/int num=0;/*用于计数*/while(*p)/*母串外循环*/8.4指针的应用if(isfun(p,b))/*调用isfun()函数,实参为母串指针和子串数组名b,转入上面函数中。如果isfun()函数返回1,num就自增1,母串指针右移。这里的母串指针仅在调用isfun()时定位isfun()函数里的母串与子串的比较起始位置*/num+;p+;return n
42、um;int main()char a100,b5;printf(Input mother string:n);gets(a);printf(Input son string:n);gets(b);printf(%d,numfun(a,b);例如:Input mother string:Jack likes going hiking Tom likes going seiming I like readingInput son string:like38.4指针的应用【例8-5】数组指针形式冒泡法排序。#include void f(int*p,int n)int t,*i,*j,*m;m=p
43、+n-1;/*确定指针位置于最后一个元素*/for(i=p;ip+n-1;i+,m-)for(j=p;jm;j+)/*指针位移,对指针进行取值比较*/if(*j*(j+1)t=*j;*j=*(j+1);*(j+1)=t;int main()int x10=8,1,3,2,9,4,12,6,24,16,*p=x;f(x,10);for(p=x;px+10;p+)printf(%d,*p);8.4指针的应用【例8-6】删除字符串中多余的空格。设有字符串thisis abook,要删除该字符串多余的空格,删除后字符串显示正常为this is a book。程序如下:#include#include void fun(char*a)char*p,*q;p=a;while(*p&*p=)p+;/*清除串开头的空格,开头没有空格则此循环无用*/p=strcpy(a,p);/*p重新指向清除开头空格后的串*/while(*p)8.4指针的应用while(*p&*p!=)p+;/*p指向了找到的第1个空格处*/q=p+1;/*用q从空格后的那个字符开始*/while(*p&*p=)p+;/*若有空格,继续清除*/p=strcpy(q,p);/*p重新指向清除了空格后的新串,继续外循环进行下一次清除*/LOGO