C语言程序设计课件第06章数组、指针与字符串_第1页
C语言程序设计课件第06章数组、指针与字符串_第2页
C语言程序设计课件第06章数组、指针与字符串_第3页
C语言程序设计课件第06章数组、指针与字符串_第4页
C语言程序设计课件第06章数组、指针与字符串_第5页
已阅读5页,还剩173页未读 继续免费阅读

下载本文档

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

文档简介

第六章数组、指针与字符串C++语言程序设计1第六章数组、指针与字符串C++语言程序设计1本章主要内容数组指针动态存储分配深拷贝与浅拷贝字符串2本章主要内容数组2数组的概念数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。数组属于构造类型。数组3数组的概念数组是具有一定顺序关系的若干相同类型变量的集合体数组的几点说明数组的定义形式同C语言中的数组。数组名是常量,表示数组元素的首地址。数组下标从零开始。下标必须是整形表达式。数组元素可以在定义时直接给出初始值列表。数组元素作函数参数同简单变量作函数参数。数组名作函数参数传递的是地址值。二维数组在内存中按行存放。数组4数组的几点说明数组的定义形式同C语言中的数组。数对象数组声明:类名数组名[元素个数];访问方法:数组名[下标].成员名数组5对象数组声明:数组5对象数组初始化数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。通过初始化列表赋值。PointA[2]={Point(1,2),Point(3,4)};如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化(调用默认构造函数或带默认形参值的构造函数)。

PointA[2]={Point(1,2)};数组6对象数组初始化数组中每一个元素对象被创建时,系统都会调用类构数组元素所属类的构造函数各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。当数组中每一个对象被删除时,系统都要调用一次析构函数。数组7数组元素所属类的构造函数各元素对象的初值要求为相同的值时,可数组#include<iostream>usingnamespacestd;classPoint{public:Point();~Point();};Point::Point(){cout<<"DefaultConstructorcalled."<<endl;}Point::~Point(){cout<<"Destructorcalled."<<endl;}voidmain(){PointA[2];}P163例6-38数组#include<iostream>P声明例:inti;int*i_pointer;概念指针:内存地址,用于间接访问内存单元指针变量:用于存放地址的变量20003i_pointer*i_pointeri2000引用i_pointer

=&i;i=3;*i_pointer=3;指针指针变量的概念9声明概念20003i_pointer*i_pointeri2语法形式

存储类型数据类型*指针名=初始地址;例:inta,*pa=&a;注意事项用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。可以用一个已赋初值的指针去初始化另一个指针变量。不要用一个内部auto变量去初始化static指针。指针指针变量的初始化10语法形式指针指针变量的初始化10指针名=地址向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。指针的类型是它所指向变量的类型,而不是指针本身数据值的类型,任何一个指针本身的数据值都是unsignedlongint型。允许声明指向void类型的指针。该指针可以被赋予任何类型对象的地址。但是不能通过void类型的指针间接访问所指向的变量,必须经过强制类型转换。

指针指针变量的赋值11指针名=地址指针指针变量的赋值11例6-6void类型指针的使用#include<iostream>usingnamespacestd;//voidvobject;//错,不能声明void类型的变量void*pv;//对,可以声明void类型的指针int*pint;inti;voidmain(){cout<<"i="<<i<<endl;pv=&i; //void类型指针指向整型变量

//cout<<"*pv="<<*pv<<endl;//错,不能访问pint=(int*)pv;cout<<"*pint="<<*pint<<endl;}指针cout<<"*pv="<<*(int*)pv<<endl;12例6-6void类型指针的使用#include<iost指针变量的算术运算指针与整数的加减运算指针p加上或减去n,其意义是指针当前指向位置的前方或后方第n个数据的地址。这种运算的结果值取决于指针指向的数据类型。指针自增,自减运算指向下一个或前一个数据。例如:y=*px++相当于y=*(px++)

