C++课件:第10章 指针.ppt_第1页
C++课件:第10章 指针.ppt_第2页
C++课件:第10章 指针.ppt_第3页
C++课件:第10章 指针.ppt_第4页
C++课件:第10章 指针.ppt_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第10章 指针,主要内容: (1)指针和地址 (2)指针常量和指针变量 (3)指针与数组的结合应用 (4)指针与函数的结合应用 (5)指针数组与指向指针的指针变量 重点: 指针变量的定义与引用 通过指针访问数组元素 指针变量作为函数参数 返回指针值的函数,10. 1 指针和指针变量,例10.1:数据的直接访问与间接访问: main() a p int a, *p; FFD6H scanf(%d, /*输出变量p的值,即a的地址*/ 指针:就是地址,变量的指针即指向该变量的地址。 指针变量:存放内存(变量、数组、函数等)地址的变量。,指针变量,例10.2 交换两个指针变量所指向的变量的值。 ma

2、in() int a=10,b=20,t; int *p1,*p2; /*定义指向整型的指针变量p1,p2*/ p1= 图示其执行过程: 见下页,本例中指针变量的作用: 通过指针变量访问该指针变量指向的单元,指针变量的值不变。,指针变量的定义的一般格式为: 类型标识符 *指针变量名 例如: int *p; float *q; 指针变量的引用: 必须先定义,后使用 指针变量定义后,可以对其进行如下操作: 赋值、引用指针变量的值、访问指针变量指向的变量等。如上例中通过p1、p2访问变量a、b对应的单元,其中 p1表示指针变量, *p1表示p1指向的变量(即变量a), t=a; a=b; b=t;

3、main() int x=5,y=6; swap(x,y); printf(nx=%d,y=%d,x,y); 结果:x=5,y=6 程序并未实现交换x、y的值, why? 因为参数传递是单向的,对形参的改变不影响实参的值。,指针变量作函数参数,解决以上问题的方法是: 指向变量的指针变量作函数形参,接收主调函数中实参变量的地址,实现传地址调用。 即在被调函数中通过指针变量访问(读取或修改)主调函数中对应的变量,当返回主调函数后,主调函数就得到了这些已修改过的变量的值。因此,“传地址”调用可以实现函数间多个数据的“双向传递”。,main() /*编写函数交换两个变量的值*/ int a,b; vo

4、id swap(int *p,int *q); printf(n input 2 integers:); scanf(%d%d, ,调用过程中参数的对应关系: Main: swap: a p b q *p a *q b 因此,在swap函数中通过指针变量p、q就可以访问main函数中的变量a、b了。由此可以实现函数之间的多个“数据传递”。, a: a0 a1 a5 After execute: pa=a; a0 a1 a5 a: pa pa+1 pa+2,例10. 5 分别用下标法和指针法访问一维数组。 程序(1):下标法 main() int a 5=1,2,3,5,7, i; for(i=

5、0; i5; i+) printf(%4d, ai); 程序(2):指针法 main() int a5=1,2,3,5,7, *p; for(p=a; pa+5; p+) printf(%5d, *p); ,程序(3):地址法(指针常量) main() int a5=1,2,3,5,7, i; for(i=0; i5; i+) printf(%5d,*(a+i); ,指针运算,除赋值、取地址 则解释以下表达式的含义: *p *(p+1) (*p)+ *(p+) p-q,例10.3利用指针求字符串的长度。 分析:设字符串用一维字符数组str保存。 算法: s1, 首先让指针变量p指向字符串的首地

6、址。 s2, 重复判断指针变量所指的字符(*p)是否等于字符串结束标志0:若不等,则指针p指向下一个字符。 S3, 两个指针相减(p-str)即字符串的长度。 其中,s2用循环结构实现。str 是数组名,代表数组的首地址,相当于指针常量。,例10.3 程序: str main() char str=you 运行结果:string_length: 8 P+的含义:p指向下一个数组元素。思考:p+=2呢? P-str的含义:p和str之间数据的个数(只有都指向同一数组时使用)。 程序中不能直接使用str+,因为str不是指针变量,而是指针常量。,y o u while(*srt!=0) n+; r

7、eturn n; main() char s80=sale apples.; int m; m=len(s); printf(n lenth:%6d, m); 分析参数传递过程:s = str,例10.6编写函数实现:将数组中的n个整数逆序存放。调用该函数实现将10个整数逆序存放。 main() int a10=1,2,4,6,8,9,7,5,3,10,i; int *p; void inv(int *q , int n); /*函数声明*/ printf(n before inverse:n); for(p=a; pa+10; p+) printf(“%5d”,*p); /*用指针访问数组元

8、素*/ inv(a , 10); printf( n after inverse:n); for(i=0;i10;i+) printf(“%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、调用函数inv()时,实参与形参的对应关系: 实参: a 10 形参:q n 结果:指针变量q接收数组a的首地址,即q指向数组a的第一个数组元素。因此,在函数inv()中通过指针变量i,j改变

9、的是数组a的元素。 函数inv()与下面的函数inver()功能等价: void inver(int b ,int n) int i, j, t; for(i=0, j=n-1; ij; i+, j-) t=bi; bi=bj; bj=t; return; 说明:形参数组名与指针变量等价。此处用b接收a的首地址,实现通过数组名b访问数组a. 指针法与下标法访问数组的区别:用指针速度快。,10.2.2 指针与二维数组,1、可以将二维数组看作一个一维数组进行访问: 通过指向数组元素的指针访问各元素。 例10.8 利用指针变量输出整型二维数组ss中的各元素。 main() int ss23=2,4,

10、6,8,10,12; int *p; printf(n); for(p=ss0;pss0+6;p+) /*p=ss0与p= ,说明:因为p是指向整型数据的指针变量,因此初值应为第一个数组元素的地址,p+使得p指向下一个数组元素。 图示: p,2 4 6 8 10 12,S00 S01 S02 S10 S11 S12,2、利用指向一维数组的指针变量访问二维数组。 例10.9 利用指向一维数组的指针变量p输出数组ss24中的各元素。 main() int ss24=2, 4, 6, 8, 10, 12, 14, 16 ; int (*p)4, j; printf(n); for(p=ss;pss+

11、2;p+) for(j=0;j4;j+) printf(%6d,*(*p)+j);/* equal to: (*p)j */ ,说明: p是指向一个包含有4个元素的一维数组的指针变量,因此, p+的含义是: 使 p 指向下一个一维数组,即移动4个元素的位置。(与例10.8中的p+比较)。 *(*p)+j)的含义:p所指向的一维数组中下标为j 的元素。 等价于 (*p)j,通过以上两例比较,可以看出两种指针变量的使用区别:指向数组元素的指针变量可以访问任意长度的数组,指向一维数组的指针变量只能访问固定长度的数组。 应用:当需用指针变量作为函数参数,编写处理任意二维数组的数据时,用方法1更合适。

12、例10.10 编写函数实现:求m*n矩阵中最大值元素的下标。并编写主函数调用之,在主函数中输出结果(较高要求的练习)。 分析: 设函数名为max,类型为void ,参数有5个,分别表示数组元素的首地址、行列数m,n、最大值元素的行列下标地址 r, c。 算法(略):,main() int ss43=1,12,3,14,5,16,7,8,9,2,13,4; int max_r,max_c; void max(); max(ss0,4,3,(p+i*n+j)表示数组元素ssij的地址 思考: 1、若用二维数组名作函数参数,是否能实现? 2、如何用函数实现:计算任意班级(n个人m门课)每门课的平均成

13、绩?,10.2.3 指针与字符串,字符串用字符数组来保存,可以通过数组名及下标访问,也可以通过字符指针访问。 例10.11:输入任意字符串,通过字符数组名和字符指针输出该字符串。 #include main() char string80, *str; gets(string); /*string is the address of string0*/ puts(string); str=string; /*str point to the character array */ puts(str); ,例10.12用字符数组与字符指针分别访问一字符串常量。 #include main() ch

14、ar string =you are really fine!, *str=thank you.; puts(string); puts(str); 运行结果: you are really fine! thank you.,分析: (字符数组名与字符指针变量的使用区别) *str=“thank you.”; 等价于 char *str ; str=thank you.; 而char string=“you are really fine!”; 不等价于 char string80 ; string= “you are really fine!”; 若定义: char s180,*s2; 则语

15、句: gets(s1); 是正确的 但语句:gets(s2); 不完全正确 ,因为s2未赋值就使用,这样可能使系统程序或其他数据区受到破坏,,字符指针变量作函数参数,等同于字符数组名作函数参数,实现传地址调用,便于多个函数之间的字符串的传递。 例10.14 用函数实现取子字符串:从字符串s1中第m个字符开始的全部字符复制到另一字符串。 #include main() char s180,s280; int n; void copy_str(char *p,char *q,int m); gets(s1); scanf(%d, ,void copy_str(char *p, char *q, i

16、nt m) p=p+m-1; while(*p!=0) *q=*p; p+;q+; *q = 0; 思考: 若用字符数组作函数参数,如何实现?分析参数传递的过程,有何区别? 结论:形参数组名相当于指针变量。,10.3 指针与函数,指针变量作函数参数: 如果形参是指针变量,实参可以是变量的地址、数组元素的地址(或数组名)、函数的首地址。 本节主要介绍:指向函数的指针的使用 返回值指针值的函数(主要用于处理多个字符串) 重点:编写返回指针的函数,指向函数的指针,函数的指针:即函数名,表示函数的首地址. 例10.15指向函数的指针变量的定义、引用 #include “math.h” main() d

17、ouble x,(*p)(),y; /*注意定义与引用中的*的区别*/ x=3.14/2; p=sin; y=(*p)(x); printf(n sin: %3.1f,y); p=cos; y=(*p)(x); printf(n cos: %3.1f,y); ,指向函数的指针变量的一般定义形式为: 类型标识符 (*指针变量名)( 参数类型 ); 例如: int (*da)( ); 定义指针变量 da,它指向一个返回int 型值的函数。 应用: 利用指向函数的指针变量编写通用函数(较高要求)。 例10.16编写函数:求任意函数f(x)在区间(a,b)上的定积分。 程序(略),返回指针值的函数,一

18、个函数的返回值可以是 int、float、double、character型等,也可以返回其他类型的值,比如指针类型。 例如: char *strcpy(char *a,char *b) char *strcat(char *s1, char *s2) char *strchr(char *s, char ch),例10.17 编写函数search():查找字符ch在字符串str中第一次出现的位置。在主函数中输入字符串、待查找的字符,输出查找结果。 分析:函数search()的类型为指向字符数据的指针类型,参数有两个:字符型的ch和指向字符的指针变量str. 算法:从str指向的字符串的首字符

19、开始,循环比较str指向的字符是否与字符ch相等。若相等,则结束循环,返回指向该字符的指针;否则,str指向下一个字符,直到字符串结束标志0为止,返回空指针(NULL),表示没找到。,#include “stdio.h” /*程序(例10.17):*/ main() char *search(char *str,char ch); char ss80,*p,chr; printf(n input a string;); gets(ss); printf(n input a char for search:); chr=getchar(); p=search(ss,chr); if(p=NULL

20、)printf(n not found.); else printf(n position:%d(count from 0),p-ss); char *search(char *str,char ch) /*注意:函数名前的* while(*str!=0) 表示该函数的返回值为指针*/ if(*str=ch) return(str); else str+; return(NULL); ,返回指针值的函数的一般定义格式: 类型标识符 *函数名(形参表) 与其他函数的不同:函数名前有*,表示指针类型。类型标识符说明该指针指向的数据的类型。 例10.18 编写两个字符串连接的函数,返回连接后的字符串

21、的首地址。 分析: 函数类型为返回指向字符型的指针,参数两个:均为字符数组或字符型指针变量。 首先找到字符串str1的末尾,然后将字符串str2的字符逐个送入str1,最后在str1的末尾加字符串结束标记0。,#include stdio.h char *my_strcat(char *str1, char *str2) char *p=str1; while(*p!=0) p+; /*find the end of str1*/ while(*str2!=0) *p+=*str2+; *p=0; return(str1); main() char s180=we are ,s2 =good

22、friends.,*p; puts(s1); puts(s2); p=my_strcat(s1,s2); puts(p); ,*p+=*str2+;”的功能是: 将str2指向的字符赋给p指向的单元(字符串str1中的指定位置),然后p和str均指向下一个字符。该语句等价于 *p=*str2; p+; str2+; 再比如:字符串复制。 char *strcopy( char *s , char *t) char *p=s; while( *t!=0) *s=*t; s+; t+; *s=0; return p; 上面红色的语句等价于 : while ( (*s+ = *t+)!=0) ;,1

23、0.4 指针数组和指向指针的指针,指针数组 指向指针的指针 命令行参数 要求:熟悉,10.4.1 指针数组,指针数组实际上是指向相同类型数据的指针变量的集合,每个数组元素相当于一个指针变量。 指针数组的应用: 1)用于访问由多个字符串组成的二维字符数组。优点是:节省内存、加快排序速度。 2)指针数组作main函数的形参。 例10.19用指针数组指向给定的5个字符串,然后逐个输出。 分析:5个字符串的首地址分别存放于指针数组的一个元素中;因为要处理给定的字符串,所以在程序中直接给出,而不是用户输入。 程序:l10_4_1.c(下页),#include /*L10_4_1.c:*/ main()

