C++课件:第10章 指针.ppt
第10章 指针主要内容:主要内容:主要内容:主要内容:(1 1)指针和地址)指针和地址(2 2)指针常量和指针变量)指针常量和指针变量(3 3)指针与数组的结合应用)指针与数组的结合应用(4 4)指针与函数的结合应用)指针与函数的结合应用(5 5)指针数组与指向指针的指针变量)指针数组与指向指针的指针变量重点:重点:重点:重点:指针变量的定义与引用指针变量的定义与引用通过指针访问数组元素通过指针访问数组元素指针变量作为函数参数指针变量作为函数参数返回指针值的函数返回指针值的函数10.1 指针和指针变量指针和指针变量 n n例例10.110.1:数据的:数据的直接访问直接访问直接访问直接访问与与间接访问间接访问间接访问间接访问:main()a pmain()a p int int a,*p;FFD6H a,*p;FFD6H scanfscanf(%d,&a);(%d,&a);p=&a;p=&a;/*/*变量变量p p保存保存a a的地址的地址*/*/printfprintf(“n a=%d”,a);(“n a=%d”,a);/*/*通过变量名访问单元:通过变量名访问单元:FFD6H*/FFD6H*/printfprintf(“n*p:%d”,*p);(“n*p:%d”,*p);/*/*通过指针变量通过指针变量P P访问单元访问单元:ffd6h*/ffd6h*/printfprintf(“n p:%xn”,p);(“n p:%xn”,p);/*/*输出变量输出变量p p的值,即的值,即a a的地址的地址*/指针指针:就是就是地址地址,变量的指针即指向该变量的地址。,变量的指针即指向该变量的地址。指针变量:指针变量:存放存放内存内存(变量、数组、函数等)地址的变量(变量、数组、函数等)地址的变量。25FFD6H指针变量指针变量n n例例10.2 10.2 交换两个指针变量所指向的变量的值。交换两个指针变量所指向的变量的值。main()main()int int a=10,b=20,t;a=10,b=20,t;intint*p1,*p2*p1,*p2;/*;/*定义指向整型的指针变量定义指向整型的指针变量定义指向整型的指针变量定义指向整型的指针变量p1,p2*/p1,p2*/p1=&a;p2=&b;/*p1=&a;p2=&b;/*使使使使p1 p1 指向指向指向指向 a,p2 a,p2 指向指向指向指向 b*/b*/printfprintf(n before exchange:a=%d,b=%d,a,b);(n before exchange:a=%d,b=%d,a,b);t=*p1;*p1=*p2;*p2=t;t=*p1;*p1=*p2;*p2=t;/*/*交换交换交换交换p1,p2p1,p2指向的变量的值指向的变量的值指向的变量的值指向的变量的值*/*/printfprintf(n after exchange:a=%d,b=%d,a,b);(n after exchange:a=%d,b=%d,a,b);printf printf(n*p1:%d,*p2:%d,*p1,*p2);(n*p1:%d,*p2:%d,*p1,*p2);图示其执行过程:图示其执行过程:图示其执行过程:图示其执行过程:见下页见下页见下页见下页本例中指针变量的作用:通过指针变量访问该指针变量指向的单元,指针变量的值不变。n n指针变量的定义的一般格式为:指针变量的定义的一般格式为:指针变量的定义的一般格式为:指针变量的定义的一般格式为:类型标识符类型标识符类型标识符类型标识符 *指针变量名指针变量名指针变量名指针变量名 n n例如例如:intint*p;*p;float*q;float*q;n n指针变量的引用:指针变量的引用:指针变量的引用:指针变量的引用:必须先定义,后使用必须先定义,后使用必须先定义,后使用必须先定义,后使用指针变量定义后,可以对其进行如下操作:指针变量定义后,可以对其进行如下操作:赋值、引用指针变量的值、访问指针变量指向的变量赋值、引用指针变量的值、访问指针变量指向的变量赋值、引用指针变量的值、访问指针变量指向的变量赋值、引用指针变量的值、访问指针变量指向的变量等。等。等。等。如上例中通过如上例中通过如上例中通过如上例中通过p1p1、p2p2访问变量访问变量访问变量访问变量a a、b b对应的单元,其中对应的单元,其中对应的单元,其中对应的单元,其中p1p1表示指针变量,表示指针变量,表示指针变量,表示指针变量,*p1p1表示表示表示表示p1p1指向的变量(即变量指向的变量(即变量指向的变量(即变量指向的变量(即变量a a),),),),&p1&p1表示指针变量表示指针变量表示指针变量表示指针变量p1p1所在单元的地址所在单元的地址所在单元的地址所在单元的地址。回顾例回顾例10.210.2:通过指针变量:通过指针变量p1p1,p2p2交换了变量交换了变量a a和和b b的值。的值。那么,为什么要用指针变量而不直接用变量名呢?那么,为什么要用指针变量而不直接用变量名呢?再回顾函数一章的例再回顾函数一章的例8.48.4:编写函数:编写函数swap()swap()交换两个变量的值,交换两个变量的值,函数如下:函数如下:viod viod swap(swap(int int a,a,int int b)b)int int t;t=a;a=b;b=t;t;t=a;a=b;b=t;main()main()int int x=5,y=6;x=5,y=6;swap(x,y);swap(x,y);printfprintf(nxnx=%d,y=%d,x,y);=%d,y=%d,x,y);结果结果:x=5,y=6 x=5,y=6 程序并未实现交换程序并未实现交换x x、y y的值的值,why?why?因为因为参数传递是单向的,对形参的改变不影响实参的值。参数传递是单向的,对形参的改变不影响实参的值。指针变量作函数参数指针变量作函数参数解决以上问题的方法是:解决以上问题的方法是:指向变量的指针变量作函数形参,接收主调函数指向变量的指针变量作函数形参,接收主调函数指向变量的指针变量作函数形参,接收主调函数指向变量的指针变量作函数形参,接收主调函数中实参变量的地址,实现传地址调用。中实参变量的地址,实现传地址调用。中实参变量的地址,实现传地址调用。中实参变量的地址,实现传地址调用。即在被调函数中通过指针变量访问(读取或修改)即在被调函数中通过指针变量访问(读取或修改)主调函数中对应的变量,当返回主调函数后,主调函数中对应的变量,当返回主调函数后,主调函数就得到了这些已修改过的变量的值。主调函数就得到了这些已修改过的变量的值。因此,因此,“传地址传地址”调用可以实现函数间多个数调用可以实现函数间多个数据的据的“双向传递双向传递”。main()/*main()/*编写函数交换两个变量的值编写函数交换两个变量的值编写函数交换两个变量的值编写函数交换两个变量的值*/*/intint a,b;a,b;void swap(void swap(intint*p,*p,intint*q)*q);printf printf(n input 2 integers:);(n input 2 integers:);scanf scanf(%d%d,&a,&b);(%d%d,&a,&b);printf printf(n before swap:a=%d,b=%d,a,b);(n before swap:a=%d,b=%d,a,b);swap(&a,&b);swap(&a,&b);printf printf(n after swap:a=%d,b=%d,a,b);(n after swap:a=%d,b=%d,a,b);void swap(void swap(intint*p,*p,intint*q)/*q)/*交换两个变量的值交换两个变量的值交换两个变量的值交换两个变量的值*/*/intint t;t;t=*p;*p=*q;*q=t;t=*p;*p=*q;*q=t;调用过程中参数的对应关系调用过程中参数的对应关系:Main:swap:a p b q *p a *q b 因此,在因此,在swapswap函数中通过指针变量函数中通过指针变量p p、q q就可以访问就可以访问mainmain函数中的变量函数中的变量a a、b b了。由此可以实现函数之间的多个了。由此可以实现函数之间的多个“数据传递数据传递”。&a&b10.2 指针与数组指针与数组n n 通过指针访问数组元素通过指针访问数组元素 10.2.1 指针与一维数组指针与一维数组int int a6,*pa,k;a6,*pa,k;a:a0 a1 a5 After execute:pa=a;a0 a1 a5 a:pa pa+1 pa+2例例例例10.10.5 5 分分别别用用下下标标法法和和指指针法访问一维数组。针法访问一维数组。程序(程序(1 1):下标法):下标法main()main()int int a 5=1,2,3,5,7,i;a 5=1,2,3,5,7,i;for(i=0;i5;i+)for(i=0;i5;i+)printf printf(%4d,ai);(%4d,ai);程序(程序(2 2):指针法):指针法main()main()intint a5=1,2,3,5,7,a5=1,2,3,5,7,*p;*p;for(p=a;pa+5;p+)for(p=a;pa+5;p+)printf printf(%5d,*p);(%5d,*p);程序(3):地址法(指针常量)main()int a5=1,2,3,5,7,i;for(i=0;is =str strn n例例10.610.6编写函数实现:将数组中的编写函数实现:将数组中的n n个整数逆序存放。个整数逆序存放。调用该函数实现将调用该函数实现将1010个整数逆序存放。个整数逆序存放。main()main()int int a10=1,2,4,6,8,9,7,5,3,10,i;a10=1,2,4,6,8,9,7,5,3,10,i;int int*p;*p;void inv(void inv(intint*q,*q,int int n);/*n);/*函数声明函数声明*/*/printfprintf(n before inverse:n);(n before inverse:n);for(p=a;pa+10;p+)for(p=a;pa+10;p+)printfprintf(“%5d”,*p);(“%5d”,*p);/*/*用指针访问数组元素用指针访问数组元素*/*/inv(a,10);inv(a,10);printfprintf(n after inverse:n);(n after inverse:n);for(i=0;i10;i+)for(i=0;i10;i+)printf printf(“%5d”,ai);(“%5d”,ai);/*/*用下标访问用下标访问*/*/void inv(int*q,int n)/*函数inv()实现逆序*/int*i,*j,t;for(i=q,j=q+n-1;ij;i+,j-)t=*i;*i=*j;*j=t;return;3 3、调用函数、调用函数inv()inv()时,实参与形参的对应关系:时,实参与形参的对应关系:实参:实参:实参:实参:a 10 a 10 形参:形参:形参:形参:q nq nn n结果:指针变量结果:指针变量q q接收数组接收数组a a的首地址,即的首地址,即q q指向数组指向数组a a的第一的第一个数组元素。因此,在函数个数组元素。因此,在函数inv()inv()中通过指针变量中通过指针变量i,ji,j改变的是改变的是数组数组a a的元素。的元素。n n函数函数inv()inv()与下面的函数与下面的函数inverinver()()功能等价:功能等价:void void inverinver(int int b ,b ,intint n)n)int int i,j,t;i,j,t;for(i=0,j=n-1;ij;i+,j-)for(i=0,j=n-1;ij;i+,j-)t=bi;bi=bj;bj=t;t=bi;bi=bj;bj=t;return;return;说明说明:形参数组名与指针变量等价形参数组名与指针变量等价形参数组名与指针变量等价形参数组名与指针变量等价。此处用。此处用b b接收接收a a的首地址,的首地址,实现通过数组名实现通过数组名b b访问数组访问数组a.a.指针法与下标法访问数组的区别指针法与下标法访问数组的区别:用指针速度快。用指针速度快。10.2.2 指针与二维数组指针与二维数组n n1 1、可以将二维数组看作一个一维数组进行访问可以将二维数组看作一个一维数组进行访问可以将二维数组看作一个一维数组进行访问可以将二维数组看作一个一维数组进行访问:通过指向数组元素的指针访问各元素通过指向数组元素的指针访问各元素通过指向数组元素的指针访问各元素通过指向数组元素的指针访问各元素。n n例例10.8 10.8 利用指针变量输出整型二维数组利用指针变量输出整型二维数组ssss中的各元素。中的各元素。main()main()int ss int ss23=2,4,6,8,10,12;23=2,4,6,8,10,12;int int*p;*p;printf printf(n);(n);for(for(p=p=ssss00;p;pssss0+6;p+)0+6;p+)/*p=/*p=ssss00与与与与p=&p=&ssss0000等价等价等价等价*/*/printfprintf(%6d,*p);(%6d,*p);说明:说明:因为p是指向整型数据的指针变量,因此初值应为第一个数组元素的地址第一个数组元素的地址,p+使得使得p指向指向下一个数组元素下一个数组元素。n n图示:p 24681012S00S01S02S10S11S122 2、利用指向一维数组的指针变量访问二维数组。利用指向一维数组的指针变量访问二维数组。利用指向一维数组的指针变量访问二维数组。利用指向一维数组的指针变量访问二维数组。例例例例10.9 10.9 利用指向一维数组的指针变量利用指向一维数组的指针变量利用指向一维数组的指针变量利用指向一维数组的指针变量p p输出数组输出数组输出数组输出数组ssss2424中的各元素。中的各元素。中的各元素。中的各元素。main()main()int ss int ss24=2,4,6,8,10,12,14,16;24=2,4,6,8,10,12,14,16;int int (*p)4(*p)4,j;,j;printf printf(n);(n);for(p=for(p=ssss;p;pssss+2;p+)+2;p+)for(j=0;j4;j+)for(j=0;j4;j+)printf printf(%6d,(%6d,*(*p)+j)*(*p)+j);/*equal to:);/*equal to:(*p)j(*p)j */*/说明:p是指向一个包含有是指向一个包含有4个元素的一维个元素的一维数组的指针变量,因此,数组的指针变量,因此,p+的含义是的含义是:使使 p 指向下一个一维数组指向下一个一维数组,即移动4个元素的位置。(与例10.8中的p+比较)。*(*p)+j)的含义的含义:p所指向的一维数组中所指向的一维数组中下标为下标为j 的元素。的元素。等价于等价于(*p)jn n通过以上两例比较,可以看出两种指针变量的使通过以上两例比较,可以看出两种指针变量的使用区别:用区别:指向数组元素的指针变量可以访问指向数组元素的指针变量可以访问任意任意任意任意长度长度长度长度的数组,指向一维数组的指针变量只能访问的数组,指向一维数组的指针变量只能访问固定长度固定长度固定长度固定长度的数组。的数组。n n应用应用:当需用指针变量作为函数参数,编写处理:当需用指针变量作为函数参数,编写处理任意二维数组的数据时,用方法任意二维数组的数据时,用方法1 1更合适。更合适。n n例例10.10 10.10 编写函数实现:求编写函数实现:求m*nm*n矩阵中最大值元素矩阵中最大值元素的下标。并编写主函数调用之,在主函数中输出的下标。并编写主函数调用之,在主函数中输出结果(结果(较高要求的练习较高要求的练习)。)。n n分析分析:设函数名为设函数名为maxmax,类型为类型为void,void,参数有参数有5 5个,个,分别表示数组元素的首地址、行列数分别表示数组元素的首地址、行列数m,nm,n、最大值最大值元素的行列下标地址元素的行列下标地址 r,cr,c。算法算法(略略):main()main()int ss int ss43=1,12,3,14,5,16,7,8,9,2,13,4;43=1,12,3,14,5,16,7,8,9,2,13,4;int int max_r,max_c;void max();max_r,max_c;void max();max(max(ssss0,4,3,&max_r,&max_c);0,4,3,&max_r,&max_c);printf printf(n max:%d,row:%d,(n max:%d,row:%d,columcolum:%d,:%d,ss ssmax_rmax_c,max_r,max_c);max_rmax_c,max_r,max_c);void max(void max(intint*p,*p,int int m,m,int int n,n,int int*r,*r,int int*c)*c)int int i,j,i,j,krkr,kckc;/*;/*krkr,kckc分别为最大值元素的行列下标分别为最大值元素的行列下标分别为最大值元素的行列下标分别为最大值元素的行列下标*/*/krkr=kckc=0;=0;for(i=0;im;i+)for(i=0;im;i+)for(j=0;jn;j+)for(j=0;j*(p+*(p+i*n+j)*(p+krkr*n+*n+kckc)krkr=i;=i;kckc=j;=j;*r=*r=krkr;*c=;*c=kckc;(p+i*n+j)表示数组元素表示数组元素ssij的地址的地址n n思考:思考:1 1、若用二维数组名作函数参数,是否能实现?、若用二维数组名作函数参数,是否能实现?2 2、如何用函数实现:计算任意班级(、如何用函数实现:计算任意班级(n n个人个人mm门门课)每门课的平均成绩?课)每门课的平均成绩?10.2.3 指针与字符串n n字符串用字符数组来保存,可以通过数组名及下标字符串用字符数组来保存,可以通过数组名及下标字符串用字符数组来保存,可以通过数组名及下标字符串用字符数组来保存,可以通过数组名及下标访问,也可以通过字符指针访问访问,也可以通过字符指针访问访问,也可以通过字符指针访问访问,也可以通过字符指针访问。n n例例例例10.1110.11:输入任意字符串,通过字符数组名和字符:输入任意字符串,通过字符数组名和字符:输入任意字符串,通过字符数组名和字符:输入任意字符串,通过字符数组名和字符指针输出该字符串。指针输出该字符串。指针输出该字符串。指针输出该字符串。#include include.hmain()main()char string80,*char string80,*strstr;gets(string);/*string is the address of string0*/gets(string);/*string is the address of string0*/puts(string);puts(string);str str=string;/*=string;/*strstr point to the character array point to the character array*/*/puts(puts(strstr););例例10.1210.12用字符数组与字符指针分别访问一字符用字符数组与字符指针分别访问一字符串常量。串常量。#include include.hmain()main()char string=you are really fine!,*char string=you are really fine!,*strstr=thank=thank you.;you.;puts(string);puts(string);puts(puts(strstr););运行结果运行结果:you are really fine!you are really fine!thank you.thank you.分析:分析:(字符数组名与字符指针变量的使用区别)(字符数组名与字符指针变量的使用区别)n n*strstr=“thank you.”;=“thank you.”;等价于等价于 char *char *str str ;strstr=thank you.;=thank you.;n n而而char string=“you are really fine!”;char string=“you are really fine!”;不等价于不等价于 char string80;string=“you are really fine!”;char string80;string=“you are really fine!”;n n若定义若定义若定义若定义:char s180,*s2;char s180,*s2;则语句则语句则语句则语句:gets(s1);gets(s1);是正确的是正确的是正确的是正确的 但语句但语句但语句但语句:gets(s2);gets(s2);不完全正确不完全正确不完全正确不完全正确 ,因为,因为s2s2未赋值就使用,这样可能使系统程未赋值就使用,这样可能使系统程序或其他数据区受到破坏,序或其他数据区受到破坏,n n字符指针变量作函数参数,等同于字符数组名作字符指针变量作函数参数,等同于字符数组名作字符指针变量作函数参数,等同于字符数组名作字符指针变量作函数参数,等同于字符数组名作函数参数,实现传地址调用,便于多个函数之间函数参数,实现传地址调用,便于多个函数之间函数参数,实现传地址调用,便于多个函数之间函数参数,实现传地址调用,便于多个函数之间的字符串的传递。的字符串的传递。的字符串的传递。的字符串的传递。例例例例10.14 10.14 用函数实现取子字符串:从字符串用函数实现取子字符串:从字符串用函数实现取子字符串:从字符串用函数实现取子字符串:从字符串s1s1中第中第中第中第mm个字符开始的全部字符复制到另一字符串。个字符开始的全部字符复制到另一字符串。个字符开始的全部字符复制到另一字符串。个字符开始的全部字符复制到另一字符串。#include include.hmain()main()char s180,s280;char s180,s280;int int n;n;void copy_ void copy_strstr(char*p,char*q,(char*p,char*q,intint m);m);gets(s1);gets(s1);scanf scanf(%d,&n);(%d,&n);copy_ copy_strstr(s1,s2,n);(s1,s2,n);puts(s2);puts(s2);void copy_void copy_strstr(char*p,char*q,(char*p,char*q,int int m)m)p=p+m-1;p=p+m-1;while(*p!=0)while(*p!=0)*q=*p;p+;q+;*q=*p;p+;q+;*q=0;*q=0;思考思考:若用字符数组作函数参数,如何实现?分析参数传递若用字符数组作函数参数,如何实现?分析参数传递的过程,有何区别?的过程,有何区别?结论:形参数组名相当于指针变量。结论:形参数组名相当于指针变量。10.3 指针与函数指针与函数n n指针变量作函数参数指针变量作函数参数:如果形参是指针变量,实参可以是变量的地址、数组如果形参是指针变量,实参可以是变量的地址、数组元素的地址(或数组名)、函数的首地址。元素的地址(或数组名)、函数的首地址。本节主要介绍:指向函数的指针的使用本节主要介绍:指向函数的指针的使用n n返回值指针值的函数返回值指针值的函数(主要用于处理多个字符串)(主要用于处理多个字符串)重点重点:编写返回指针的函数编写返回指针的函数指向函数的指针n n函数的指针:即函数名,表示函数的首地址函数的指针:即函数名,表示函数的首地址函数的指针:即函数名,表示函数的首地址函数的指针:即函数名,表示函数的首地址.例例例例10.1510.15指向函数的指针变量的定义、引用指向函数的指针变量的定义、引用指向函数的指针变量的定义、引用指向函数的指针变量的定义、引用#include“math.h”include“math.h”main()main()double x,double x,(*p)()(*p)(),y;/*,y;/*注意定义与引用中的注意定义与引用中的注意定义与引用中的注意定义与引用中的*的区别的区别的区别的区别*/*/x=3.14/2;x=3.14/2;p=sin;y=p=sin;y=(*p)(x);(*p)(x);printf printf(n sin:%3.1f,y);(n sin:%3.1f,y);p=p=coscos;y=;y=(*p)(x)(*p)(x);printfprintf(n(n cos cos:%3.1f,y);:%3.1f,y);n n指向函数的指针变量的一般定义形式为:指向函数的指针变量的一般定义形式为:n n 类型标识符类型标识符类型标识符类型标识符 (*(*指针变量名指针变量名指针变量名指针变量名)()(参数类型参数类型参数类型参数类型);例如例如:int int (*(*dada)();)();定义指针变量定义指针变量 dada,它指向一个返回它指向一个返回int int 型值的函数。型值的函数。应用:应用:利用指向函数的指针变量编写通用函数利用指向函数的指针变量编写通用函数(较高要求较高要求)。例例10.1610.16编写函数:求任意函数编写函数:求任意函数f(x)f(x)在区间在区间(a,b)a,b)上的定上的定积分。积分。程序(略)程序(略)返回指针值的函数n n一个函数的返回值可以是一个函数的返回值可以是 intint、floatfloat、doubledouble、charactercharacter型等,也可以返回其他类型的值,比如型等,也可以返回其他类型的值,比如指针类型。指针类型。n n例如例如:char *char *strcpystrcpy(char*a,char*b)(char*a,char*b)char*char*strcatstrcat(char*s1,char*s2)(char*s1,char*s2)char*char*strchrstrchr(char*s,char(char*s,char ch ch)例例10.17 10.17 编写函数编写函数search()search():查找字符查找字符chch在在字符串字符串strstr中第一次出现的位置。在主函数中第一次出现的位置。在主函数中输入字符串、待查找的字符,输出查找中输入字符串、待查找的字符,输出查找结果。结果。n n分析:函数分析:函数search()search()的类型为指向字符数的类型为指向字符数据的指针类型,参数有两个:字符型的据的指针类型,参数有两个:字符型的chch和指向字符的指针变量和指向字符的指针变量strstr.算法:算法:从从从从strstr指向的字符串的首字符开始,指向的字符串的首字符开始,指向的字符串的首字符开始,指向的字符串的首字符开始,循环比较循环比较循环比较循环比较strstr指向的字符是否与字符指向的字符是否与字符指向的字符是否与字符指向的字符是否与字符chch相相相相等。若相等,则结束循环,返回指向该字等。若相等,则结束循环,返回指向该字等。若相等,则结束循环,返回指向该字等。若相等,则结束循环,返回指向该字符的指针;否则,符的指针;否则,符的指针;否则,符的指针;否则,strstr指向下一个字符,指向下一个字符,指向下一个字符,指向下一个字符,直到字符串结束标志直到字符串结束标志直到字符串结束标志直到字符串结束标志00为止,返回空为止,返回空为止,返回空为止,返回空指针(指针(指针(指针(NULLNULL),),),),表示没找到。表示没找到。表示没找到。表示没找到。#include“include“stdiostdio.h”/*.h”/*程序程序程序程序(例例例例10.17):*/10.17):*/main()main()char*search(char*char*search(char*strstr,char,char ch ch);char);char ss ss80,*p,80,*p,chrchr;printf printf(n input a string;);gets(n input a string;);gets(ssss););printfprintf(n input a char for search:);(n input a char for search:);chr chr=getchargetchar();();p=search(p=search(ssss,chrchr););if(p=NULL)if(p=NULL)printfprintf(n not found.);(n not found.);else else printf printf(n position:%d(count from 0),p-(n position:%d(count from 0),p-ssss););char*search(char*char*search(char*strstr,char,char ch ch)/*/*注意:函数名前的注意:函数名前的注意:函数名前的注意:函数名前的*while(*while(*strstr!=0)!=0)表示该函数的返回值为指针表示该函数的返回值为指针表示该函数的返回值为指针表示该函数的返回值为指针*/*/if(*if(*strstr=chch)return()return(strstr););else else str str+;+;return(NULL);return(NULL);n n返回指针值的函数的一般定义格式返回指针值的函数的一般定义格式返回指针值的函数的一般定义格式返回指针值的函数的一般定义格式:类型标识符类型标识符类型标识符类型标识符 *函数名(形参表)函数名(形参表)函数名(形参表)函数名(形参表)与其他函数的不同:函数名前有与其他函数的不同:函数名前有与其他函数的不同:函数名前有与其他函数的不同:函数名前有*,表示指针类型。,表示指针类型。,表示指针类型。,表示指针类型。类型标识符说明该指针指向的数据的类型。类型标识符说明该指针指向的数据的类型。类型标识符说明该指针指向的数据的类型。类型标识符说明该指针指向的数据的类型。例例例例10.18 10.18 编写两个字符串连接的函数编写两个字符串连接的函数编写两个字符串连接的函数编写两个字符串连接的函数,返回连接后的字返回连接后的字返回连接后的字返回连接后的字符串的首地址。符串的首地址。符串的首地址。符串的首地址。分析分析分析分析:函数类型为返回指向字符型的指针,参数两个:均为函数类型为返回指向字符型的指针,参数两个:均为函数类型为返回指向字符型的指针,参数两个:均为函数类型为返回指向字符型的指针,参数两个:均为字符数组或字符型指针变量。字符数组或字符型指针变量。字符数组或字符型指针变量。字符数组或字符型指针变量。首先找到字符串首先找到字符串首先找到字符串首先找到字符串str1str1的末尾,然后将字符串的末尾,然后将字符串的末尾,然后将字符串的末尾,然后将字符串str2str2的字的字的字的字符逐个送入符逐个送入符逐个送入符逐个送入str1,str1,最后在最后在最后在最后在str1str1的末尾加字符串结束标的末尾加字符串结束标的末尾加字符串结束标的末尾加字符串结束标记记记记00。#include include stdiostdio.h.h char*my_char*my_strcatstrcat(char*str1,char*str2)(char*str1,char*str2)char*p=str1;char*p=str1;while(*p!=0)p+;/*find the end of str1*/while(*p!=0)p+;/*find the end of str1*/while(*str2!=0)while(*str2!=0)*p+=*str2+;*p+=*str2+;*p=0;*p=0;return(str1);return(str1);main()main()char s180=we are,s2=good friends.,*p;char s180=we are,s2=good friends.,*p;puts(s1);puts(s2);puts(s1);puts(s2);p=p=my_my_strcatstrcat(s1,s2);(s1,s2);puts(p);puts(p);n n*p+=*str2+;p+=*str2+;”的的功功能能是是:将将str2str2指指向向的的字字符符赋赋给给p p指指向向的的单单元元(字字符符串串str1str1中中的的指指定定位位置置),然然后后p p和和strstr均指向下一个字符。该语句等价于均指向下一个字符。该语句等价于 *p=*str2;p+;str2+;p=*str2;p+;str2+;n n再比如再比如:字符串复制。字符串复制。char *char *strcopystrcopy(char*s,char*t)(char*s,char*t)char *p=s;char *p=s;while(*t!=0)while(*t!=0)*s=*t;s+;t+;*s=*t;s+;t+;*s=0;*s=0;return p;return p;上面红色的语句等价于上面红色的语句等价于:while(while(*s+=*t+*s+=*t+)!=0);)!=0);10.4 指针数组和指向指针的指针指针数组和指向指针的指针n n指针数组 n n指向指针的指针n n命令行参数要求:熟悉10.4.1 指针数组指针数组n n指指指指针针针针数数数数组组组组实实实实际际际际上上上上是是是是指指指指向向向向相相相相同同同同类类类类型型型型数数数数据据据据的的的的指指指指针针针针变变变变量量量量的的的的集合,每个数组元素相当于一个指针变量。集合,每个数组元素相当于一个指针变量。集合,每个数组元素相当于一个指针变量。集合,每个数组元素相当于一个指针变量。n n指针数组的应用:指针数组的应用:1 1)用于访问由多个字符串组成的二维字符数组用于访问由多个字符串组成的二维字符数组。优点。优点是:节省内存、加快排序速度。是:节省内存、加快排序速度。2)2)指针数组作指针数组作mainmain函数的形参函数的形参。n n例例10.1910.19用指针数组指向给定的用指针数组指向给定的5 5个字符串,然后逐个个字符串,然后逐个输出。输出。分析:分析:5 5个字符串的首地址分别存放于指针数组的一个个字符串的首地址分别存放于指针数组的一个元素中;因为要处理给定的字符串,所以在程序中元素中;因为要处理给定的字符串,所以在程序中直接给出,而不是用户输入。直接给出,而不是用户输入。n n程序:程序:l10_4_1.cl10_4_1.c(下页)下页)#include include /*L10_4_1.c.h