(*和++优先级相同,自右向左运算)指针13指针变量的算术运算指针与整数的加减运算指针papa-2pa-1pa+1pa+2pa+3*(pa-2)*pa*(pa+1)*(pa+2)*(pa+3)*(pa-1)short*pa1414papa-2pa-1pa+1pa+2pa+3*(pa-2)*pb-1pbpb+1pb+2*(pb-1)*pb*(pb+1)*(pb+2)long*pb1515pb-1pbpb+1pb+2*(pb-1)*pb*(pb+1关系运算指向相同类型数据的指针之间可以进行==与!=的关系运算。指向不同数据类型的指针,以及指针与一般整数变量之间的关系运算是无意义的。指针可以和零之间进行等于或不等于的关系运算。例如:p==0或p!=0指针变量的关系运算指针16关系运算指针变量的关系运算指针16指向数组元素的指针声明与赋值例:inta[10],*pa;pa=&a[0];或pa=a;通过指针引用数组元素经过上述声明及赋值后:*pa就是a[0],*(pa+i)就是a[i].a[i],*(pa+i),*(a+i),pa[i]都是等效的。不能写a++,因为a是数组首地址(是常量)。指针17指向数组元素的指针声明与赋值指针17指针数组数组的元素是指针类型例:Point*pa[2];

由pa[0],pa[1]两个指针组成指针18指针数组数组的元素是指针类型指针18例6-8利用指针数组存放单位矩阵#include<iostream>usingnamespacestd;voidmain(){ intline1[]={1,0,0};//声明数组,矩阵的第一行 intline2[]={0,1,0};//声明数组,矩阵的第二行 intline3[]={0,0,1};//声明数组,矩阵的第三行 int*p_line[3]; //声明整型指针数组 p_line[0]=line1;//初始化指针数组元素 p_line[1]=line2; p_line[2]=line3;指针19例6-8利用指针数组存放单位矩阵#include<io //输出单位矩阵cout<<"Matrixtest:"<<endl; for(inti=0;i<3;i++) {for(intj=0;j<3;j++) cout<<<<"";cout<<endl; }}输出结果为:Matrixtest:10001000120指针也可以写成:p_line[i][j]或*(*(p_line+i)+j)*(p_line[i]+j)20 //输出单位矩阵输出结果为:20指针也可例6-9二维数组举例#include<iostream>usingnamespacestd;voidmain(){inta[2][3]={{11,12,13},{21,22,23}};int(*p1)[3]=a;for(inti=0;i<2;i++){for(intj=0;j<3;j++)cout<<*(*(p1+i)+j)<<"";cout<<endl; }}指针可以写成:*(p1[i]+j)或p1[i][j]21例6-9二维数组举例#include<iostream例6-9二维数组举例#include<iostream>usingnamespacestd;voidmain(){inta[2][3]={{11,12,13},{21,22,23}};int*p1=a;for(inti=0;i<2;i++){for(intj=0;j<3;j++)cout<<*p1++<<"";cout<<endl; }}指针在C++中这种赋值是错误的。22例6-9二维数组举例#include<iostream以指针作为函数参数以地址方式传递数据,可以用来返回函数处理结果。实参是数组名时形参可以是指针。

指针与函数23以指针作为函数参数以地址方式传递数据,可以用来返回函数处理结例6-10题目:读入三个浮点数,将整数部分和小数部分分别输出#include<iostream>usingnamespacestd;voidsplitfloat(floatx,int*intpart,float*fracpart){*intpart=int(x);//取x的整数部分

*fracpart=x-*intpart;//取x的小数部分}

指针与函数24例6-10题目:读入三个浮点数,将整数部分和小数部分分别输出voidmain(){ inti,n; floatx,f; cout<<"Enterthree(3)floatingpointnumbers"<<endl; for(i=0;i<3;i++) { cin>>x; splitfloat(x,&n,&f); cout<<"IntegerPartis"<<n

<<"FractionPartis"<<f<<endl; }}25

指针与函数25voidmain()25指针与函数25运行结果:Enterthree(3)floatingpointnumbers4.7IntegerPartis4FractionPartis0.78.913IntegerPartis8FractionPartis0.913-4.7518IntegerPartis-4FractionPartis-0.751826

指针与函数26运行结果:26指针与函数26例:输出数组元素的内容和地址#include<iostream>#include<iomanip>usingnamespacestd;voidArray_Ptr(long*P,intn){ inti; cout<<"Infunc,addressofarrayis"

<<unsignedlong(P)<<endl; cout<<"Accessingarrayusingpointers"<<endl; for(i=0;i<n;i++) {cout<<"Addressforindex"<<i<<"is"

<<unsignedlong(P+i); cout<<"Valueis"<<*(P+i)<<endl; }}

指针与函数27例:输出数组元素的内容和地址#include<iostrvoidmain(){ longlist[5]={50,60,70,80,90}; cout<<"Inmain,addressofarrayis"<<unsignedlong(list)<<endl; cout<<endl; Array_Ptr(list,5);}2828voidmain()2828运行结果:Inmain,addressofarrayis6684132Infunc,addressofarrayis6684132AccessingarrayusingpointersAddressforindex0is6684132Valueis50Addressforindex1is6684136Valueis60Addressforindex2is6684140Valueis70Addressforindex3is6684144Valueis80Addressforindex4is6684148Valueis902929运行结果:2929指针型函数当函数的返回值是地址时,该函数就是指针型函数。定义形式:

返回值类型*函数名(参数表){函数体}

