【文档说明】C++大学教程指针和基本指针的字符串.课件.ppt,共(70)页,388.000 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-7129.html
以下为本文档部分文字说明:
《C++大学教程》2007.91第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结《C++大学教程》2007.92指针:地址数据我们首先的观念就是简单地把地址作为数据,可以
把地址存储在内存中。intx;10002x=2;100410201000由于地址作为数据对待,他们也可以存储在内存中。《C++大学教程》2007.93一个变量的指针当一个变量存储另一个变量的地址时,那我们说它就
是那个变量的指针。在内存表中,我们经常用箭头来表示指针,x的真实地址和我们理解的概念不相关。我们经常用任意地址描述指针,同时在以后经常会放弃它。intx;10002x=2;100410201000我们把1000作为整数2的
指针《C++大学教程》2007.94指针的概念指针就是把地址作为数据,把地址存储在内存中指针变量:存储地址的变量变量的指针:当一个变量存储另一个变量的地址时,那我们说它就是那个变量的指针100021000如在某一程序中定义了intx;X
=2;如系统给x分配的空间是1000号单元,则指向x的指针是另一个变量,该变量中存放的数据为1000《C++大学教程》2007.95指针变量的声明如何定义一个变量为指针变量?类型标识符*指针变量;如:int*intp;d
ouble*doublep;char*chPtr;多个指针变量需要分别加*:double*doublep,*doubleq;《C++大学教程》2007.96关于指针的几个问题回答这些问题可以使我们更好地理解指针。intx,*px;x=2;1000x21004问题:1、如何把x的地址置入px中
?2、如何用px处理和改变x?1020px《C++大学教程》2007.97问题1:指针赋值我们不能用简单的常数作为地址对指针进行赋值。我们永远不知道当我们编写程序时,变量地址的值将是什么?intx,*px;1000x=2;21004问题:1、如何把x的地
址置入px中?我们不能用这样表示:1020pxpx=1000;《C++大学教程》2007.98指针赋值如何把某一变量的地址置入一个指针变量中?用地址运算符“&”解决。如表达式“&x”返回的是变量x的地址。如:intp
=&x;&运算符后面不能跟常量或表达式。如&2是没有意义的,&(m*n+p)。也是没有意义的《C++大学教程》2007.99地址运算符提供运算符返回操作数的地址,我们用&来表示。intx,*px;1000x=2;21004我们想要做的:px=x的地址1020我们应该表示为:
pxpx=&x《C++大学教程》2007.910处理内存地址使用变量的指针就是为了用这个指针得到变量的值并改变它。intx,*px;10002x=2;1004px=&x;2、我们怎样用px得到x的值并改变它?10
20px《C++大学教程》2007.911问题2:处理内存地址如何用指针变量处理和改变它所指向的单元的值?用引用运算符“*”解决。如*intp表示的是intp指向的这个单元的内容。在对intp使用引用运算之前,必须先对intp赋值《C++大学教
程》2007.912引用运算符在定义中,*号是语法标记同时和类型结合在一起产生一个指针定义。在运算时,我们采用*号运算符,就象指针定义一样。但是*号是独立运算符,并和指针一起表示一个数值。intx,*px,y;1000x2x=2;1004px=&x;y2我们
想得到:y=px指向的值;1020px我们表示为:y=*px;《C++大学教程》2007.913指针处理我们可以认为一个指针是另一个变量的参考,当我们处理这个变量时,我们叫这个运算符为“参考运算符”,这个操作为“参考指针”intx,*px,y;1000x2x=2;10042px=&x
;yy=*px;1020px*为引用运算符《C++大学教程》2007.914指针的基本类型为什么指针要指向一定类型的数据?地址对于编译器来说不足以解析地址的数据类型。由于指针的基本数据类型可以对指针表达式进行错
误检查,比如,分配一个整型数据指针,或者反之将产生一个警告。intx,*px,y;1000x2x=2;1004px=&x;y2y=*px;1020指针必须要有一个明确的数据类型px1000以便编译器
可以解析数据的指向类型《C++大学教程》2007.915指针实例如有:intX,*intp,Y;X=3;Y=4;intp=&X;1000intp10044Y10003X如执行:*intp=Y+4;1000intp10044Y10008X注意:不能用intp=100;因为我
们永远不知道变量存储的真实地址,而且程序每次运行可能都不同。运行Fig.8.4观察aPtr值的变化《C++大学教程》2007.916指针的定义及使用指针变量可以指向不同的变量。如上例中intp指向x,我们可以通过对
intp的重新赋值改变指针的指向。如果想让intp指向y,只要执行intp=&y就可以了。这时,intp与x无任何关系。同类的指针变量之间可相互赋值,表示二个指针指向同一内存空间。空指针指针没有指向任何空间空指针用常量NULL表示,NULL
的值一般赋为0不能引用空指针指向的值《C++大学教程》2007.917指针变量的使用练习设有定义intx,y;int*p1,*p2;1000x1004y1008p11012p2执行语句:x=23;y=234;100023x1004234y1008p11012p2执行语句
:p1=&x;p2=&y;100023x1004234y10081000p110121004p2执行语句:*p1=34;*p2=17;100034x100417y10081000p110121004p2
《C++大学教程》2007.918指针实例有以下结构Ap1aBp2b比较执行p1=p2和*p1=*p2后的不同结果。解:Ap1aBp2bBp1aBp2b《C++大学教程》2007.919指针的初始化指针在使用前必须初始化。仅和别的变量一样定义指针,不初始化
是一个比较普遍的错误。没有初始化的指针可能指向任意地址,对这些指针作操作可能会导致程序错误。NULL是一个特殊指针值,称为空指针。它的值为0。它可被用来初始化一个指针,表示不指向任何地址。《C++大学教程》2007.920void指
针void指针:统配指针类型定义:void*指针变量名;作用:在标准C中,只有类型相同的指针之间能互相赋值,但任何类型的指针都能与统配指针互相赋值。主要用于动态内存分配。《C++大学教程》2007.921
第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结《C++大学教程》2007.922传参数到函数的方法C++有三种传递参数到函数的方法:按值传递,用引用参数按引用传递用指针参数按引用传递按值传递:在函数内部对形式参数的任何改变都不会
影响实际参数的值。voidswap(inta,intb){intc;c=a;a=b;b=c;}如果调用swap(x,y);并不能真正交换x和y的值!!!《C++大学教程》2007.923引用调用但在某些应用中确实需要改变实际参数的值。例如,我们经常需要修改两个变量的值,希望有
个函数可以实现此功能。要解决此问题可以采用指针作为参数。《C++大学教程》2007.924引用调用--指针作为函数参数voidswap(int*a,int*b){intc;c=*a;*a=*b;*b=c;}swap(&x,&y)34xyab用指针作为参数可以在函数中修改主调程序的变量值,即实现变
量传递。但必须小心使用!!!调用:《C++大学教程》2007.925指针作为函数参数voidswap(int*a,int*b){intc,d;c=*a;*a=*b;*b=c;a=&c;b=&d}swap(&x,&y)34xyabcd这里,通过传指针仍然交换了x,y的值
,交换后a,b又分别获得了局部变量c,d的地址.所以函数本质上还是传值,是将地址值传给了a,b变量.调用:《C++大学教程》2007.926引用传递步骤把函数参数声明为指针在函数体内使用间接访问指针当调用函数时,把地址作为参数传递《C++大
学教程》2007.927能解一元二次方程的函数目前为止我们了解到的函数只能有一个返回值,由return语句返回。一个一元二次方程有二个解,如何让此函数返回二个解。答案是采用指针作为函数的参数。函数原型可设计为:intSolveQuadratic(doublea,doubleb,doubl
ec,double*px1,double*px2)函数的调用SolveQuadratic(1.3,4.5,2.1,&x1,&x2)SolveQuadratic(a,b,c,&x1,&x2)《C++大学
教程》2007.928完整的函数intSolveQuadratic(doublea,doubleb,doublec,double*px1,double*px2){doubledisc,sqrtDisc;if(a==0)re
turn1;disc=b*b–4*a*c;if(disc<0)return1;sqrtDisc=sqrt(disc);*px1=(-b+sqrtDisc)/(2*a);*px2=(-b-sqrtDisc)/(2
*a);return0;}《C++大学教程》2007.929SolveQuadratic的调用intmain(void){doublea,b,c,x1,x2;intresult;cout<<“inputa,b,c:\n”;cin<<a<<b<<c;result=SolveQuad
ratic(a,b,c,&x1,&x2);if(result)cout<<“error”;elsecout<<“x1=“<<x1<<x2=“<<x2;}《C++大学教程》2007.930const修饰指针指针是如此的奇妙,通过传递指针值,函数获得了对外界变量空间的访问权限,尤其为其创造了修改
空间中数据的机会.如何通过指针只能做读取,而不能写入?用const修饰加const的时机:遵循最小特权原则,对于函数的参数,在能满足函数处理数据的要求的前提下,给予它最小的权限《C++大学教程》2007.931const修饰参数的四种
方式(1)指向非常量的非常量指针调用:intx;f(&x)voidf(int*ptr){可以通过引用改变x的值;//*ptr=3;可以改变ptr本身的值;//ptr++;};此时,x是变量,ptr也是变量《C++大学教程》
2007.932指向常量数据的非常量指针调用:intx;f(&x)voidf(constint*ptr){不可以通过引用改变x的值;//*ptr=3;可以改变ptr本身的值;//ptr++;};此时,x是变量,ptr也
是变量,但不可以通过对ptr的引用运算而修改x的值const修饰参数的四种方式(2)《C++大学教程》2007.933指向非常量的常量指针调用:intx;f(&x)voidf(int*constptr){可以通过引用改变x的值;//*pt
r=3;不可以改变ptr本身的值;//ptr++;};此时,ptr是常量,x的值也不可以通过ptr的引用方式来改动const修饰参数的四种方式(3)《C++大学教程》2007.934指向常量的常量指针调用:intx;f(&x)voidf(constint*
constptr){不可以通过引用改变x的值;//*ptr=3;不可以改变ptr本身的值;//ptr++;};此时,ptr是变量,ptr所指的空间中的值也不能通过它来改变const修饰参数的四种方式(4)《C++大学教程》
2007.935sizeofsizeof(类型名)返回该数据类型单个元素所占的字节数sizeof数组名返回该数组所占的字节数intarray[10];cout<<sizeofarray<<endl;voidf(
int*p,intlen){cout<<sizeofp<<endl;}调用f(array,10);返回10*4即40输出4,即一个指针变量占据的空间,而非数组array占据的空间《C++大学教程》2007.936指针小结intx,y,*p;定义一个整型指针。如定义多个指针变
量,则在每个变量前都要加*p=&x;把变量的地址赋给指针*p=2;改变指针指向的地址的值y=*p;指针指向的地址中的值赋给一个变量Swap(&x,&y);传递地址参数voidSwap(int*p1,int*p
2)定义指针作为形式参数《C++大学教程》2007.937第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结《C++大学教程》2007.938数组与指针在C++中,数组与指针是密切相关的,两者几乎可以交换使用
.数组名代表数组的起始地址,因此一个数组名就是一个常量指针.数组与指针相同之处在访问内存方面的操作方式几乎相同数组与指针不同之处1、系统内存空间分配不同2、数组名是常量指针,不能修改它的值。《C++大学教程》2007.9
39指针的运算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=30
0+4*13《C++大学教程》2007.940数组与指针——相同之处constintN=5;inta[N],*p;假设300是a的基地址如下操作是允许的:p=&a[0];此时p=300等价于p=&a[1];此时p=3
04;p=a;p=a+1;《C++大学教程》2007.941数组与指针——相同之处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];《C++大学教程》2007.942数组与指针——不同之处系统内存空间分配不同constin
tN=5;inta[N],*p;假设300是a的基地址300304308312316a[0]a[1]a[2]a[3]a[4]ap《C++大学教程》2007.943constintN=5;inta[N],*p;假设300是
a的基地址以下操作是不允许的:a=p;a++;a+=3;a是常量指针,不能修改它的值。运行并分析Fig.8.20,Fig.8.21数组与指针——不同之处《C++大学教程》2007.944指针数组数组是同种数据类型数据的集合,该类型当然也可以是指针.指针数
组:数组的每个元素都是指针如:char*a[4];charch1,ch2,ch3,ch4a[0]=&ch1;a[1]=&ch2;a[2]=&che3;a[3]=&ch4;《C++大学教程》2007.945指针数组实际应用中,常见的做法是字符串数组:constchar*suit[4]=
{“Hearts”,“Diamonds”,“Clubs”,“Spades”}字符串数组中的每一项都是一个字符串,实际指向相应字符串的第一个字符的指针(地址)《C++大学教程》2007.946第八章指针和基于指针的字符串指针引用调
用数组与指针函数指针基于指针的字符串总结《C++大学教程》2007.947函数指针指向函数的指针:指针指向内存中函数代码存放的起始地址函数指针和其它指针一样也可以传递给函数、从函数中返回、赋给其他的函数指针、存储在数组中。函数指针的声明:如bool(*co
mpare)(int,int)类型名(*指针变量名)(形式参数列表)《C++大学教程》2007.948函数指针通过函数指针调用函数:如(*compare)(3+5,x)其中x是int类型(*指针变量名)(实际参数列表)函数指针常用在菜单驱动的系统
中,将不同的菜单功能设计成不同的函数来实现,之后根据用户输入的不同通过函数指针调用不同的函数.《C++大学教程》2007.949例:Fig08.29//Fig.8.29:fig08_29.cpp//Demonstratinganarra
yofpointerstofunctions.#include<iostream>usingstd::cout;usingstd::cin;usingstd::endl;//functionprototypes--eachfunctionperformssimilaractio
nsvoidfunction0(int);voidfunction1(int);voidfunction2(int);《C++大学教程》2007.950例:Fig08.29intmain(){void(*f[3])(int)={function0,function1,function2};
intchoice;cout<<"Enteranumberbetween0and2,3toend:";cin>>choice;声明函数指针数组《C++大学教程》2007.951例:Fig08.29while(
(choice>=0)&&(choice<3)){(*f[choice])(choice);cout<<"Enteranumberbetween0and2,3toend:";cin>>choice;}co
ut<<"Programexecutioncompleted."<<endl;return0;}通过函数指针调用不同函数《C++大学教程》2007.952例:Fig08.29voidfunction0(inta){cout<<"Youentered"<<a<<"sofunct
ion0wascalled\n\n";}voidfunction1(intb){cout<<"Youentered"<<b<<"sofunction1wascalled\n\n";}voidfuncti
on2(intc){cout<<"Youentered"<<c<<"sofunction2wascalled\n\n";}《C++大学教程》2007.953第八章指针和基于指针的字符串指针引用调用数组与指针函数指针基于指针的字符串总结《C++大学教程》2007
.954串的定义字符串:是可以被当作一个单元来处理的一系列字符从存储方式上看:第一种解释:特殊的一维字符数组charstr[size];第二种解释:指向字符的指针char*cptr;即:通过指向字符串第一个字符的指针来访问该
字符串.一个字符串的值就是它的第一个字符的地址《C++大学教程》2007.955串的结束符„\0‟inta[3]={1,2,3}chars[3]={„a‟,‟b‟,‟\0‟}s的实际长度为2,但必
须分配2+1个空间,多余一个空间用来存放’\0‟串是以’\0‟为结束符的一维字符数组《C++大学教程》2007.956复习字符串(第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”分配空间并将值写入,最后将该空间的起始地址赋给指针变量P《C++大学教程》2007.957字符串
的读入两种方式:用cin对象通过流提取读入一个字符串到一个字符数组中。读入时见到空白字符或文件结束符结束charword[10];cin>>word;通过cin调用函数getline读入一个字符串到一个字符数组中。读入时见到一个换行符号结束,结果串中不含换行符。charline
[80];cin.getline(line,80);《C++大学教程》2007.958字符串处理库中的字符串操作函数#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。《C++大学教程》2007.959intstrcmp(constchar*s1,constc
har*s2)按照字典次序比较s1和s2,s1<s2结果<0;s1=s2=0;s1>s2>0char*strcpy(char*s1,constchar*s2)把s2复制到s1,直到遇到s2中的’\0‟。s1要保证足够空间。函数返回的是s1size_tstrlen(cons
tchar*s)函数返回’\0‟前的字符个数字符串处理库中的字符串操作函数《C++大学教程》2007.960Fig08-32#include<iostream>usingstd::cout;usingstd::endl;#include<cstring>//prototypesforstrca
tandstrncatusingstd::strcat;usingstd::strncat;intmain(){《C++大学教程》2007.961chars1[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;//concatena
tefirst6charactersofs1tos3strncat(s3,s1,6);//places'\0'afterlastcharacter《C++大学教程》2007.962cout<<"\n\nAfterstrncat(s3,s1,6):\ns1="<
<s1<<"\ns3="<<s3;strcat(s3,s1);//concatenates1tos3cout<<"\n\nAfterstrcat(s3,s1):\ns1="<<s1<<"\ns3="<<s3<<endl;return0;}《C+
+大学教程》2007.963Fig08-34strtok把字符分解为一个个记号#include<iostream>usingstd::cout;usingstd::endl;#include<cstring>//prototypeforstr
tokusingstd::strtok;intmain(){《C++大学教程》2007.964charsentence[]="Thisisasentencewith7tokens";char*tokenPtr
;cout<<"Thestringtobetokenizedis:\n"<<sentence<<"\n\nThetokensare:\n\n";//begintokenizationofsentencetokenPtr=strto
k(sentence,"");《C++大学教程》2007.965//continuetokenizingsentenceuntiltokenPtrbecomesNULLwhile(tokenPtr!=NULL){cout<<tokenPtr<<'\n';t
okenPtr=strtok(NULL,"");//getnexttoken}//endwhilecout<<"\nAfterstrtok,sentence="<<sentence<<endl;return0;}《C++大学教程》2007.966常见错误忘记给串尾加上\0;程序员有责任确保为
串分配足够空间;chars[3];strcpy(s,”abc“);„a‟与”a”用错位置charw[100];scanf(“%s”,&w)《C++大学教程》2007.967第八章指针和基于指针的字符串指针引用调用数组与
指针函数指针基于指针的字符串总结《C++大学教程》2007.968总结—指针指针是一个包含了地址值的变量;指针的声明方式:如int*ptr,ptr称作整型指针指针的初始化:可以为0,NULL或一个变量的地址指针运算:地址运算符&将一个变量的地址赋给一个指针,不能将&用于一个常量引用运算
符*返回存储在指针所指的内存中保存的数据作为函数参数当调用函数时,如果所用参数需要在函数中修改其值,则该参数以指针的方式传入,在函数中以引用运算修改其值const修饰指针参数可以防止在函数内通过引用方式修改
所指空间的值《C++大学教程》2007.969总结—数组与指针数组名实际就是数组的起始地址,即第一个元素的地址,可以将其付给同类型的指针变量指针指向一个数组时可以象数组名一样带下标来用sizeof(数组名)返回数组的总字节数指针可进
行算数运算,特别注意指针+1意味着指针值加指向对象的字节数void指针可以存放任何类型的指针值.其他类型指针值可以直接赋值给它,但要注意:一个void指针值赋值给其他类型的指针必须经过强制的转换《C++大学教程》2007.970总结数组中也可以存放指针类型函数指针是函数在内存
中的存放地址函数指针可以象其他指针一样传递给函数,从函数返回,存储赋值函数指针常用于菜单驱动系统,由用户选择菜单中的具体项来决定运行的函数字符串名代表了存储字符串数组的起始地址,本质上是一个指针值字符串处理库提供了一系列函数
strcpy、strncpy、strcat、strncat、strcmp、strncmp、strtol、strlen