C程序设计第5章构造数据类型.ppt
第五章 程序的数据描述(II)构造数据类型,本章内容,构造数据类型概述 枚举类型数组类型结构与联合类型指针类型(参数传递和动态数据结构)引用类型,构造数据类型,有些数据不适合用基本数据类型来表示。语言往往提供了由基本数据类型来构造新类型的手段。构造数据类型属于用户自定义数据类型。枚举类型数组类型结构/联合类型指针/引用类型,枚举类型,如何描述一个星期的每一天这样的数据?如果用int来描述,将会面临:1表示什么意思?星期天用什么整数表示?0还是7?如果用06表示一个星期的每一天,则对于一个取值为一个星期某一天的int型变量day,如何防止下面的逻辑错误:day=10day=day*2在C+中用枚举类型来解决上面的问题。,枚举类型的定义,枚举类型是由用户自定义的一种简单数据类型。在定义一个枚举类型时,需要列出其值集中的每个值(枚举值)。枚举类型的定义格式为:enum;为用逗号隔开的若干个标识符。例如:enum Day SUN,MON,TUE,WED,THU,FRI,SAT;enum Color RED,GREEN,BLUE;enum Month JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC;,每一个枚举值都对应着一个整数。默认情况下,第一个枚举值对应常量值0,其它的值为前一个值加1。在定义枚举类型时,也可给枚举值指定对应的整数值。例如:enum Day SUN=7,MON=1,TUE,WED,THU,FRI,SAT;TUE:2,.bool类型可看成是C+语言提供的一个预定义的枚举类型:enum bool false,true;,枚举类型变量的定义格式为:;或enum;或enum;或enum;例如:enum Day SUN=7,MON=1,TUE,WED,THU,FRI,SAT;Day d1;,枚举类型的运算,赋值一个枚举类型的变量只能在相应枚举类型的值集中取值。例如:Day day;day=SUN;/OKday=1;/Errorday=RED;/Error相同枚举类型之间可以进行赋值操作,例如:Day d1,d2;d2=d1;可以把一个枚举值赋值给一个整型变量,但不能把一个整型数赋值给枚举类型的变量,例如:int a;a=d1;/OKd1=a;/Errord1=(Day)a;/OK,但不安全,比较枚举值之间的比较为枚举值所对应的整数之间的比较。例:MON d;/Errorcout d;/OK,将把d转换成int,枚举类型输入/输出举例,#include using namespace std;int main()Day d;int i;cin i;switch(i)case 0:d=SUN;break;case 1:d=MON;break;case 2:d=TUE;break;case 3:d=WED;break;case 4:d=THU;break;case 5:d=FRI;break;case 6:d=SAT;break;default:cout Input Error!endl;exit(-1);,.switch(d)case SUN:cout SUN endl;break;case MON:cout MON endl;break;case TUE:cout TUE endl;break;case WED:cout WED endl;break;case THU:cout THU endl;break;case FRI:cout FRI endl;break;case SAT:cout SAT endl;break;return 0;,数组类型,如何表示一个向量和矩阵这样的复合数据?如果用独立的变量来分别表示它们的元素,则会面临:变量数量太多。变量之间缺乏显式的联系。C+提供了数组类型来表示上述的数据:数组类型是一种由固定多个同类型的元素按一定次序所构成的复合数据类型。数组类型是一种用户自定义的数据类型。数组类型可分为:一维数组:表示向量和线性表等二维数组:表示矩阵等多维数组(三维及三维以上),一维数组,用于表示由固定多个同类型的具有线性次序关系的数据所构成的复合数据类型。如:向量、某门课程的成绩表、学生的姓名表等。数组类型定义格式为:typedef;为任意C+类型(void除外)为整型常量表达式例如:typedef int A10;/由10个int型元素所构成的/一维数组类型,一维数组类型变量定义格式为:;或;为任意C+类型(void除外)为整型常量表达式例如:typedef int A10;A a;/由10个int型元素所构成的数组。或int a10;/由10个int型元素所构成的数组。,一维数组的操作,通常情况下,对数组类型数据的操作要通过其元素来进行。访问一维数组元素格式:为整型表达式第一个元素的下标为:0例如:int a10;/数组aa0、a1、.、a9/数组元素C+语言不对数组元素下标越界进行检查。程序员必须仔细处置这个问题!如:ai中i的取值,可把数组的每个元素看成是独立的变量。例如:int a10;int sum=0,i;.for(i=0;i10;i+)sum+=ai;不能对两个数组进行整体赋值,需要通过元素来进行:int a10,b10;.a=b;/Errorfor(int i=0;i10;i+)ai=bi;/OK,例:用一维数组实现求第n个费波那契(Fibonacci)数,#include using namespace std;int main()const int MAX_N=40;int fibsMAX_N;int n,i;cout n;if(n MAX_N)cout n太大!应不大于 MAX_N endl;return-1;fibs0=fibs1=1;/初始化第1、2个费波那契数for(i=2;in;i+)/计算其它的费波那契数fibsi=fibsi-1+fibsi-2;cout 第 n 个费波那契数是:fibsn-1 endl;return 0;,例:从键盘输入10个数,输出其中的最大值,.int main()int a10;for(int i=0;i ai;int max=a0;/首先假设第0个元素最大for(i=1;i max)max=ai;cout max endl;,例:从键盘输入10个数,把它们从小到大排序后输出,从n个数中找出最大者,与第n个数交换位置;然后,从剩余的n-1个数中再找出最大者,与第n-1个数交换位置;,一直到剩下的数只有一个为止。int main()int a10;int i;for(i=0;i ai;for(int n=10;n1;n-)/n为元素个数 int j=0;/用j记住最大元素的下标,首先假设第0个元素最大 for(i=1;iaj)j=i;/保持j为最大元素的下标/交换aj和an-1的值 int temp=an-1;an-1=aj;aj=temp;for(i=0;i10;i+)cout ai;,一维数组变量的初始化,用一对花括号把元素的初始值括起来。例如:int a10=1,2,3,4,5,6,7,8,9,10;初始化表中的值可以少于数组元素个数,不足部分的数组元素初始化成0。例如:int b10=1,2,3,4;/b4b9为0如果每个元素都进行了初始化,则数组元素个数可以省略。例如:int c=1,2,3;/隐含着c由三个元素构成,一维数组的存储分配,对于一维数组类型的数据,编译程序将会在内存中给其分配连续的存储空间来存储数组元素。例如:int a10;其内存空间分配如下:a0 a1.a9,一维数组所占的内存空间大小可以用sizeof操作符来计算。例如:int a10;cout sizeof(a);/输出数组a所占的内存字节数。,向函数传递一维数组,被调用函数的形参一般为不带数组大小的一维数组定义以及数组元素的个数。例如:int max(int x,int num)int i,j;j=0;/先假设第0个元素最大for(i=1;i xj)j=i;return j;,调用者需要把一个一维数组变量的名以及数组元素的个数传给被调用函数。例如:int a10,b20,index_max;.index_max=max(a,10);cout aindex_max index_max endl;index_max=max(b,20);cout bindex_max index_max endl;,为了提高数组传递的效率,数组作为函数参数传递时实际传递的是数组在内存中的首地址,函数的形参数组不再分配内存空间,它共享实参数组的内存空间。函数中通过形参数组能改变实参数组的值!(函数的副作用),字符串的一种实现一维字符数组,C+语言本身没有提供字符串类型。在C+中,通常用元素类型为char的一维数组(字符数组)来表示字符串类型。例如:char s10;/可表示长度为9的字符串用字符数组存贮字符串时,通常在最后一个字符的后面放置一个字符串结束标记:0。在定义一个字符数组时,其元素个数应比它实际能够存储的字符串最大长度多一个.字符串作为函数参数传递时,只要给出一维字符数组类型的形参,不需要给出字符个数(长度)。,例:编写一个函数把一个由数字构成的字符串转换成一个整型数,算法:1234-(1*10+2)*10+3)*10+4int str_to_int(char str)if(str0=0)return 0;int n=str0-0;for(int i=1;stri!=0;i+)n=n*10+(stri-0);return n;,int str_to_int(char str)int n=0;for(int i=0;stri!=0;i+)n=n*10+(stri-0);return n;,字符数组的初始化,char s10=h,e,l,l,o,0;char s10=hello;char s10=hello;char s=hello;在上面的字符数组初始化中,除了第一种形式,其它形式的初始化都会在最后一个字符的后面自动加上0,而对于第一种形式,程序中必须显式地加上0。,标准库中的字符串处理函数(头文件cstring或string.h),计算字符串的长度int strlen(const char s);字符串复制char*strcpy(char dst,const char src);char*strncpy(char dst,const char src,int n);字符串拼接char*strcat(char dst,const char src);char*strncat(char dst,const char src,int n);字符串比较int strcmp(const char s1,const char s2);int strncmp(const char s1,const char s2,int n);,例:从键盘输入一个字符串,然后把该字符串逆向输出,#include#include using namespace std;int main()const int MAX_LEN=100;char strMAX_LEN;cin str;/?int len=strlen(str);/str中的字符个数for(int i=0,j=len-1;ilen/2;i+,j-)char temp;temp=stri;stri=strj;strj=temp;cout str endl;return 0;,二维数组,二维数组通常用于表示由固定多个同类型的具有行列结构的数据所构成的复合数据。如矩阵等。二维数组所表示的是一种具有两维结构的数据,第一维称为二维数组的行,第二维称为二维数组的列。二维数组的每个元素由其所在的行和列唯一确定。,二维数组类型定义格式:typedef;为任意C+类型(void除外)和为整型常量表达式例如:typedef int A105;/由10行、5列int型元素/所构成的二维数组类型,二维数组类型变量的定义格式:;或;或 为任意C+类型(void除外)、和为整型常量表达式,例如:typedef int A105;A a;或int a105;或typedef int B5;B a10;,二维数组的操作,访问二维数组元素,格式是:和为整型表达式,均从0开始。例如:int a105;a00、a01、.、a90、.、a94以行为单位访问,例如:int a105;a0、a1、.、a9上面每一个都为一个一维数组,代表二维数组中的一行,对二维数组的操作通常是通过其元素来进行。例如:int a105,sum=0;.for(int i=0;i10;i+)for(int j=0;j5;j+)sum+=aij;,例:从键盘输入一个NN的矩阵,把它转置后输出,#include using namespace std;int main()const int N=3;int aNN;int i,j;/输入矩阵数据cout aij;,/矩阵转置:交换aij和aji的值,i=0N-1,j=i+1N-1for(i=0;iN;i+)for(j=i+1;jN;j+)/交换aij与aji的值int temp=aij;aij=aji;aji=temp;/输出转置后的矩阵cout 转置后为:n;for(i=0;iN;i+)for(j=0;jN;j+)cout aij;cout endl;return 0;,x x x x x x x x x x x x x x x,二维数组的初始化,int a23=1,2,3,4,5,6;int a23=1,2,3,4,5,6;int a23=1,2,3,4;以上初始化按照数组的行来进行 int a23=1,2,3,4;a00、a01、a10和a11分别初始化为1,2,3和4,其它为0int a3=1,2,3,4,5,6,7,8,9;行数为3,二维数组的存贮,在C+中,二维数组元素是按照行来存储的,即先是第一行的元素;再是第二行的元素;.。例如:int a105;其内存空间分配如下:,a00.a04 a10.a14.a90.a94,向函数传递二维数组,被调用函数的形参应为不带数组行数的二维数组定义及其行数。例如:int sum(int x5,int lin)/接收lin行、5列的二维数组int s=0;for(int i=0;ilin;i+)for(int j=0;j5;j+)s+=xij;return s;注意:二维数组作为函数参数传递时实际传递的也是数组的首地址,因此,二维数组形参的列数必须要写,否则,函数体中无法计算xij的内存地址:xij的地址=x的首地址+i列数+j,调用者需要提供一个二维数组变量(列数要与形参相同)的名和行数。例如:int a105,b205;.cout a的元素之和为:sum(a,10)endl;cout b的元素之和为:sum(b,20)endl;下面的二维数组c就不能调用函数sum来计算其元素的和,因为c的列数与函数sum要求的列数不符:int c4020;.sum(c,40);/Error,二维数组降为一维数组处理,int sum(int x,int num)int s=0;for(int i=0;inum;i+)s+=xi;return s;.int a105,b205,c4020;.cout sum(a0,10*5)endl;cout sum(b0,20*5)endl;cout sum(c0,40*20)endl;,例:求解约瑟夫(Josephus)问题,约瑟夫(Josephus)问题是:有N个小孩围坐成一圈,从某个小孩开始顺时针报数,报到M的小孩从圈子离开,然后,从下一个小孩开始重新报数,每报到M,相应的小孩从圈子离开,最后一个离开圈子的小孩为胜者,问胜者是哪一个小孩?采用一个一维的循环数组in_circle来表示小孩围成一圈:bool in_circleN;in_circlei为true表示编号为i的小孩在圈子里。圈子中i的下一个位置j=(i+1)%N,0,N-1,1,N-2,报数采用下面的方法来实现:从编号为0的小孩开始报数,用变量index表示要报数的小孩的下标,其初始值为N-1(即将报数的前一个小孩的下标)。下一个要报数的小孩的下标由:(index+1)%N 来计算。用变量count来对成功的报数进行计数,每一轮报数前,count为0,每成功地报一次数,就把count加1,直到M为止。要使得报数成功,in_circleindex应为true。用变量num_of_children_remained表示圈中剩下的小孩数目,其初始值为N。,/变量num_of_children_remained表示圈中剩下的小孩数目,其初始值为N/变量count来对成功的报数进行计数/变量index表示要报数的小孩的位置#include using namespace std;const int N=20,M=5;int main()bool in_circleN;int num_of_children_remained,index;/初始化数组in_circle。for(index=0;indexN;index+)in_circleindex=true;,/开始报数index=N-1;/从编号为0的小孩开始报数,/index为前一个小孩的位置。num_of_children_remained=N;/报数前的圈子中小孩个数while(num_of_children_remained 1)int count=0;while(count M)/对成功的报数进行计数,直到M。index=(index+1)%N;/计算要报数的小孩的编号。if(in_circleindex)count+;/如果编号为index的/小孩在圈子中,该报数为成功的报数。in_circleindex=false;/小孩离开圈子。num_of_children_remained-;/圈中小孩数减1。,/找最后一个小孩for(index=0;indexN;index+)if(in_circleindex)break;cout The winner is No.index.n;return 0;,结构(struct)类型,结构类型用于表示由固定多个类型可以不同的元素所构成的复合数据,它是一种用户自定义类型。结构类型定义格式:struct;为结构类型的元素(成员)类型说明可以是任意的C+类型(void和本结构除外)结构成员之间在逻辑上没有先后次序关系结构成员的说明次序会影响成员的存储安排,例如:struct Studentint no;char name20;Sex sex;Date birth_date;char birth_place40;Major major;,enum Sex MALE,FEMALE;struct Dateint year,month,day;enum Major MATHEMATICS,PHYSICS,CHEMISTRY,COMPUTER,GEOGRAPHY,ASTRONOMY,ENGLISH,CHINESE,PHILOSOPHY;,结构类型变量的定义格式如下:;或struct;或struct;或struct;例如:Student st;,结构类型的操作,访问结构成员结构成员的访问要通过结构变量名来“受限”.例如:Student st;st.no,st.name,.每个成员都可以看作是一个独立的变量,可以分别操作它们,例如:st.no=1;strcpy(st.name,张三);st.sex=MALE;.,不同结构类型的成员的名字可以相同,并且,它们还可以与程序中非结构成员的名字相同:struct Achar name10;/OK.;struct Bchar name5;/OK.;char name20;/OKint main()A a;B b;.a.name./结构变量a的成员变量name。.b.name./结构变量b的成员变量name。.name./全局变量name。,赋值可以对结构类型数据进行整体结构赋值,例如:Student st1,st2;st1=st2;/OK不同的结构类型之间不能相互赋值,例如:Student st;Date today;st=today;/Error,结构类型变量的初始化,在定义结构类型的变量时,依次给出成员的初始化,例如:Student some_student=2,李四,FEMALE,1970,12,20,北京,MATHEMATICS;在定义一个结构类型时,不能对其成员进行初始化,例如:struct A int i=1;/Error double d=1.2;/Error,结构类型的存储,结构类型的变量在内存中占用一块连续的存储空间,其各个元素依它们在结构类型中的定义次序存储在这块内存空间中。例如:Student st;其内存空间安排如下:st.no st.name st.sex st.birth_date st.birth_place st.major结构成员的内存空间之间可能会存在空隙!可用sizeof计算结构类型的大小,向函数传递结构数据,可作为参数传给函数,默认参数传递方式为值传递,例如:void f(Student st).Student st1;.f(st1);可作为函数返回值返回给调用者,例如:Student g().return.;.Student st1=g();,例:名表,名表是指一个由一系列名字及其相关信息所构成的表。名表可以用一个一维数组来表示,每个元素用一个结构来表示。const int NAME_LEN=20;const int TABLE_LEN=100;struct TableItem char nameNAME_LEN;./其它信息;TableItem name_tableTABLE_LEN;,名表的查找(检索),名表查找是指根据某个名字在名表中查找与该名字相关的信息。顺序查找折半查找(二分法),名表查找(顺序),#include using namespace std;int linear_search(char key,/关键词TableItem t,/名表int num_of_items)/表的长度int index;for(index=0;indexnum_of_items;index+)if(strcmp(key,tindex.name)=0)break;if(index num_of_items)return index;elsereturn-1;,const int NAME_LEN=20;const int TABLE_LEN=100;struct TableItem char nameNAME_LEN;./其它信息;TableItem name_tableTABLE_LEN;int main()int n;/名表元素的个数(长度)./名表元素数据的获取char nameNAME_LEN;/待查找的名字./待查找的名字获取int result=linear_search(name,name_table,n);if(result=-1)cout Not foundn;return-1;./使用name_tableresult的值return 0;,名表查找(二分法),如果名表的元素已经按名字大小排了序,则可以采用折半查找:首先用要查找的值与名表中间位置上的元素与进行比较若相等,则找到,若大于中间位置上的元素,则在名表的后半部分中继续进行查找;若小于中间位置上的元素,则在名表的前半部分中继续进行查找。在前半部分或后半部分中查找时,仍然采用折半查找,直到找到或表中元素比较完为止。,int binary_search(char key,TableItem t,int num_of_items)int index,first,last;first=0;last=num_of_items-1;while(first 0)/key大于tindex.name first=index+1;else/key小于tindex last=index-1;return-1;,联合(union)类型,联合类型用于实现用一个类型表示多种类型的数据。例如:union A int i;char c;double d;上面的联合类型A既可以描述int型数据,也可以描述char和double类型数据。联合类型的所有成员占有同一块内存空间,该内存空间的大小为其最大成员所需要的内存空间的大小。A a;cout sizeof(a);/输出:8,在程序运行的不同时刻中,可以给一个联合类型的变量赋予不同类型的数据,例如:A a;a.i=1;/给变量a赋一个int型的值./把a当作int型来用a.c=A;/给变量a赋一个char型的值./把a当作char型来用。a.d=2.0;/给变量a赋一个double型的值./把a当作double型来用。对于一个联合类型的变量,在程序中将会分阶段地把它作为不同的类型来使用,而不会同时把它作为几种类型来用。,当给一个联合类型的变量赋了一个某种类型的值之后,如果以另外一种类型来使用这个值,将得不到原来的值。例如:a.i=12;cout a.d;/输出什么呢?也可利用联合类型来实现多种数据共享内存空间。例如:union AB int a100;double b100;AB buffer;.buffer.a./使用数组a.buffer.b./使用数组b.,例:从键盘输入一组图形数据,然后输出相应的图形。其中的图形可以是:线段、矩形和圆。,一组图形数据可用一个一维数组表示:const int MAX_NUM_OF_FIGURES=100;Figure figuresMAX_NUM_OF_FIGURES;数组元素的类型Figure是一个联合类型。,struct Linedouble x1,y1,x2,y2;struct Rectangledouble left,top,right,bottom;struct Circledouble x,y,r;union FigureLine line;Rectangle rect;Circle circle;上面的表示存在问题:无法区分存储在figuresi中的是什么图形!,解决上面问题的办法是:enum FigureShape LINE,RECTANGLE,CIRCLE;struct LineFigureShape place_holder;double x1,y1,x2,y2;struct RectangleFigureShape place_holder;double left,top,right,bottom;struct CircleFigureShape place_holder;double x,y,r;,union FigureFigureShape shape;Line line;Rectangle rect;Circle circle;给一个数组元素figuresi赋值时,除了图形的几何数据外,还需给出它为何种图形。例如:figuresi.shape=LINE;figuresi.line.x1=10;figuresi.line.y1=20;figuresi.line.x2=100;figuresi.line.y2=200;访问数组元素figuresi时,通过figuresi.shape的值就可知道figuresi存储的是什么图形。,图形数据的输入:int count;for(count=0;count shape;while(shape 2);if(shape=-1)break;switch(shape)case 0:/线figurescount.shape=LINE;cout figurescount.line.x1 figurescount.line.y1 figurescount.line.x2 figurescount.line.y2;break;,case 1:/矩形figurescount.shape=RECTANGLE;cout figurescount.rect.left figurescount.rect.top figurescount.rect.right figurescount.rect.bottom;break;case 2:/圆形figurescount.shape=CIRCLE;cout figurescount.circle.x figurescount.circle.y figurescount.circle.r;break;/end of switch/end of for,图形的输出:for(int i=0;icount;i+)switch(figuresi.shape)case LINE:draw_line(figuresi.line);break;case RECTANGLE:draw_rectangle(figuresi.rect);break;case CIRCLE:draw_circle(figuresi.circle);break;,指针类型,在C+中,用指针类型来描述内存地址,通过指针运算来实现与内存地址有关的程序功能。指针是内存地址的抽象表示,一个指针代表了一个内存地址。指针类型是一种用户自定义的简单类型,它的值集是由一些内存地址(指针)构成。,指针类型的定义,指针类型的定义格式为:typedef*;其中,表示一个指针类型,其值集为所表示的数据的地址,例如:typedef int*Pointer;上面定义了一个指针类型Pointer,其值集为所有int变量的地址。,指针类型变量的定义,指针类型变量(简称:指针变量)的定义格式:;或*;例如:typedef int*Pointer;Pointer p;/p为一个指向整数类型数据的指针变量或int*p;/p为一个指向整数类型数据的指针变量注意:指针变量拥有自己的内存空间,在该空间中存储的是另一个数据的内存地址,指针变量,指向的数据,指针类型的基本操作,取地址间接访问赋值指针运算,取地址操作&,int x.&x./取变量x的地址,int x,*p,*p1;double y,*q;.p=/OK,不建议使用。,指针赋值操作,间接访问操作(*和-),可以通过“*”来访问一个指针变量指向的变量,例如:int x;int*p;p=,指针间接访问操作的例子,执行操作:“x=1;”前,(假设120和124分别代表变量x和p的内存地址)x p 120:?124:?执行操作:“x=1;”后:x p 120:1124:?执行操作:“p=”后,x p 120:2124:120,int*p;int x;x=1;p=,对于一个指向结构类型变量的指针变量,如果通过该指针变量来访问相应结构变量的成员,则可以写成:(*).或-例如:struct A int i;double d;char ch;;A a;A*p=/输出a.i和a.d,请注意下面的问题:int*p;*p=1;/1赋值到哪里去了?,一个指针加上或减去一个整型值实际加(或减)的值由该指针所指向的数据类型来定。例如:int x;int*p;p=访问数组a的元素可采用:a0、a1、.、a9*p、*(p+1)、.、*(p+9)p0、p1、.、p9,指针的运算,int a10;int*p=,两个同类型的指针相减实际结果由指针所指向的类型来定。例如:int a10;int*p=,int x=1;int*p=/输出q指向的字符:Acout(void*)q/输出p的值,即字符串ABCD的内存首地址,指针的输出,指针的主要作用,提高参数传递的效率实现动态数据结构高效访问数组元素,指针作为形参类型,void swap(int x,int y)int t=x;x=y;y=t;int main()int a=0,b=1;swap(a,b);cout a=a,b=b endl;return 0;输出:a=0,b=1,void swap(int*px,int*py)/交换px和py所指向的变量的值。int t=*px;*px=*py;*py=t;int main()int a=0,b=1;swap(输出:a=1,b=0,向函数传递大型的结构类型数据,struct Aint no;char name20;.;void f(A*p)/p为指向结构类型的指针.p-no./或者,(*p).no.p-name./或者,(*p).name.int main()A a;.f(/把结构变量的地址传给函数f。.,再论数组作为参数传递,在C+中,数组参数的默认传递方式是把实参数组的首地址传给函数,以提高参数传递效率。实际上,对于下面的函数定义和调用:int max(int x,int num).xi.编译程序将按下面来解释:int max(int*x,int num).*(x+i).,int main()int a10;.max(a,10).,int main()int a10;.max(&a0,10).,避免指针参数带来的副作用,指针作为形参的类型可以产生两个效果:提高参数传递效率:大量数据的参数传递,通过形参改变实参的值:把函数的计算结果(有多个)通过参数返回给调用者。如果只需要指针参数的第一种效果,怎么办?,指向常量的指针,const int*p;/p为指向常量的指针变量int*q;const int x=0;int y;p=/?,OK,如果只需要指针参数的第一种效果,则应把形参定义为指向常量的指针。例如:void g(const A*p)/A为一个结构类型.p-no=./Error,不能改变p所指向的数据。再例如:void f(const int*p,int num)/或者,void f(const int p,int num).pi=./Error,不能改变p所指向的数据。.,指向常量的指针作为函数形参类型,指针作为函数返回值类型,函数的返回值类型可以是一个指针类型。例如:int*max(int x,int num)int max_index=0;for(int i=1;i xmax_index)max_index=i;return,不能把局部量的地址作为指针返回给调用者。例如:int*f()int i=0;return,指针与动态变量,对输入的100个数进行排序:int a100;for(int i=0;i ai;sort(a,100);对输入的若干个数进行排序,下面的做法可行吗?int n;cin n;int an;for(int i=0;i ai;sort(a,n);,动态变量,动态变量是指在程序运行中,由程序根据需要所创建的变量。例如:int*p,*q;p=new int;/创建了一个int型动态变量,p指向之。或p=(int*)malloc(sizeof(int);/#include 再例如:q=new intn;/创建了一个由n个int型元素所构成/的动态数组变量,q指向其第一个元素。或q=(int*)malloc(sizeof(int)*n);,动态变量没有名字,对动态变量的访问需要通过指向动态变量的指针变量来进行(间接访问)。例如:int*p,*q;p=new int;.*p./访问上面创建的int型动态变量q=new intn;.*(q+3)./或.q3.,访问上面创建的/动态数组中的第4个元素,在C+中,动态变量需要由程序显式地撤消(使之消亡)。例如:delete p;/撤消p指向的int型动态变量或free(p);再例如:delete q;/撤消q指向的动态数组或free(q);用new创建的动态变量需要用delete来撤销;用malloc创建的动态变量则需要用free撤销。,new与malloc的主要区别在于:new自动计算所需分配的空间大小,而malloc则需要显式指出。new自动返回相应类型的指针,而malloc要作强制类型转换。例如:int*p,*q;p=new in