指针与函数30指针型函数当函数的返回值是地址时,该函数就是指针型函数。指针型函数#include<iostream>usingnamespacestd;char*ch(chars[]){inti;for(i=0;s[i]!='\0';i++) if(s[i]=='A')break;returns+i;}voidmain(){char*s="ThbikAjiklom";cout<<ch(s)<<endl;}

指针与函数31指针型函数#include<iostream>指针声明形式数据类型(*函数指针名)();

含义:数据指针指向数据存储区,而函数指针指向的是程序代码存储区。指向函数的指针

指针与函数32声明形式指向函数的指针指针与函数32例6-11函数指针#include<iostream>usingnamespacestd;voidprint_stuff(floatdata_to_ignore);voidprint_message(floatlist_this_data);voidprint_float(floatdata_to_print);void(*function_pointer)(float); voidmain() { floatpi=(float)3.14159; floattwo_pi=(float)2.0*pi;

指针与函数33例6-11函数指针#include<iostream>

print_stuff(pi);

function_pointer=print_stuff;

function_pointer(pi);

function_pointer=print_message;

function_pointer(two_pi);

function_pointer(13.0);

function_pointer=print_float;

function_pointer(pi);

print_float(pi);}34

指针与函数34print_stuff(pi);34指针与函数voidprint_stuff(floatdata_to_ignore){ cout<<"Thisistheprintstufffunction.\n";}voidprint_message(floatlist_this_data){ cout<<"Thedatatobelistedis"<<list_this_data<<endl;}voidprint_float(floatdata_to_print){ cout<<"Thedatatobeprintedis"<<data_to_print<<endl;}35

指针与函数35voidprint_stuff(floatdata_to运行结果:Thisistheprintstufffunction.Thisistheprintstufffunction.Thedatatobelistedis6.283180Thedatatobelistedis13.000000Thedatatobeprintedis3.141590Thedatatobeprintedis3.14159036

指针与函数36运行结果:36指针与函数36指向常量的指针inti=13;intconst*p=&i;//指向常量的指针变量注:不能通过指针来改变所指对象的值,指针所指向的对象的值(i的值)可以通过直接访问方式进行更新,指针本身的值也可以改变,可以指向另外的对象。指针37指向常量的指针inti=13;指针37#include<iostream>usingnamespacestd;voidmain(){inti=13;int*p=&i;i++;(*p)++;cout<<i<<ends<<*p<<endl;}指针#include<iostream>usingnamespacestd;voidmain(){inti=13;intconst

*p=&i;i++;

(*p)++;cout<<i<<ends<<*p<<endl;}此语句编译错误指向常量的指针38#include<iostream>指针#char*name1="John";chars[]="abc";name1=s;*name1='1';charconst

*name1="John";chars[]="abc";name1=s;*name1='1';错误!不能通过指向常量的指针改变所指向的对象的值指针指向常量的指针char*name1="John";name1="abcdef";*name1='A';运行时错误!字符串常量的内容不能被改变39char*name1="John";charconst指针类型的常量若声明指针常量,则指针本身的值不能被改变。例:char*constname2="John";name2="abc";//错误,指针常量值不能改变指针40指针类型的常量若声明指针常量,则指针本身的值不能被改变。对象指针声明形式类名*对象指针名;例PointA(5,10);Piont*ptr;ptr=&A;通过指针访问对象成员对象指针名->成员名ptr->getx()相当于(*ptr).getx();对象指针41对象指针声明形式对象指针41对象指针应用举例voidmain(){PointA(5,10);Point*ptr;

ptr=&A; intx; x=ptr->GetX(); cout<<x<<endl;}对象指针42对象指针应用举例voidmain()对象指针this指针隐含于每一个类的成员函数中的特殊指针。明确地指出了成员函数当前所操作的数据所属的对象。当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针。this指针43this指针隐含于每一个类的成员函数中的特殊指针。tthis指针例如:Point类的构造函数体中的语句:X=xx;Y=yy;相当于:this->X=xx;this->Y=yy;this指针44this指针例如:Point类的构造函数体中的语句:this指针一般的程序设计中,通常不直接使用this指针来引用对象成员。this是一个指针变量,因此在成员函数中,可以使用*this来标识正在调用该函数的对象。this指针45this指针一般的程序设计中,通常不直接使用this#include<iostream>usingnamespacestd;classPoint {public: Point(intX,intY);intGetX(){returnX;}intGetY(){returnY;}private:intX,Y;};Point::Point(intX,intY){this->X=X;this->Y=Y;}voidmain(){Pointp(4,5);cout<<p.GetX()<<ends<<p.GetY()<<endl;}this指针46#include<iostream>this指Point::Point(intX,intY){this->X=X;this->Y=Y;cout<<GetX()<<ends<<GetY()<<endl;cout<<this->GetX()<<ends<<this->GetY();cout<<endl;