24、char *str =basic,turbo c, fortran, vc+, java; int i; for(i=0;i5;i+) puts(stri); 程序中指针数组的初始化等价于: char *str5 ,string 10= basic,turbo c, fortran,vc+,java; for(i=0,i5;i+) stri=stringi; 图示二者区别:用指针数组更节省内存。 注意:指针数组与指向数组的指针变量的区别。 区分 char *str5; 与 char (*p)5;,例10.20 用指针数组实现字符串排序。(速度更快) 分析:一初始化方式存入5个名字,排序,输出。

25、 其中,10个名字用字符型指针数组保存,每个元素保存一个名字的首地址。 排序时,只交换指向字符串的指针,而不需交换两个字符串,输出时,按指针数组的元素顺序即是排序后的字符串的顺序。,#include main() void sort(),prn(); char *str =basic, turbo c, fortran, vc+, java; sort(str,5); prn(str,5); void sort(char *v, int m) /*用选择法排序*/ int i, j, k; char *t; for(i=0; i0) k=j; if(k!=i) t=vk; vk=vi; vi=

26、t; /*交换*/ ,void prn(char *v , int m) int i; for(i=0; im; i+) puts(vi); 运行结果: basic fortran java turbo c vc+,例10.4.3 指针数组作main函数的参数,实现向程序传送命令行参数。(如编程实现文件复制:copy file1name file2name CR ,详见文件一章) 下面程序(l10_4_3.c)实现:输出命令行参数。 main(int argc,char *argv ) int j; for(j=1;jargc;j+) printf(“n%s”,argvj); 运行时输入:l10_4_3 f1.dat f2.dat 则输出:f1.dat f2.dat,命令行: l10_4_3 f1.dat f2.dat argv,l10_4_30,f1.dat0,f2.dat0,下面程序与上例等价:main(int

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论