版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结1指针:地址数据我们首先的观念就是简单地把地址作为数据,可以把地址存储在内存中。
intx;10002
x=2;1004 1020
1000由于地址作为数据对待,他们也可以存储在内存中。2一个变量的指针当一个变量存储另一个变量的地址时,那我们说它就是那个变量的指针。在内存表中,我们经常用箭头来表示指针,x的真实地址和我们 理解的概念不 相关。我们经常用任意地址描述指针,同时在以后经常 会放弃它。intx;10002x=2;1004 1020 1000我们把1000作为整数2的指针3指针变量的声明如何定义一个变量为指针变量?
类型标识符*指针变量;如:int*intp;double*doublep; char*chPtr;多个指针变量需要分别加*:double*doublep,*doubleq;5关于指针的几个问题回答这些问题可以使我们更好地理解指针。
intx,*px;
x=2; 1000x21004问题:1、如何把x的地址置入px中?2、如何用px处理和改变x?
1020px6问题1:指针赋值我们不能用简单的常数作为地址对指针进行赋值。我们永远不知道当我们编写程序时,变量地址的值将是什么?
intx,*px;
1000
x=2;21004问题:1、如何把x的地址置入px中? 我们不能用这样表示:1020
px
px=1000;
7地址运算符提供运算符返回操作数的地址,我们用&来表示。
intx,*px;1000
x=2;21004我们想要做的:
px=x的地址
1020我们应该表示为: px
px=&x9处理内存地址使用变量的指针就是为了用这个指针得到变量的值并改变它。 intx,*px;10002 x=2;1004 px=&x;2、我们怎样用px得到x的值并改变它? 1020 px
10问题2:处理内存地址如何用指针变量处理和改变它所指向的单元的值?用引用运算符“*”解决。如*intp表示的是intp指向的这个单元的内容。在对intp使用引用运算之前,必须先对intp赋值11指针处理我们可以认为一个指针是另一个变量的参考,当我们处理这个变量时,我们叫这个运算符为“参考运算符”,这个操作为“参考指针”
intx,*px,y; 1000 x2 x=2; 10042 px=&x; y y=*px;
1020px*为引用运算符
13指针的基本类型为什么指针要指向一定类型的数据?地址对于编译器来说不足以解析地址的数据类型。由于指针的基本数据类型可以对指针表达式进行错误检查,比如,分配一 个整型数据指 针,或者反之 将产生一个警 告。
intx,*px,y; 1000 x2 x=2; 1004 px=&x; y2 y=*px;
1020指针必须要有一个明确的数据类型px1000以便编译器可以解析数据的指向类型 14指针实例如有:intX,*intp,Y;X=3;Y=4;intp=&X;1000intp10044Y10003X如执行:*intp=Y+4;1000intp10044Y10008X注意:不能用intp=100;因为我们永远不知道变量存储的真实地址,而且程序每次运行可能都不同。运行Fig.8.4观察aPtr值的变化15指针变量的使用练习设有定义intx,y;int*p1,*p2;1000x1004y1008p11012p2执行语句:x=23;y=234;100023x1004234y1008p11012p2执行语句:p1=&x;p2=&y;100023x1004234y10081000p110121004p2执行语句:*p1=34;*p2=17;100034x100417y10081000p110121004p217指针实例有以下结构
Ap1aBp2b比较执行p1=p2和*p1=*p2后的不同结果。
解:
Ap1aBp2bBp1aBp2b18指针的初始化指针在使用前必须初始化。仅和别的变量一样定义指针,不初始化是一个比较普遍的错误。没有初始化的指针可能指向任意地址,对这些指针作操作可能会导致程序错误。NULL是一个特殊指针值,称为空指针。它的值为0。它可被用来初始化一个指针,表示不指向任何地址。19第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结21传参数到函数的方法C++有三种传递参数到函数的方法:按值传递,用引用参数按引用传递用指针参数按引用传递按值传递:在函数内部对形式参数的任何改变都不会影响实际参数的值。voidsa,intb){intc;c=a;a=b;b=c;}
如果调用swap(x,y);并不能真正交换x和y的值!!!22引用调用但在某些应用中确实需要改变实际参数的值。例如,我们经常需要修改两个变量的值,希望有个函数可以实现此功能。要解决此问题可以采用指针作为参数。23指针作为函数参数voids*a,int*b){intc,d;c=*a;*a=*b;*b=c;a=&c;b=&d}
s,&y)34xyabcd这里,通过传指针仍然交换了x,y的值,交换后a,b又分别获得了局部变量c,d的地址.所以函数本质上还是传值,是将地址值传给了a,b变量.调用:25引用传递步骤把函数参数声明为指针在函数体内使用间接访问指针当调用函数时,把地址作为参数传递26SolveQuadratic的调用intmain(void){doublea,b,c,x1,x2;intresult;cout<<“inputa,b,c:\n”;cin<<a<<b<<c;result=SolveQuadratic(a,b,c,&x1,&x2);if(result)cout<<“error”;elsecout<<“x1=“<<x1<<x2=“<<x2;}29const修饰指针指针是如此的奇妙,通过传递指针值,函数获得了对外界变量空间的访问权限,尤其为其创造了修改空间中数据的机会.如何通过指针只能做读取,而不能写入?用const修饰加const的时机:遵循最小特权原则,对于函数的参数,在能满足函数处理数据的要求的前提下,给予它最小的权限30const修饰参数的四种方式(1)指向非常量的非常量指针调用:intx;f(&x)voidf(int*ptr){ 可以通过引用改变x的值;//*ptr=3;可以改变ptr本身的值;//ptr++;};
此时,x是变量,ptr也是变量31指向常量数据的非常量指针调用:intx;f(&x)voidf(constint*ptr){ 不可以通过引用改变x的值;//*ptr=3;可以改变ptr本身的值;//ptr++;};
此时,x是变量,ptr也是变量,但不可以通过对ptr的引用运算而修改x的值const修饰参数的四种方式(2)32指向非常量的常量指针调用:intx;f(&x)voidf(int*constptr){ 可以通过引用改变x的值;//*ptr=3;不可以改变ptr本身的值;//ptr++;};
此时,ptr是常量,x的值也不可以通过ptr的引用方式来改动const修饰参数的四种方式(3)33指向常量的常量指针调用:intx;f(&x)voidf(constint*constptr){ 不可以通过引用改变x的值;//*ptr=3;不可以改变ptr本身的值;//ptr++;};
此时,ptr是变量,ptr所指的空间中的值也不能通过它来改变const修饰参数的四种方式(4)34sizeofsizeof(类型名)返回该数据类型单个元素所占的字节数sizeof数组名返回该数组所占的字节数intarray[10];cout<<sizeofarray<<endl;voidf(int*p,intlen){cout<<sizeofp<<endl;}调用f(array,10);返回10*4即40输出4,即一个指针变量占据的空间,而非数组array占据的空间35指针小结intx,y,*p; 定义一个整型指针。如定义多个指针变量,则在每个变量前都要加*p=&x;把变量的地址赋给指针*p=2;改变指针指向的地址的值y=*p;指针指向的地址中的值赋给一个变量S);传递地址参数voidS*p1,int*p2)定义指针作为形式参数36第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结37数组与指针在C++中,数组与指针是密切相关的,两者几乎可以交换使用.数组名代表数组的起始地址,因此一个数组名就是一个常量指针.数组与指针相同之处在访问内存方面的操作方式几乎相同数组与指针不同之处1、系统内存空间分配不同2、数组名是常量指针,不能修改它的值。38指针的运算constintN=5;inta[N]={1,2,3,4,5};假设300是a的基地址int*p;12345ap+i本质是p+4*i3、*(a+2)?2、++p;1、p=a;p=300p=300+4*1339数组与指针——相同之处constintN=5;inta[N],*p;假设300是a的基地址如下操作是允许的:p=&a[0];
此时p=300等价于p=&a[1];此时p=304;p=a;p=a+1;
40数组与指针——相同之处constintN=5;inta[N],*p;假设300是a的基地址对数组求和的三种方式:方法1:sum=0;for(p=a;p<&a[N];++p)sum+=p;方法2:sum=0;for(i=0;i<N;++i)sum+=*(a+i);方法3:p=a;sum=0;for(i=0;i<N;++i)sum+=
p[i];41数组与指针——不同之处系统内存空间分配不同constintN=5;inta[N],*p;假设300是a的基地址300304308312316a[0]a[1]a[2]a[3]a[4]ap42constintN=5;inta[N],*p;假设300是a的基地址以下操作是不允许的:a=p;a++;a+=3;a是常量指针,不能修改它的值。运行并分析Fig.8.20,Fig.8.21数组与指针——不同之处43指针数组数组是同种数据类型数据的集合,该类型当然也可以是指针.指针数组:数组的每个元素都是指针如:char*a[4];charch1,ch2,ch3,ch4
a[0]=&ch1;a[1]=&ch2;a[2]=&che3;a[3]=&ch4;44指针数组实际应用中,常见的做法是字符串数组:constchar*suit[4]={“Hearts”,“Diamonds”,“Clubs”,“Spades”}
字符串数组中的每一项都是一个字符串,实际指向相应字符串的第一个字符的指针(地址)
45第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结46函数指针指向函数的指针:
指针指向内存中函数代码存放的起始地址函数指针和其它指针一样也可以传递给函数、从函数中返回、赋给其他的函数指针、存储在数组中。函数指针的声明:如bool(*compare)(int,int)类型名(*指针变量名)(形式参数列表)47函数指针通过函数指针调用函数:如(*compare)(3+5,x)其中x是int类型(*指针变量名)(实际参数列表)函数指针常用在菜单驱动的系统中,将不同的菜单功能设计成不同的函数来实现,之后根据用户输入的不同通过函数指针调用不同的函数.48例:Fig08.29//Fig.8.29:fig08_29.cpp//Demonstratinganarrayofpointerstofunctions.#include<iostream>usingstd::cout;usingstd::cin;usingstd::endl;//functionprototypes--eachfunctionperformssimilaractionsvoidfunction0(int);voidfunction1(int);voidfunction2(int);49例:Fig08.29intmain(){void(*f[3])(int)={function0,function1,function2};intchoice;cout<<"Enteranumberbetween0and2,3toend:";cin>>choice;声明函数指针数组50例:Fig08.29
while((choice>=0)&&(choice<3))
{(*f[choice])(choice);cout<<"Enteranumberbetween0and2,3toend:";cin>>choice;}cout<<"Programexecutioncompleted."<<endl;return0;}通过函数指针调用不同函数51例:Fig08.29voidfunction0(inta){cout<<"Youentered"<<a<<"sofunction0wascalled\n\n";}voidfunction1(intb){cout<<"Youentered"<<b<<"sofunction1wascalled\n\n";}voidfunction2(intc){cout<<"Youentered"<<c<<"sofunction2wascalled\n\n";}52第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结53串的定义字符串:是可以被当作一个单元来处理的一系列字符从存储方式上看:第一种解释:特殊的一维字符数组charstr[size];
第二种解释:指向字符的指针char*cptr;即:通过指向字符串第一个字符的指针来访问该字符串.一个字符串的值就是它的第一个字符的地址54串的结束符‘\0’
inta[3]={1,2,3}chars[3]={‘a’,’b’,’\0’}s的实际长度为2,但必须分配2+1个空间,多余一个空间用来存放’\0’
串是以’\0’为结束符的一维字符数组55复习字符串(第7章内容)空字符串:没有任何字符,只有’\0’‘a’与”a”的区别
串的初始化方法:1:chars[4]={‘a’,’b’,’c’,’\0’};2:chars[]={‘a’,’b’,’c’,’\0’};3:chars[]=“abc”;4:constchar*p=“abc”;首先在内存中为“abc”分配空间并将值写入,最后将该空间的起始地址赋给指针变量P56字符串的读入两种方式:用cin对象通过流提取读入一个字符串到一个字符数组中。读入时见到空白字符或文件结束符结束charword[10];cin>>word;通过cin调用函数getline读入一个字符串到一个字符数组中。读入时见到一个换行符号结束,结果串中不含换行符。charline[80];cin.getline(line,80);57字符串处理库中的字符串操作函数#include<cstring>提供了字符串操作、比较、查找、计算长度等函数char*strcpy(char*s1,constchar*s2)把s2复制到s1,直到遇到s2中的’\0’。s1要保证足够空间。函数返回s1的值char*strncpy(char*s1,constchar*s2,size_tn)把s2复制到s1,且最多复制n个字符。s1要保证足够空间。函数返回的是s1的值char*strcat(char*s1,contstchar*s2)把s1与s2拼接起来,结果存放到s1中。程序员必须保证s1有足够的空间容纳拼接结果。函数返回的是串s1。58intstrcmp(constchar*s1,constchar*s2)按照字典次序比较s1和s2,s1<s2结果<0;s1=s2=0;s1>s2>0char*strcpy(char*s1,constchar*s2)把s2复制到s1,直到遇到s2中的’\0’。s1要保证足够空间。函数返回的是s1size_tstrlen(constchar*s)函数返回’\0’前的字符个数字符串处理库中的字符串操作函数59Fig08-32#include<iostream>usingstd::cout;usingstd::endl;#include<cstring>//prototypesforstrcatandstrncatusingstd::strcat;usingstd::strncat;intmain(){60chars1[20]="Happy";//length6chars2[]="NewYear";//length9chars3[40]="";cout<<"s1="<<s1<<"\ns2="<<s2;
strcat(s1,s2);//concatenates2tos1(length15)cout<<"\n\nAfterstrcat(s1,s2):\ns1="<<s1<<"\ns2="<<s2;//concatenatefirst6charactersofs1tos3
strncat(s3,s1,6);//places'\0'afterlastcharacter61
cout<<"\n\nAfterstrncat(s3,s1,6):\ns1="<<s1<<"\ns3="<<s3;
strcat(s3,s1);//concatenates1tos3cout<<"\n\nAfterstrcat(s3,s1):\ns1="<<s1<<"\ns3="<<s3<<endl;return0;}62Fig08-34
strtok把字符分解为一个个记号#include<iostream>usingstd::cout;usingstd::endl;#include<cstring>//prototypeforstrtokusingstd::strtok;intmain(){63charsentence[]="Thisisasentencewith7tokens";char*tokenPtr;cout<<"Thestringtobetokenizedis:\n"<<sentence<<"\n\nThetokensare:\n\n";//begintokenizationofsentence
tokenP
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论