cout<<(*this).GetX()<<ends<<(*this).GetY();

cout<<endl;}this指针效果是一样的,在类的成员函数中,可以使用this指针访问类中其它成员函数。47Point::Point(intX,intY)t指向类的非静态成员的指针通过指向成员的指针可以访问对象的公有数据成员。声明指向成员的指针声明指向公有数据成员的指针类型说明符类名::*指针名;

声明指向公有函数成员的指针类型说明符(类名::*指针名)(参数表);指针48指向类的非静态成员的指针通过指向成员的指针可以访问对象的公有指向类的非静态成员的指针

指向数据成员的指针的赋值

指针名=&类名::数据成员名;上述赋值说明被赋值的指针是专门用于指向类中哪个数据成员的,同时在指针中存放该数据成员在类中的相对位置。指向函数成员的指针的赋值

指针名=类名::函数成员名;指针49指向类的非静态成员的指针指向数据成员的指针的赋值指指向类的非静态成员的指针#include<iostream>usingnamespacestd;classPoint {public: Point(intxx=0,intyy=0){X=xx;Y=yy;} intGetX(){returnX;} intGetY(){returnY;} public: intX,Y;};指针50指向类的非静态成员的指针#include<iostream指针voidmain() {PointA(4,5); Point*p1=&A; intPoint::*p_num;p_num=&Point::X;cout<<A.X<<ends;cout<<A.*p_num<<ends; cout<<p1->X<<ends; cout<<p1->*p_num<<endl;int(Point::*p_GetX)();p_GetX=Point::GetX; cout<<A.GetX()<<ends;cout<<(A.*p_GetX)()<<ends; cout<<p1->GetX()<<ends; cout<<(p1->*p_GetX)()<<endl; }指向数据成员的指针指向函数成员的指针数据成员指针赋值函数成员指针赋值指向对象的指针51指针voidmain() 指向数据成员的指向类的非静态成员的指针通过对象名(或对象指针)与成员指针结合来访问数据成员:对象名.*类成员指针名或:对象指针名—>*类成员指针名通过对象名(或对象指针)与成员指针结合来访问函数成员:(对象名.*类成员指针名)(参数表)或:(对象指针名—>*类成员指针名)(参数表)指针52指向类的非静态成员的指针通过对象名(或对象指针)与成员指针结指向类的静态成员的指针对类的静态成员的访问不依赖于对象可以用普通的指针来指向和访问静态成员例6-14通过指针访问类的静态数据成员例6-15通过指针访问类的静态函数成员指针53指向类的静态成员的指针对类的静态成员的访问不依赖于对象#include<iostream>usingnamespacestd;classPoint {public: Point(intxx=0,intyy=0){X=xx;Y=yy;countP++;} Point(Point&p); intGetX(){returnX;} intGetY(){returnY;}

staticintcountP;private: intX,Y;};Point::Point(Point&p){ X=p.X;Y=p.Y;countP++;}intPoint::countP=0;指针P184例6-1454#include<iostream>指针voidmain() { int*count=&Point::countP; PointA(4,5); cout<<"Point,"<<A.GetX()<<","<<A.GetY();cout<<"Objectid="<<*count<<endl;

PointB(A); cout<<"PointB,"<<B.GetX()<<","<<B.GetY(); cout<<"Objectid="<<*count<<endl; }55指针55voidmain() 55指针55指针P185例6-15#include<iostream>usingnamespacestd;classPoint {public: Point(intxx=0,intyy=0){X=xx;Y=yy;countP++;} Point(Point&p); intGetX(){returnX;} intGetY(){returnY;}

staticvoidGetC(){cout<<"Objectid="<<countP<<endl;}private: intX,Y;staticintcountP;};Point::Point(Point&p){X=p.X;Y=p.Y;countP++;}intPoint::countP=0;56指针P185例6-15#includevoidmain() { void(*gc)()=Point::GetC; PointA(4,5); cout<<"PointA,"<<A.GetX()<<","<<A.GetY();

gc(); PointB(A); cout<<"PointB,"<<B.GetX()<<","<<B.GetY();

gc();}57指针57voidmain() 57指针57动态申请内存操作符new

new类型名T(初值列表)功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL)

