成员函数课件

上传人:痛*** 文档编号:241780705 上传时间:2024-07-23 格式:PPT 页数:77 大小:318.04KB
返回 下载 相关 举报
成员函数课件_第1页
第1页 / 共77页
成员函数课件_第2页
第2页 / 共77页
成员函数课件_第3页
第3页 / 共77页
点击查看更多>>
资源描述
第五章 成员函数5.1 成员函数的概念 为了实现对象的行为,我们把一些相关的为了实现对象的行为,我们把一些相关的语句语句组织在一起,并给它们注明相应的名称,形成一组织在一起,并给它们注明相应的名称,形成一些相对独立而且便于管理和阅读的小块程序,每些相对独立而且便于管理和阅读的小块程序,每个小程序块描述了一个完整的行为,这种形式的个小程序块描述了一个完整的行为,这种形式的组合就构成了成员函数。组合就构成了成员函数。5.2.1 算法的概念 一个完整的对象应该包括两个方面的内一个完整的对象应该包括两个方面的内容,容,即对数据的描述(对象属性)和对操作的描述即对数据的描述(对象属性)和对操作的描述(对象行为)。对操作的描述也就是算法,是设(对象行为)。对操作的描述也就是算法,是设计和实现对象行为的灵魂。计和实现对象行为的灵魂。一个完整的算法应该具有以下一个完整的算法应该具有以下5 5个特性:个特性:有穷性有穷性、确定性确定性、有效性有效性、输入性输入性和和输出性输出性。5.2.1 算法的表示 为了表示一个算法,可以采用多种形式。最常见为了表示一个算法,可以采用多种形式。最常见的几的几种方法有自然语言表示法、流程图表示法、伪代码表示法种方法有自然语言表示法、流程图表示法、伪代码表示法和计算机语言表示法。和计算机语言表示法。自然语言表示法:自然语言表示法:自然语言表示法就是用我们日常生活中的语言来表示算法的自然语言表示法就是用我们日常生活中的语言来表示算法的实现实现过程,对采用何种语言没有限制。但是采用自然语言表示往往不太严过程,对采用何种语言没有限制。但是采用自然语言表示往往不太严格,容易造成歧义。另外,用这种方法描述包含分支和循环的算法不格,容易造成歧义。另外,用这种方法描述包含分支和循环的算法不太方便。因此,自然语言表示法很少用来描述复杂的算法。太方便。因此,自然语言表示法很少用来描述复杂的算法。流程图表示法:流程图表示法:流程图就是用一些图框表示各种操作。用流程图来表示算法流程图就是用一些图框表示各种操作。用流程图来表示算法最大最大的优点就是直观形象,便于理解,并且实用性强,能够方便的表示包的优点就是直观形象,便于理解,并且实用性强,能够方便的表示包含分支和循环的结构,避免了用自然语言表示算法的不足。含分支和循环的结构,避免了用自然语言表示算法的不足。图图5.1 5.1 一般流程图表示算法一般流程图表示算法 图图5.2 N-S5.2 N-S流程图表示算法流程图表示算法5.2.2 算法的表示伪代码表示法:伪代码表示法:伪代码是用介于自然语言和计算机语言之间的文字和符号伪代码是用介于自然语言和计算机语言之间的文字和符号来描述算法。从结构上看,伪代码表示法类似于最终的计算机语来描述算法。从结构上看,伪代码表示法类似于最终的计算机语言,每一行就表示一个基本的操作。言,每一行就表示一个基本的操作。伪代码表示法书写格式比较自由,容易直观表达出设计者伪代码表示法书写格式比较自由,容易直观表达出设计者的思想。同时,书写的算法也容易修改,很容易写出结构话的算的思想。同时,书写的算法也容易修改,很容易写出结构话的算法。法。因此,这种方法一般被专业的软件开发人员采用,特别是在因此,这种方法一般被专业的软件开发人员采用,特别是在详细详细设计中采用伪代码表示法,可以使以后的编码阶段变得简单。设计中采用伪代码表示法,可以使以后的编码阶段变得简单。5.2.2 算法的表示计算机语言表示法:计算机语言表示法:一个算法要拿到计算机上去运行,最终还是要采一个算法要拿到计算机上去运行,最终还是要采用计算机语言表示。目前使用的计算机语言多种多样,用计算机语言表示。目前使用的计算机语言多种多样,本书所介绍的面向对象的程序设计语言(本书所介绍的面向对象的程序设计语言(C+C+)就是种很)就是种很好的描述和实现算法的工具。好的描述和实现算法的工具。5.3 成员函数的定义与调用 5.3.1 成员函数的定义说明一个函数原型的一般形式有两种:返回值类型返回值类型 函数名函数名(参数类型参数类型1 1 参数名参数名1,1,参数类型参数类型2 2 参数参数名名,);,);返回值类型返回值类型 函数名函数名(参数类型参数类型1,1,参数类型参数类型2,);2,);5.3.1 成员函数的定义定义一个成员函数必须具备四个条件:定义一个成员函数必须具备四个条件:函数必须具有返回值类型,即函数必须有返回值,且该函数必须具有返回值类型,即函数必须有返回值,且该返回值的类型应该与函数返回值的类型一致返回值的类型应该与函数返回值的类型一致 函数必须具有一个名字,即函数名。函数必须具有一个名字,即函数名。函数必须具有一个形参(形式参数)列表,函数必须具有一个形参(形式参数)列表,C+C+规定,规定,形参列表以左括号形参列表以左括号“(”(”开始,到右括号开始,到右括号“)”)”结束,且各结束,且各个形参个形参之间用之间用“,”,”分开。分开。函数要完成一定的功能,必须具有一个函数体,函数要完成一定的功能,必须具有一个函数体,其中,其中,前面的三个条件构成了函数的原型。前面的三个条件构成了函数的原型。说明一个函数原型的一般形式有两种:说明一个函数原型的一般形式有两种:函数返回值类型函数返回值类型 函数名函数名(参数类型参数类型1 1 参数名参数名1,1,参数类型参数类型2 2 参数名参数名2,)2,);函数返回值类型函数返回值类型 函数名函数名(参数类型参数类型1,1,参数类型参数类型2,);2,);以上两种方法均可以使用,但是为了增加程序的可读性建以上两种方法均可以使用,但是为了增加程序的可读性建议使用第一种方法。议使用第一种方法。请注意,这时的函数名应该包含:请注意,这时的函数名应该包含:类名类名(Circle)+(Circle)+作用域分辨符作用域分辨符(:)+(:)+原函数原函数(circle_areacircle_area)5.3.1 成员函数的定义5.3.2 成员函数的调用一般形式有两种:一般形式有两种:对象名对象名.函数名函数名(实参实参1,1,实参实参2,);2,);对象指针对象指针函数名函数名(实参实参1,1,实参实参2,);2,);例如:例如:void main()void main()coutcout “The area of circle=”“The area of circle=”mycircle.circle_area(3.14);mycircle.circle_area(3.14);5.3.2 成员函数的调用关于形参和实参的说明:关于形参和实参的说明:在函数定义时说明的形参,并不占内存中的存储单元。在函数定义时说明的形参,并不占内存中的存储单元。只有在函数调用时,形参才被分配内存单元,并被赋以实只有在函数调用时,形参才被分配内存单元,并被赋以实参的值。在调用结束后,该部分内存立刻被释放。参的值。在调用结束后,该部分内存立刻被释放。实参可以是常量、变量、或表达式等,但要求它们必须实参可以是常量、变量、或表达式等,但要求它们必须有确定的值。有确定的值。5.3.3.1函数指针 在程序运行中,每个函数在编译时都会在程序运行中,每个函数在编译时都会被编译被编译器分配给一个入口地址,则指向这个入口地址的器分配给一个入口地址,则指向这个入口地址的指针就称为函数指针。函数代码是程序的算法指指针就称为函数指针。函数代码是程序的算法指令部分,被存放在代码区(令部分,被存放在代码区(codecode),函数指针指),函数指针指向代码区中某个函数的地址,因此,通过函数指向代码区中某个函数的地址,因此,通过函数指针可以调用相应的函数。针可以调用相应的函数。函数指针的声明函数指针的声明正确的指针类型声明如下:正确的指针类型声明如下:返回值类型返回值类型 (*(*函数指针名函数指针名)()(参数表参数表););例如:例如:intint(*(*func_p)(charfunc_p)(char a,char b);a,char b);其中,其中,“intint”表示函数的返回值类型为整型,表示函数的返回值类型为整型,“(*(*func_pfunc_p)”)”表示表示func_pfunc_p是一个指针,后面的是一个指针,后面的(char(char a,chara,char b)b)表示该表示该指针(指针(func_pfunc_p)是函数指针。其定义后产生的指针变量)是函数指针。其定义后产生的指针变量有全局、静态与局部之分,同样占有内存空间(与其他有全局、静态与局部之分,同样占有内存空间(与其他类型指针变量所占空间相同)。类型指针变量所占空间相同)。5.3.3.1函数指针5.3.3.1函数指针调用函数 由于由于(*(*func_pfunc_p)所扮演的角色与函数名相同,因此所扮演的角色与函数名相同,因此在使在使用用(*(*func_pfunc_p)时,只需将他看作函数名即可。时,只需将他看作函数名即可。看下面一个例子,学习如何通过函数指针调用函数:看下面一个例子,学习如何通过函数指针调用函数:intint func(intfunc(int););intint(*(*func_p)(intfunc_p)(int););func_pfunc_p=funcfunc;/函数指针函数指针(*(*func_pfunc_p)指向代码区函数指向代码区函数funcfunc()()的地址的地址intint x=x=funcfunc(4);/(4);/使用函数使用函数funcfunc()(),这个用法很,这个用法很常见常见intint y=(*func_p)(5);y=(*func_p)(5);/使用函数指针使用函数指针(*(*func_pfunc_p)实际上调用了实际上调用了funcfunc()()函数函数5.3.3.1函数指针用作函数参数函数指针可以作为函数的参数,如下所示:函数指针可以作为函数的参数,如下所示:int all(int x,int y,int(*func)(int,int)int all(int x,int y,int(*func)(int,int)return(*func)(x,y);return(*func)(x,y);函数函数allall共有共有3 3 个形参,它的第三个形参是指向函个形参,它的第三个形参是指向函数的指针对象数的指针对象intint(*func)(int,int)(*func)(int,int),可用一个定义的,可用一个定义的函数代替函数代替allall中的中的 funcfunc,例如,例如all(a,b,maxall(a,b,max),相当于执行,相当于执行max(a,bmax(a,b),从而输出,从而输出 a,ba,b当中的最大值。当中的最大值。同样方法可以调用同样方法可以调用 minmin,而,而allall函数的形式不函数的形式不变,只是在调用时改变实参函数名。这就增加了函数使用变,只是在调用时改变实参函数名。这就增加了函数使用的灵活性,它在大型程序设计中,尤其是模块设计时特别的灵活性,它在大型程序设计中,尤其是模块设计时特别有用。有用。完整的示例程序:#include#include using namespace std;using namespace std;int all(int x,int y,int(*func)(int,int)int all(int x,int y,int(*func)(int,int)return(*func)(x,y);return(*func)(x,y);int max(int x,int y)int max(int x,int y)return(xy?x:y);return(xy?x:y);int min(int x,int y)int min(int x,int y)return(xy?x:y);return(xy?x:y);void main()void main()int a,b;int a,b;a=15,b=20;a=15,b=20;coutmax=all(a,b,max)endl;coutmax=all(a,b,max)endl;coutmin=all(a,b,min)endl;coutmin=all(a,b,min)endl;5.3.3.1函数指针注意事项注意:注意:(1)(1)定义一个函数指针与定义一个返回值是指针的函数不同定义一个函数指针与定义一个返回值是指针的函数不同intint(*(*f_p)(constf_p)(const char*);/char*);/定义一个函数的指定义一个函数的指针针intint*func_p(charfunc_p(char a)/a)/定义一个返回指针的定义一个返回指针的函数函数(2)(2)可以用可以用typedeftypedef简化函数指针的使用,如下例:简化函数指针的使用,如下例:typedeftypedef intint(*(*FUN)(intFUN)(int a,a,intint b);b);/声明声明(*FUN)(*FUN)是一个函数指针类型是一个函数指针类型FUN FUN func_pfunc_p;/func_pfunc_p为一个返回整型和两个整型参数的函数指为一个返回整型和两个整型参数的函数指针针(3)(3)函数指针可以和其他指针一样地使用函数指针可以和其他指针一样地使用5.3.4内联函数 内联函数也称内嵌函数,它主要是解决程内联函数也称内嵌函数,它主要是解决程序的运行效率。序的运行效率。因为函数调用通常需要建立栈内环境,进因为函数调用通常需要建立栈内环境,进行参数传递,并产生程序执行转移,这些工作都行参数传递,并产生程序执行转移,这些工作都需要一些时间开销,对于一些代码很短,但使用需要一些时间开销,对于一些代码很短,但使用频率很高的函数来说,时间开销显得尤为突出。频率很高的函数来说,时间开销显得尤为突出。如果将那些代码很短且调用频率高的函如果将那些代码很短且调用频率高的函数定义为内联函数,则编译器在程序中每次遇到数定义为内联函数,则编译器在程序中每次遇到该函数名时,都直接用内联函数的函数体来替换,该函数名时,都直接用内联函数的函数体来替换,以次来减少时间开销。以次来减少时间开销。#include#include using namespace std;using namespace std;inline int isnumber(char);inline int isnumber(char);/inline /inline 函数声明函数声明void main()void main()char c;char c;while(c=cin.get()!=n)while(c=cin.get()!=n)if(isnumber(c)if(isnumber(c)/调用一个小函数调用一个小函数coutyou enter a digit n;coutyou enter a digit n;else else coutyou enter a non-digit n;cout=0&ch=0&chZ)将将!右!右边的的结果(果(逻辑值)取非)取非R按位取反运算符按位取反运算符 A将将A值按位取反按位取反R取地址与取取地址与取值运算运算符符&pX=&Y提取提取变量量Y的地址,然后的地址,然后赋给指指针变量量pXR*X=*pY提取指提取指针变量量pY所指的地址所指的地址单元的内元的内容,然后容,然后赋给变量量X类型型转换运算符运算符(类型名)型名)X=(int)Y将将Y转换为整型,然后整型,然后赋给XR动态内存分配运算内存分配运算符符NewPa=new int4;创建一个整型数建一个整型数组,其中含有,其中含有4个元素,个元素,并将首地址并将首地址给PaRdeletedelete Pa;delete Pb;数数组必必须用用delete 进行行删除除普通的堆普通的堆对象可用象可用delete删除除4将两数相减将两数相减*X*Y将两数相乘将两数相乘L/X/Y将两数相除将两数相除%X%Y将两数相除取其余数将两数相除取其余数5+X+Y将两数相加将两数相加-X Y将两数相减将两数相减6移位运算符移位运算符A A 2将将A值向右平移向右平移2位位7关系运算符关系运算符X X Y判断判断X是否大于是否大于Y=X=X=Y判断判断X是否大于等于是否大于等于Y8=X=Y判断判断X是否等于是否等于Y!=X!=Y判断判断X是否不等于是否不等于Y9位运算符位运算符&A&B将将A和和B的的值按位相与按位相与L10A B将将A和和B的的值按位相异或按位相异或11|A|B将将A和和B的的值按位相或按位相或12逻辑运算符运算符&XZ将将&两两边的的结果(果(逻辑值)相与)相与L13|XZ将将|两两边的的结果(果(逻辑值)相或)相或14条件运算符条件运算符?:?:Z=XY?E1:E2;如果如果XY为真,真,Z等于等于E1的的值,否,否则等于等于E2的的值R15赋值运算符运算符=X=Y将将Y的的值赋给XR+=X+=Y将将X的的值加加Y后,再后,再赋给X,等价,等价于于 X=X+Y-=X-=Y将将X的的值减减Y后,再后,再赋给X,等价,等价于于 X=X Y*=X*=Y将将X的的值乘乘Y后,再后,再赋给X,等价,等价于于 X=X*Y/=X/=Y将将X的的值除除Y后,再后,再赋给X,等价,等价于于 X=X/Y%=X%=Y将将X的的值对Y取余后,再取余后,再赋给X,等价于等价于 X=X%Y&=X&=Y将将X的的值与与Y按位相与后,再按位相与后,再赋给X,等价于,等价于 X=X&Y=X=Y将将X的的值与与Y按位相异或后,再按位相异或后,再赋给X,等价于,等价于 X=X Y|=X|=Y将将X的的值与与Y按位相或后,再按位相或后,再赋给X,等价于,等价于 X=X|Y=X=Y将将X的的值左移左移Y位后,再位后,再赋给X,等价于等价于 X=X=X=Y将将X的的值右移右移Y位后,再位后,再赋给X,等价于等价于 X=X Y16逗号运算符逗号运算符,E1,E2,E3从左到右依次求出表达式从左到右依次求出表达式E1,E2,E3的的值L5.4.2 表达式 所谓表达式是指:所谓表达式是指:用运算符将运算对象(也称操作用运算符将运算对象(也称操作数)数)连接起来的、符合语法规则的式子连接起来的、符合语法规则的式子。根据连接运算对象的连接符(运算符)的不同大体上可以将根据连接运算对象的连接符(运算符)的不同大体上可以将表达式分为以下四种:表达式分为以下四种:算术运算表达式(算术运算表达式的运算结果是数值算术运算表达式(算术运算表达式的运算结果是数值 )逻辑运算表达式(逻辑运算表达式的运算结果是逻辑值逻辑运算表达式(逻辑运算表达式的运算结果是逻辑值 )赋值运算表达式(赋值运算符的结合性是从右向左的赋值运算表达式(赋值运算符的结合性是从右向左的 )逗号运算表达式(逗号运算表达式的值是最后一个表达式逗号运算表达式(逗号运算表达式的值是最后一个表达式的值的值 )5.4.2 表达式注意:注意:当一个表达式中包含多种运算符时,必须考虑运算符的优先级和当一个表达式中包含多种运算符时,必须考虑运算符的优先级和结合性。结合性。可以用()改变运算符的优先级;可以用()改变运算符的优先级;例如例如:intint i=1,n=2;i=1,n=2;n=i+n 1;n=i+n 1;/因为因为“+”+”高于高于“”高于高于“=”=”,所以先运,所以先运算算i+ni+n 等于等于3 3,/再运算再运算3131得得6 6,最后,最后n=6n=6。用用“()”()”改变先后次序如下:改变先后次序如下:intint i=1,n=2;i=1,n=2;n=i+(n 1);n=i+(n 1);/因为因为 (n1n1)高于高于“+”+”高于高于“=”=”,所以先运,所以先运算算n1 n y?e1:e2;x y?e1:e2;i+;i+;赋值运算符左侧必须是一个可以引用的存储单赋值运算符左侧必须是一个可以引用的存储单元(如:变量),决不能是表达式。元(如:变量),决不能是表达式。5.4.3 数据类型的转换类型转换就是将一种类型的值转换为另一种类型的值。类型转换就是将一种类型的值转换为另一种类型的值。隐式类型转换隐式类型转换 其转换过程是由系统按照一定的转换规则自动完成的。其转换过程是由系统按照一定的转换规则自动完成的。显式类型转换显式类型转换 显式类型转换的方法有两种。显式类型转换的方法有两种。(1)(1)强制转换法强制转换法 强制转换法的格式为:强制转换法的格式为:(类型名类型名)表达式表达式;如:如:(int)xint)x;(2)(2)函数法函数法 函数法的转换格式为:类型名函数法的转换格式为:类型名(表达式表达式););如:如:int(xint(x););为了提高程序的设计质量,为了提高程序的设计质量,19661966年,年,BohmBohm和和 acopiniacopini提出了提出了在程序设计过程中在程序设计过程中,使用以下三种控制结,使用以下三种控制结构构作为算法的基本单元作为算法的基本单元。事实上,任何一个成员函数的。事实上,任何一个成员函数的定义都离不开这三种基本结构:定义都离不开这三种基本结构:5.5.1 5.5.1 顺序结构顺序结构顺序结构是指程序语句按顺序,自上而下依次执行顺序结构是指程序语句按顺序,自上而下依次执行 5.5.2 5.5.2 选择结构(又称分支结构)选择结构(又称分支结构)选择结构是指能根据选择条件,改变程序走向的一种语句选择结构是指能根据选择条件,改变程序走向的一种语句 5.5.3 5.5.3 循环结构循环结构 循环结构是指能根据循环条件,重复执行某段程序的一种循环结构是指能根据循环条件,重复执行某段程序的一种语句。是代码可重用技术的一种基本形式语句。是代码可重用技术的一种基本形式 5.5 控制结构5.5.1 顺序结构 顺序结构是指程序语句按顺序,自上而下依次执顺序结构是指程序语句按顺序,自上而下依次执行。行。如,输入三角形的三边长,求三角形面积的函数。如,输入三角形的三边长,求三角形面积的函数。f_areaf_area:float float f_areaf_area(float a,float b,float c)(float a,float b,float c)float s;float s;s=1.0/2 *(a+b+c);s=1.0/2 *(a+b+c);return return sqrtsqrt(s*(s a)*(s-b)*(s-(s*(s a)*(s-b)*(s-c);c);5.5.2 选择结构(又称分支结构)if if 和和 if elseif elseifif是最简单的选择语句,一般格式为:是最简单的选择语句,一般格式为:if(if()2 当条件表达式的值为当条件表达式的值为“真真”,我们所要执行的语句多于一条时,我们所要执行的语句多于一条时,C+C+规定,必须将这些语句用规定,必须将这些语句用“”和和“”括起来。一般格式为:括起来。一般格式为:if(if()1 2 n n+15.5.2 选择结构(又称分支结构)if elseif else是用来解决在互相对立的两种条件下,所要分别进行处是用来解决在互相对立的两种条件下,所要分别进行处理理的两条语句。的两条语句。if(if()1 2 nelseelse n+1 n+2 n+k n+k+1 5.5.2 选择结构当分支结构(即选择结当分支结构(即选择结构)的分支较多时,构)的分支较多时,C+C+提供了嵌套式的选提供了嵌套式的选择结构:择结构:if(if()1)12nelse if(else if()2)n+1n+2n+kelseelse n+k+1n+k+2n+k+m n+k+m+1 5.5.2 选择结构(又称分支结构)例如,设计一个函数,当输入大于例如,设计一个函数,当输入大于0 0时,输出为时,输出为1 1;当输入小;当输入小于于0 0时,输出为时,输出为 -1-1;当输入等于;当输入等于0 0时,输出为时,输出为0 0;(注意本例中判断条件有;(注意本例中判断条件有三种情况)三种情况)intint f_s(intf_s(int x)x)ifif(x0 x0)0)/到此排除了到此排除了x0 x0 x0和和x=0 x=0的情况的情况 x=1;x=1;elseelse/到此排除了到此排除了x0 x0 x0的情况,只剩下的情况,只剩下x=x=0 0的情况的情况 x=0;x=0;return x;return x;5.5.2 选择结构(又称分支结构)switchswitch语句又称开关语句。主要用于根据某个整型数据语句又称开关语句。主要用于根据某个整型数据的变的变化,达到多种分支的目的。一般格式为:化,达到多种分支的目的。一般格式为:switchswitch(整型表达式(整型表达式E E)case case 整型表达式整型表达式E1:E1:语句系列语句系列1 1;break;break;/跳过下面的所有语句直接去执行语句跳过下面的所有语句直接去执行语句k+2k+2;case case 整型表达式整型表达式E2:E2:语句系列语句系列2 2;break;break;case case 整型表达式整型表达式EkEk:语句系列语句系列k k;break;break;default:default:语句系列语句系列k+1k+1;/开关语句结束开关语句结束语句语句k+2k+2;5.5.2 选择结构(又称分支结构)注意:注意:整型表达式整型表达式E E,E1E1,E2E2,EkEk的值,是整型数据的值,是整型数据(或者(或者字符变量、字符常量)。字符变量、字符常量)。当整型表达式当整型表达式E E的值等于整型表达式的值等于整型表达式E1E1的值时,执行的值时,执行语句语句系列系列1 1;同理当整型表达式;同理当整型表达式E E的值等于整型表达式的值等于整型表达式EkEk的值时,的值时,执行语句系列执行语句系列k k。当程序执行到当程序执行到breakbreak时,将跳过下面所有的语句,执时,将跳过下面所有的语句,执行开行开关语句后的语句,即语句关语句后的语句,即语句k+2k+2。当整型表达式当整型表达式E E的值不等于整型表达式的值不等于整型表达式E1E1,E2E2,EkEk的的值时,则执行值时,则执行defaultdefault语句下的语句系列语句下的语句系列k+1k+1。5.5.2 选择结构(又称分支结构)例如,编程实现两个浮点数的四则运算函数例如,编程实现两个浮点数的四则运算函数f_arithf_arith:float float f_arith(floatf_arith(float d1,float d2,char op)d1,float d2,char op)float temp;float temp;switch(opswitch(op)case+:case+:temp=d1+d2;temp=d1+d2;break;break;/跳过下面的所有语句直接去执行跳过下面的所有语句直接去执行switchswitch语句后面的语语句后面的语句句case-:case-:temp=d1-d2;temp=d1-d2;break;break;case*:case*:temp=d1*d2;temp=d1*d2;break;break;case/:case/:temp=d1/d2;temp=d1/d2;break;break;default:default:temp=-100;temp=-100;/开关语句结束开关语句结束return temp;return temp;/函数结束函数结束5.5.3 循环结构 forfor语句语句当参加循环的语句(又称循环体),只有一条语句时,其一般格式为:当参加循环的语句(又称循环体),只有一条语句时,其一般格式为:for(E1;E2;E3)for(E1;E2;E3)1 例如:计算从例如:计算从1 1到到n n的自然数的累加和函数的自然数的累加和函数f_sumf_sum。intint f_sumf_sum(intint n)n)intint i,sum=0;i,sum=0;for(i=1;i n+1;i+)for(i=1;i n+1;i+)sum+=i;sum+=i;return sum;return sum;5.5.3 循环结构当参加循环的语句,多于一条语句时,需要用当参加循环的语句,多于一条语句时,需要用“”和和“”将循环体括起来。其一般格式为:将循环体括起来。其一般格式为:for(E1;E2;E3)for(E1;E2;E3)1 2 n 5.5.3 循环结构breakbreak语句与语句与continuecontinue语句对循环的影响语句对循环的影响breakbreak语句:语句:当某个条件满足,我们想结束循环时,采用这个语当某个条件满足,我们想结束循环时,采用这个语句。句。其一般形式为:其一般形式为:for()for()if(if(条件表达式条件表达式E)E)break;break;/离开整个循环直接跳到循环体外,执行离开整个循环直接跳到循环体外,执行 n+1.n+1 5.5.3 循环结构continuecontinue语句:语句:当某个条件满足,我们并不想结束循环,只想跳过某些循环语句当某个条件满足,我们并不想结束循环,只想跳过某些循环语句时,采用这个语句。其一般形式为:时,采用这个语句。其一般形式为:for()for()/循环起点循环起点 1if(if(条件表达式条件表达式E)E)continue;continue;/跳过跳过 2,重返循环起点,重返循环起点 2/循环终点循环终点 n+1 5.5.3 循环结构计算计算 n,n,n+kn+k 范围内的自然数中偶数的累加和(其中范围内的自然数中偶数的累加和(其中n n和和k k均为自然数)均为自然数)intint f_psumf_psum(intint n,n,intint k)k)intint sum=0;sum=0;while(n0)while(n0)/确保确保n n是自然数才计算是自然数才计算 if(k0)if(k0)/结束计算的条件,即跳出循环结束计算的条件,即跳出循环 break;break;if(n+k-)%2!=0)/if(n+k-)%2!=0)/奇数不累加,即跳过下面的语句重返循奇数不累加,即跳过下面的语句重返循环起点环起点 continue;continue;sum+=k+1+n;sum+=k+1+n;return sum;return sum;5.5.3 循环结构多重循环。在某个循环语句内还包含另一个循环语句。多重循环。在某个循环语句内还包含另一个循环语句。C+C+中称为中称为多重循环(或循环嵌套)。其一般格式为:多重循环(或循环嵌套)。其一般格式为:for(E1;E2;E3)for(E1;E2;E3)/外循环语句起点外循环语句起点 1/外循环体语句系列外循环体语句系列 2for(E11;E22;E33)for(E11;E22;E33)/内循环语句起点内循环语句起点 1 /内循环体语句系列内循环体语句系列 2 n /内循环语句终点内循环语句终点 n /外循环语句终点外循环语句终点5.5.3 循环结构 while while语句一般格式为:语句一般格式为:while(while()5.5.3 循环结构 dowhile dowhile语句一般格式为:语句一般格式为:do do while(while(););5.5.3 循环结构注意:注意:循环语句的形式比较多,要根据需要合理选用。循环语句的形式比较多,要根据需要合理选用。while while和和dowhiledowhile型循环语句,同样可以实现多层型循环语句,同样可以实现多层嵌。嵌。break break和和continuecontinue语句均可使用于语句均可使用于whilewhile和和dowhiledowhile语句,语句,但但是,它们仅作用于本层循环上,在任何一层上要实现是,它们仅作用于本层循环上,在任何一层上要实现breakbreak和和continuecontinue的操作,都必须在这一层中增加这两条语句。的操作,都必须在这一层中增加这两条语句。在书写时,不要忘记在书写时,不要忘记dowhiledowhile语句中最后的语句中最后的“;”;”。建议养成良好的编程习惯,不要在循环体内说明数建议养成良好的编程习惯,不要在循环体内说明数据据成员或者函数的原型,如:成员或者函数的原型,如:intint num;num;或者或者char*char*funcfunc(intint a,a,char*s);char*s);类似的声明应在循环体外。类似的声明应在循环体外。5.5.4 递归函数的自我调用 所谓所谓“递归递归”是指通过重复执行相同的计算来解是指通过重复执行相同的计算来解决问题。决问题。简单的说,递归就是函数直接或间接地自己调用自己。从而简单的说,递归就是函数直接或间接地自己调用自己。从而使得程序简短。编写递归程序的关键是:使得程序简短。编写递归程序的关键是:(1)(1)构造递归表达式。构造递归表达式。将将n n阶的问题转化为比阶的问题转化为比n n阶小的问题,阶小的问题,转化以后的问题与原来的问题的解法是相同的。转化以后的问题与原来的问题的解法是相同的。(2)(2)必须寻找一个明确的递归结束条件,称为递归出口。必须寻找一个明确的递归结束条件,称为递归出口。递归是在函数中出现调用函数本身的语句,只是每次调递归是在函数中出现调用函数本身的语句,只是每次调用时函数的实参值不一样,如果代码中没有包含终止调用时函数的实参值不一样,如果代码中没有包含终止调用的控制语句,将无限循环下去。因此,通常用用的控制语句,将无限循环下去。因此,通常用ifif语句语句中条件的判断来决定是否跳出这个递归过程。中条件的判断来决定是否跳出这个递归过程。#include#include#include#include intint f(intf(int x)x)intint y;y;if(xif(x=0|x=1)=0|x=1)return 3;return 3;y=x-f(x-2);y=x-f(x-2);return y;return y;void main()void main()coutcout “f(5)=”f(5)“f(5)=”f(5)endlendl;coutcout “f(6)=”f(6)“f(6)=”f(6)endlendl;coutcout “f(8)=”f(8)“f(8)=”f(8)endlendl;运行结果为:运行结果为:f(5)=5f(5)=5f(6)=1f(6)=1f(8)=7f(8)=7请看下面一个例子:请看下面一个例子:5.5.4 递归函数的自我调用图图5.3 5.3 递归示意图递归示意图 5.5.4 递归函数的自我调用程序详解程序详解:函数从函数从main()main()开始执行,开始执行,f(5)f(5)为第一轮调用,实参为第一轮调用,实参5 5被代入被代入f(intf(int x)x),即即f(5)f(5)。函数内判断是否该返回(这是递归函数中必须要有的语句)。函数内判断是否该返回(这是递归函数中必须要有的语句)“if(xif(x=0|x=1)return 3;”=0|x=1)return 3;”之后,函数开始调用自己(这也是递归之后,函数开始调用自己(这也是递归函数函数中必须要有的语句,否则不称为递归调用)中必须要有的语句,否则不称为递归调用)y=x-f(x-2);y=x-f(x-2);(即:(即:y=5-f(3)y=5-f(3))f(3)f(3)为第二轮调用,将实参为第二轮调用,将实参3 3代入代入f(intf(int x)x),即,即f(3)f(3)。函数内判断是。函数内判断是否该返回否该返回“if(xif(x=0|x=1)return 3;”=0|x=1)return 3;”之后,函数开始调用自己之后,函数开始调用自己 y=x-f(x-2);y=x-f(x-2);即即y=3-f(1);y=3-f(1);5.5.4 递归函数的自我调用程序详解程序详解:f(1)f(1)为第三轮调用,将实参为第三轮调用,将实参1 1代入代入“f(intf(int x)”x)”,即:,即:“f(1)”f(1)”。函数内判断。函数内判断是否该返回是否该返回“if(xif(x=0|x=1)return 3;”=0|x=1)return 3;”之后,之后,即即f(1)=3f(1)=3。因此:因此:f(5)=5-f(3)=5-(3-f(1)=5-(3-3)=5f(5)=5-f(3)=5-(3-f(1)=5-(3-3)=5同理:同理:f(6)=6-f(4)=6-(4-f(2)=6-(4-(2-f(0)f(6)=6-f(4)=6-(4-f(2)=6-(4-(2-f(0)=6-(4-(2-3)=6-5=1 =6-(4-(2-3)=6-5=1类推:类推:f(8)=8-f(6)=8-1=7f(8)=8-f(6)=8-1=7注意:注意:不要忘记语句不要忘记语句“return y;”return y;”5.5.4 递归函数的自我调用5.5.4 递归注意事项注意注意:使用递归编写程序虽然代码较少,但程序的可读性较使用递归编写程序虽然代码较少,但程序的可读性较差。差。使用递归时层次不能太深,一般不超过使用递归时层次不能太深,一般不超过3 3层。多层函数层。多层函数递递归将造成系统资源的严重浪费。归将造成系统资源的严重浪费。由于递归的缺点很明显,所以在实际开发工作中不建由于递归的缺点很明显,所以在实际开发工作中不建议议使用递归。使用递归。5.6函数的参数的传递机制 当一个函数定义有形参时,在进行函数调用时,当一个函数定义有形参时,在进行函数调用时,必须必须提供与形参个数相同、顺序相同、类型相同的实参;或提供与形参个数相同、顺序相同、类型相同的实参;或通过类型转换能够将实参的值映射为形参类型的值。通过类型转换能够将实参的值映射为形参类型的值。在在C C中,可以使用两种传递机制将实参的值传中,可以使用两种传递机制将实参的值传递递给形参:给形参:一种被称为一种被称为值传递值传递 (值调用)。(值调用)。另一种被称为另一种被称为引用传递引用传递(引用调用)。(引用调用)。5.6.1传值调用C+C+中变量的值有两种:变量本身值和变量地址值。中变量的值有两种:变量本身值和变量地址值。1.1.传值调用的特点:传值调用的特点:调用时系统先计算实参表达式的值,然后依次赋给调用时系统先计算实参表达式的值,然后依次赋给形参。因此,传值调用的实现机制是系统将实参拷贝一形参。因此,传值调用的实现机制是系统将实参拷贝一个副本给形参。在被调用的函数中参数(即参数的副本)个副本给形参。在被调用的函数中参数(即参数的副本)被改变,但未改变实参的值(即不能被改变,但未改变实参的值(即不能“回带回带”)。)。例如:交换两个变量例如:交换两个变量a a和和 b b的值(采用传值调用)。的值(采用传值调用)。void f_swap1(void f_swap1(intint A,A,intint B)B)intint temp;temp;temp=A;temp=A;A=B;A=B;B=temp;B=temp;coutcout “A=”A”“”B=”B “A=”A”“”B=”Bendlendl;void main()void main()intint a=5,b=6;a=5,b=6;f_swap1(a,b);/f_swap1(a,b);/执行完该语句后,变量的值没有执行完该语句后,变量的值没有改变改变coutcout “a=”a“”“b=”b “a=”a“”“b=”bendlendl;运行结果如下:运行结果如下:A=6A=6B=5 /B=5 /函数内的结果函数内的结果a=5a=5b=6 /b=6 /主函数中的结果,可见通过传值调用主函数中的结果,可见通过传值调用a a、b b的的 /值并没有被值并没有被“回带回带”5.6.1传值调用5.6.1传值调用2.2.传址调用的特点传址调用的特点 使用传址调用方式时,调用函数的实参是某个变量的地址值,使用传址调用方式时,调用函数的实参是某个变量的地址值,被被调用的函数的形参是指针(变量的指针或类类型的变量的指针)。调用的函数的形参是指针(变量的指针或类类型的变量的指针)。千千万注意,不能通过万注意,不能通过returnreturn返回或者通过参数返回或者通过参数“回带回带”,在函数中,在函数中定义的局部变量的地址(或指针)定义的局部变量的地址(或指针)。例如,通过函数返回、指针参数和引用参数来得到函数中局部变量的例如,通过函数返回、指针参数和引用参数来得到函数中局部变量的值。下面的做法结果是错误的:值。下面的做法结果是错误的:intint*f_pIntandInt(intf_pIntandInt(int*y,*y,intint&x)&x)intint a=5;a=5;intint*s=&a;*s=&a;y=s;/y=&a;y=s;/y=&a;x=a;x=a;return s;return s;void main()void main()intint a=6,b=7;a=6,b=7;intint*pa=&a;*pa=&a;intint*x=*x=f_pIntandInt(pa,bf_pIntandInt(pa,b););/执行完该语句后,变量的值执行完该语句后,变量的值将被改变将被改变coutcout”*x=“*x”*x=“*xendlendl;coutcout”*pa=”*pa”*pa=”*paendlendl;coutcout”b=”b”b=”bendlendl;运行结果如下:运行结果如下:*x=351x=351/*x/*x不是不是5 5而是个随机数而是个随机数*pa=6 pa=6/*pa/*pa也不是也不是5 5且未被修改且未被修改 b=5 b=5/“回带回带”了值了值5 55.6.1传值调用5.6.2引用调用 使用引用作为函数的形参时,调用函数的实使用引用作为函数的形参时,调用函数的实参要参要用变量名用变量名,将实参的变量名传给形参的引用,相当于,将实参的变量名传给形参的引用,相当于在被调用函数中使用了实参的别名。在被调用函数中使用了实参的别名。例如:交换两个变量例如:交换两个变量a a和和 b b的值。(采用引用调用)的值。(采用引用调用)void f_swap3(void f_swap3(intint&A,&A,intint&B)&B)intint temp;temp;temp=A;temp=A;A=B;A=B;/交换两个引用变量中的内容(改变实参值)交换两个引用变量中的内容(改变实参值)B=temp;B=temp;coutcout “A=”A”“”B=”B “A=”A”“”B=”Bendlendl;void main()void main()intint a=5,b=6;a=5,b=6;f_swap3(a,b);/f_swap3(a,b);/变量的地址没变,但是变量的值被间接改变量的地址没变,但是变量的值被间接改变变coutcout “a=”a”“”b=”b “a=”a”“”b=”bendlendl;运行结果如下:运行结果如下:A=6 B=5 A=6 B=5 /函数内的结果函数内的结果a=6 b=5 a=6 b=5 /主函数中的结果,可见引用调用主函数中的结果,可见引用调用a a、b b的值被的值被“回带回带”建议:在需要建议:在需要“回带回带”值的时候,使用引用值的时候,使用引用。5.6.2引用调用5.7 函数的参数 5.7.1 函数参数的求值顺序 当一个函数带有多个参数时,当一个函数带有多个参数时,C C语言没有规定语言没有规定在函在函数调用时对实参的求值的顺序,数调用时对实参的求值的顺序,编译器根据对代码进行优编译器根据对代码进行优化的需要自行决定对实参的求值顺序化的需要自行决定对实参的求值顺序。有的编译器规定自。有的编译器规定自左向右,有的编译器规定自右向左,这种求值顺序的不左向右,有的编译器规定自右向左,这种求值顺序的不同,对一般参数来讲没有影响。但是,同,对一般参数来讲没有影响。但是,如果实参表达式中如果实参表达式中的某个变量与前后表达式中的某个变量有关时,就可能由的某个变量与前后表达式中的某个变量有关时,就可能由于求值顺序的不同而造成了二义性于求值顺序的不同而造成了二义性。因此,。因此,建议将参数列建议将参数列表简单化为好(相关运算放在调用前)表简单化为好(相关运算放在调用前)。(举例如下)。(举例如下)intint f_add_intf_add_int(intint x,x,intint y,y,intint z)z)return x+y+z;return x+y+z;void main()void main()intint x=5,y=6,z=7,c;x=5,y=6,z=7,c;c=c=f_add_intf_add_int(+x,(+x,x+y+zx+y+z,-z);,-z);如果编译器规定自左向右的求值,则如果编译器规定自左向右的求值,则 c=c=f_add_intf_add_int(6,6+6+7,6),c=31;(6,6+6+7,6),c=31;如果编译器规定自右向左的求值,则如果编译器规定自右向左的求值,则c=c=f_add_intf_add_int(6,5+6+6,6),c=29;(6,5+6+6,6),c=29;5.7.1 函数参数的求值顺序5.7.2数组作为函数参数数组作为函数参数时,根据调用机制的不同,可以分为两种情况:数组作为函数参数时,根据调用机制的不同,可以分为两种情况:形参用数组实参用数组名形参用数组实参用数组名 调用函数的实参用数组名,被调用的函数的形参用数组,这调用函数的实参用数组名,被调用的函数的形参用数组,这种调用的机制是形参和实参共用内存中的同一个数组。种调用的机制是形参和实参共用内存中的同一个数组。例如:检查数组例如:检查数组AmAm,将数组中小于,将数组中小于0 0的数改写为的数改写为0 0;void void f_rw1(f_rw1(intint A A,intint n n)/定定义义时时形形参参要要标标明明数数组组元元素素的的类类型型、数数组组名名、数数组组维数维数 for(intfor(int i=0;i i=0;in;in;i+)+)if(Aif(A i 0)i 0)A i=0;A i=0;void main()void main()intint a4=1,-5,4,-3;a4=1,-5,4,-3;intint n=4;n=4;f_rw1(a,4);f_rw1(a,4);/调用时实参只写数组名调用时实参只写数组名 结果是结果是a a中的元素变为:中的元素变为:1 1,0 0,4 4,0 05.7.2数组作为函数参数5.7.25.7.2数组作为函数参数数组作为函数参数形参用指针实参用数组名形参用指针实参用数组名 调用函数的实参用数组名,被调用的函数的形参用指调用函数的实参用数组名,被调用的函数的形参用指针,这种调用的机制是实参把数组的名字传递给形参。针,这种调用的机制是实参把数组的名字传递给形参。例如:检查数组例如:检查数组AmAm,将数组中小于,将数组中小于0 0的数改写为的数改写为0 0;void f_rw2(void f_rw2(intint*A,*A,intint n)n)/形参用指针形参用指针 for(intfor(int i=0;i i=0;in;in;i+)+)if(*(A+i)0)if(*(A+i)0)*(A+i*(A+i)=0;=0;void main()void main()intint a4=1,-5,4,-3;a4=1,-5,4,-3;intint n=4;n=4;f_rw2(a,4);f_rw2(a,4);/调用时实参只写数组名调用时实参只写数组名 5.7.3带缺省值的函数 C+C+语言允许语言允许在函数的原型中在函数的原型中
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!