动态存储分配58动态申请内存操作符newnew类型名T(初动态申请内存操作符new

动态存储分配int*point=newint(2);等价于:int*point;point=newint(2);注:动态分配了用于存放int类型数据的内存空间,同时在此空间中存入数值2。如果不指定初值可以写成:point=newint;或point=newint();59动态申请内存操作符new动态存储分配int*po动态申请内存操作符new

动态存储分配Line*line=newLine;表示:调用默认的构造函数。默认的构造函数不存在则调用带有默认形参值的构造函数。上述两种函数都不存在,则创建动态存储区失败。60动态申请内存操作符new动态存储分配Line*l释放内存操作符deletedelete指针P功能:释放指针P所指向的内存。P必须是new操作的返回值。

动态存储分配61释放内存操作符deletedelete指针P动态存#include<iostream>usingnamespacestd;classPoint{public:

Point(){X=Y=0;cout<<"DefaultConstructorcalled.\n";}

Point(intxx,intyy){X=xx;Y=yy;cout<<"Constructorcalled.\n";}~Point(){cout<<"Destructorcalled.\n";}intGetX(){returnX;}intGetY(){returnY;}voidMove(intx,inty){X=x;Y=y;}private:intX,Y;};

动态存储分配动态创建对象62#include<iostream>动态存储分配动态voidmain(){cout<<"StepOne:"<<endl;

Point*Ptr1=newPoint;deletePtr1;cout<<"StepTwo:"<<endl;

Ptr1=newPoint(1,2);deletePtr1;}运行结果:StepOne:DefaultConstructorcalled.Destructorcalled.StepTwo:Constructorcalled.Destructorcalled.63

动态存储分配63voidmain()运行结果:63动态存储分配63例6-17动态创建对象数组举例#include<iostream>usingnamespacestd;classPoint{//类的声明同上例,略};voidmain(){Point*Ptr=newPoint[2];//创建对象数组Ptr[0].Move(5,10);Ptr[1].Move(15,20);cout<<"Deleting..."<<endl;delete[]Ptr;//删除整个对象数组}

动态存储分配64例6-17动态创建对象数组举例#include<iostre运行结果:DefaultConstructorcalled.DefaultConstructorcalled.Deleting...Destructorcalled.Destructorcalled.65

动态存储分配65运行结果:65动态存储分配65例6-18动态数组类P189#include<iostream>usingnamespacestd;classPoint{//类的声明同例6-16…};classArrayOfPoints{public:ArrayOfPoints(intn){numberOfPoints=n;points=newPoint[n];}~ArrayOfPoints(){cout<<"Deleting..."<<endl;numberOfPoints=0;delete[]points;}Point&Element(intn){returnpoints[n];}private:Point*points;intnumberOfPoints;};66

动态存储分配66例6-18动态数组类P189#include<iostreavoidmain(){ intnumber; cout<<"Pleaseenterthenumberofpoints:"; cin>>number;//创建对象数组ArrayOfPointspoints(number);//通过指针访问数组元素的成员points.Element(0).Move(5,10);//通过指针访问数组元素的成员points.Element(1).Move(15,20);}67

动态存储分配67voidmain()67动态存储分配67运行结果如下:Pleaseenterthenumberofpoints:2DefaultConstructorcalled.DefaultConstructorcalled.Deleting...Destructorcalled.Destructorcalled.68

动态存储分配68运行结果如下:68动态存储分配68动态创建多维数组new类型名T[下标表达式1][下标表达式2]…;

如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,不是一个T类型的指针,而是一个指向T类型数组的指针,数组元素的个数为除最左边一维外各维下标表达式的乘积。例如:char(*fp)[3];fp=newchar[2][3];

动态存储分配69动态创建多维数组new类型名T[下标表达式1][下标表达式char(*fp)[3];fpfp+1fp[0][0]fp[0][1]fp[0][2]fp[1][0]fp[1][1]fp[1][2]7070char(*fp)[3];fpfp+1fp[0][0]fp例6-19动态创建多维数组#include<iostream>usingnamespacestd;voidmain(){ float(*cp)[9][8]; inti,j,k; cp=newfloat[8][9][8]; for(i=0;i<8;i++) for(j=0;j<9;j++) for(k=0;k<8;k++) *(*(*(cp+i)+j)+k)=i*100+j*10+k;//通过指针访问数组元素

动态存储分配71例6-19动态创建多维数组#include<iostreamfor(i=0;i<8;i++){for(j=0;j<9;j++){for(k=0;k<8;k++)//将指针cp作为数组名使用,//通过数组名和下标访问数组元素cout<<cp[i][j][k]<<""; cout<<endl; } cout<<endl;}}72

动态存储分配例6-19动态创建多维数组72for(i=0;i<8;i++)72动态动态存储分配函数void*malloc(size);参数size:欲分配的字节数返回值:成功,则返回void型指针。

失败,则返回空指针。头文件:<cstdlib>和<cmalloc>

动态存储分配73动态存储分配函数void*malloc(size);动态内存释放函数voidfree(void*memblock);参数memblock:指针,指向需释放的内存。返回值:无头文件:<cstdlib>和<cmalloc>

动态存储分配74动态内存释放函数voidfree(void*membl浅拷贝与深拷贝浅拷贝实现对象间数据元素的一一对应复制。深拷贝当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指的对象进行复制。浅拷贝与深拷贝75浅拷贝与深拷贝浅拷贝浅拷贝与深拷贝75#include<iostream>usingnamespacestd;classCopy{public:Copy(){p=newint(2);}voidsetP(){*p=14;}intshow(){return*p;}private:int*p;};voidmain(){Copyc1;Copyc2(c1);cout<<"c1="<<c1.show()<<ends;cout<<"c2="<<c2.show()<<endl;c1.setP();cout<<"c1="<<c1.show()<<ends;cout<<"c2="<<c2.show()<<endl;}76#include<iostream>voidmain()7#include<iostream>usingnamespacestd;classCopy{public:Copy(){p=newint(2);}

Copy(Copy&c);voidsetP(){*p=14;}intshow(){return*p;}private:int*p;};Copy::Copy(Copy&c){p=newint(4);}voidmain(){Copyc1;Copyc2(c1);cout<<"c1="<<c1.show()<<ends;cout<<"c2="<<c2.show()<<endl;c1.setP();cout<<"c1="<<c1.show()<<ends;cout<<"c2="<<c2.show()<<endl;}77#include<iostream>voidmain()7用字符数组存储和处理字符串

字符串用字符数组处理字符串同C语言。charch[6]={'c','h','i,'n','a'};charch[6]={"china"};charch[6]="china";78用字符数组存储和处理字符串字符串用字符数组处理字符串字符串的输入/输出方法逐个字符输入输出将整个字符串一次输入或输出

例:charc[]="China";

cout<<c;注意输出字符不包括'\0'输出字符串时,输出项是字符数组名,输出时遇到'\0'结束。输入多个字符串时,以空格分隔;输入单个字符串时其中不能有空格。

字符串79字符串的输入/输出方法字符串79例如:程序中有下列语句:charstr1[5],str2[5],str3[5];cin>>str1>>str2>>str3;运行时输入数据:Howareyou?内存中变量状态如下:str1:How\0str2:are\0str3:you?\080

字符串80例如:内存中变量状态如下:80字符串80若改为:charstr[13];cin>>str;运行时输入数据:Howareyou?内存中变量str内容如下:str:How\081

字符串81若改为:内存中变量str内容如下:81字符串8整行输入字符串cin.getline(字符数组名St,字符个数N,结束符);功能:一次连续读入多个字符(可以包括空格),直到读满N个,或遇到指定的结束符(默认为‘\n’)。读入的字符串存放于字符数组St中。读取但不存储结束符。cin.get(字符数组名St,字符个数N,结束符);功能:一次连续读入多个字符(可以包括空格),直到读满N个,或遇到指定的结束符(默认为'\n')。读入的字符串存放于字符数组St中。

既不读取也不存储结束符。

字符串82整行输入字符串cin.getline(字符数组名St,字符个整行输入字符串举例#include<iostream>usingnamespacestd;voidmain(void){ charcity[80]; charstate[80]; inti; for(i=0;i<2;i++) {cin.getline(city,80,',');

cin.getline(state,80,'\n'); cout<<"City:"<<city<<"State:"

<<state<<endl; }}

字符串83整行输入字符串举例#include<iostream>运行结果Beijing,ChinaCity:BeijingState:ChinaShanghai,ChinaCity:ShanghaiState:China

字符串84运行结果Beijing,China字符串84字符串处理函数strcat(连接),strcpy(复制),

strcmp(比较),strlen(求长度),

strlwr(转换为小写),

strupr(转换为大写)头文件<cstring>

字符串85字符串处理函数strcat(连接),strcpy(复制),

字符串string类C++预定义了字符串string类,string类提供了对字符串处理所需要的操作,使用string类需要包括头文件string,string类封装了串的属性并提供了一系列允许访问这些属性的服务。P198P199表6-1string类的操作86字符串string类C++预定义了字例6.21string类应用举例#include<string>#include<iostream>usingnamespacestd;voidtrueFalse(intx){cout<<(x?"True":"False")<<endl;}

字符串87例6.21string类应用举例#include<strvoidmain(){string

S1="DEF",S2="123";charCP1[]="ABC";charCP2[]="DEF";cout<<"S1is"<<S1<<endl;cout<<"S2is"<<S2<<endl;cout<<"lengthofS2:"<<S2.length()<<endl;cout<<"CP1is"<<CP1<<endl;cout<<"CP2is"<<CP2<<endl;cout<<"S1<=CP1returned";trueFalse(S1<=CP1);cout<<"CP2<=S1returned";trueFalse(CP2<=S1);

S2+=S1;cout<<"S2=S2+S1:"<<S2<<endl;cout<<"lengthofS2:"<<S2.length()<<endl;}8888voidmain()8888小结与复习建议主要内容数组、指针、动态存储分配、指针与数组、指针与函数、字符串达到的目标理解数组、指针的概念,掌握定义和使用方法,掌握动态存储分配技术,会用数组存储和处理字符串,会使用String类。实验任务实验六89小结与复习建议主要内容89第六章数组、指针与字符串C++语言程序设计90第六章数组、指针与字符串C++语言程序设计1本章主要内容数组指针动态存储分配深拷贝与浅拷贝字符串91本章主要内容数组2数组的概念数组是具有一定顺序关系的若干相同类型变量的集合体,组成数组的变量称为该数组的元素。数组属于构造类型。数组92数组的概念数组是具有一定顺序关系的若干相同类型变量的集合体数组的几点说明数组的定义形式同C语言中的数组。数组名是常量,表示数组元素的首地址。数组下标从零开始。下标必须是整形表达式。数组元素可以在定义时直接给出初始值列表。数组元素作函数参数同简单变量作函数参数。数组名作函数参数传递的是地址值。二维数组在内存中按行存放。数组93数组的几点说明数组的定义形式同C语言中的数组。数对象数组声明:类名数组名[元素个数];访问方法:数组名[下标].成员名数组94对象数组声明:数组5对象数组初始化数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。通过初始化列表赋值。PointA[2]={Point(1,2),Point(3,4)};如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化(调用默认构造函数或带默认形参值的构造函数)。

PointA[2]={Point(1,2)};数组95对象数组初始化数组中每一个元素对象被创建时,系统都会调用类构数组元素所属类的构造函数各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。当数组中每一个对象被删除时,系统都要调用一次析构函数。数组96数组元素所属类的构造函数各元素对象的初值要求为相同的值时,可数组#include<iostream>usingnamespacestd;classPoint{public:Point();~Point();};Point::Point(){cout<<"DefaultConstructorcalled."<<endl;}Point::~Point(){cout<<"Destructorcalled."<<endl;}voidmain(){PointA[2];}P163例6-397数组#include<iostream>P声明例:inti;int*i_pointer;概念指针:内存地址,用于间接访问内存单元指针变量:用于存放地址的变量20003i_pointer*i_pointeri2000引用i_pointer

=&i;i=3;*i_pointer=3;指针指针变量的概念98声明概念20003i_pointer*i_pointeri2语法形式

存储类型数据类型*指针名=初始地址;例:inta,*pa=&a;注意事项用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。可以用一个已赋初值的指针去初始化另一个指针变量。不要用一个内部auto变量去初始化static指针。指针指针变量的初始化99语法形式指针指针变量的初始化10指针名=地址向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。指针的类型是它所指向变量的类型,而不是指针本身数据值的类型,任何一个指针本身的数据值都是unsignedlongint型。允许声明指向void类型的指针。该指针可以被赋予任何类型对象的地址。但是不能通过void类型的指针间接访问所指向的变量,必须经过强制类型转换。

指针指针变量的赋值100指针名=地址指针指针变量的赋值11例6-6void类型指针的使用#include<iostream>usingnamespacestd;//voidvobject;//错,不能声明void类型的变量void*pv;//对,可以声明void类型的指针int*pint;inti;voidmain(){cout<<"i="<<i<<endl;pv=&i; //void类型指针指向整型变量

//cout<<"*pv="<<*pv<<endl;//错,不能访问pint=(int*)pv;cout<<"*pint="<<*pint<<endl;}指针cout<<"*pv="<<*(int*)pv<<endl;101例6-6void类型指针的使用#include<iost指针变量的算术运算指针与整数的加减运算指针p加上或减去n,其意义是指针当前指向位置的前方或后方第n个数据的地址。这种运算的结果值取决于指针指向的数据类型。指针自增,自减运算指向下一个或前一个数据。例如:y=*px++相当于y=*(px++)

(*和++优先级相同,自右向左运算)指针102指针变量的算术运算指针与整数的加减运算指针papa-2pa-1pa+1pa+2pa+3*(pa-2)*pa*(pa+1)*(pa+2)*(pa+3)*(pa-1)short*pa103103papa-2pa-1pa+1pa+2pa+3*(pa-2)*pb-1pbpb+1pb+2*(pb-1)*pb*(pb+1)*(pb+2)long*pb104104pb-1pbpb+1pb+2*(pb-1)*pb*(pb+1关系运算指向相同类型数据的指针之间可以进行==与!=的关系运算。指向不同数据类型的指针,以及指针与一般整数变量之间的关系运算是无意义的。指针可以和零之间进行等于或不等于的关系运算。例如:p==0或p!=0指针变量的关系运算指针105关系运算指针变量的关系运算指针16指向数组元素的指针声明与赋值例:inta[10],*pa;pa=&a[0];或pa=a;通过指针引用数组元素经过上述声明及赋值后:*pa就是a[0],*(pa+i)就是a[i].a[i],*(pa+i),*(a+i),pa[i]都是等效的。不能写a++,因为a是数组首地址(是常量)。指针106指向数组元素的指针声明与赋值指针17指针数组数组的元素是指针类型例:Point*pa[2];

由pa[0],pa[1]两个指针组成指针107指针数组数组的元素是指针类型指针18例6-8利用指针数组存放单位矩阵#include<iostream>usingnamespacestd;voidmain(){ intline1[]={1,0,0};//声明数组,矩阵的第一行 intline2[]={0,1,0};//声明数组,矩阵的第二行 intline3[]={0,0,1};//声明数组,矩阵的第三行 int*p_line[3]; //声明整型指针数组 p_line[0]=line1;//初始化指针数组元素 p_line[1]=line2; p_line[2]=line3;指针108例6-8利用指针数组存放单位矩阵#include<io //输出单位矩阵cout<<"Matrixtest:"<<endl; for(inti=0;i<3;i++) {for(intj=0;j<3;j++) cout<<<<"";cout<<endl; }}输出结果为:Matrixtest:100010001109指针也可以写成:p_line[i][j]或*(*(p_line+i)+j)*(p_line[i]+j)109 //输出单位矩阵输出结果为:20指针也可例6-9二维数组举例#include<iostream>usingnamespacestd;voidmain(){inta[2][3]={{11,12,13},{21,22,23}};int(*p1)[3]=a;for(inti=0;i<2;i++){for(intj=0;j<3;j++)cout<<*(*(p1+i)+j)<<"";cout<<endl; }}指针可以写成:*(p1[i]+j)或p1[i][j]110例6-9二维数组举例#include<iostream例6-9二维数组举例#include<iostream>usingnamespacestd;voidmain(){inta[2][3]={{11,12,13},{21,22,23}};int*p1=a;for(inti=0;i<2;i++){for(intj=0;j<3;j++)cout<<*p1++<<"";cout<<endl; }}指针在C++中这种赋值是错误的。111例6-9二维数组举例#include<iostream以指针作为函数参数以地址方式传递数据,可以用来返回函数处理结果。实参是数组名时形参可以是指针。

指针与函数112以指针作为函数参数以地址方式传递数据,可以用来返回函数处理结例6-10题目:读入三个浮点数,将整数部分和小数部分分别输出#include<iostream>usingnamespacestd;voidsplitfloat(floatx,int*intpart,float*fracpart){*intpart=int(x);//取x的整数部分

*fracpart=x-*intpart;//取x的小数部分}

指针与函数113例6-10题目:读入三个浮点数,将整数部分和小数部分分别输出voidmain(){ inti,n; floatx,f; cout<<"Enterthree(3)floatingpointnumbers"<<endl; for(i=0;i<3;i++) { cin>>x; splitfloat(x,&n,&f); cout<<"IntegerPartis"<<n

<<"FractionPartis"<<f<<endl; }}114

指针与函数114voidmain()25指针与函数25运行结果:Enterthree(3)floatingpointnumbers4.7IntegerPartis4FractionPartis0.78.913IntegerPartis8FractionPartis0.913-4.7518IntegerPartis-4FractionPartis-0.7518115

指针与函数115运行结果:26指针与函数26例:输出数组元素的内容和地址#include<iostream>#include<iomanip>usingnamespacestd;voidArray_Ptr(long*P,intn){ inti; cout<<"Infunc,addressofarrayis"

<<unsignedlong(P)<<endl; cout<<"Accessingarrayusingpointers"<<endl; for(i=0;i<n;i++) {cout<<"Addressforindex"<<i<<"is"

<<unsignedlong(P+i); cout<<"Valueis"<<*(P+i)<<endl; }}

指针与函数116例:输出数组元素的内容和地址#include<iostrvoidmain(){ longlist[5]={50,60,70,80,90}; cout<<"Inmain,addressofarrayis"<<unsignedlong(list)<<endl; cout<<endl; Array_Ptr(list,5);}117117voidmain()2828运行结果:Inmain,addressofarrayis6684132Infunc,addressofarrayis6684132AccessingarrayusingpointersAddressforindex0is6684132Valueis50Addressforindex1is6684136Valueis60Addressforindex2is6684140Valueis70Addressforindex3is6684144Valueis80Addressforindex4is6684148Valueis90118118运行结果:2929指针型函数当函数的返回值是地址时,该函数就是指针型函数。定义形式:

返回值类型*函数名(参数表){函数体}

指针与函数119指针型函数当函数的返回值是地址时,该函数就是指针型函数

温馨提示

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

评论

0/150

提交评论