




已阅读5页,还剩156页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+高级语言程序设计,第5章 函数 北京邮电大学信息与通信工程学院,程序设计中,把具有一定功能的程序模块用函数或类来实现。,2019/6/6,北京邮电大学信息与通信工程学院,-2-,第5章 函数,内容 函数定义、声明、函数的调用、函数参数传递机制 函数的特殊形式,包括递归函数、内联函数、带默认参数值的函数 标识符的作用域和可见性 变量的存储类型和生存期,2019/6/6,北京邮电大学信息与通信工程学院,-3-,5.1 函数概述,结构化程序设计,将整个程序自顶向下分为若干个程序模块,每个模块用来实现一个特定的功能。 C + 中的模块以函数和类的形式实现。 函数是具有一定功能又经常使用的相对独立代码段。 无论是面向过程的程序设计还是面向对象的程序设计,函数都是一种实现算法的重要形式。,2019/6/6,北京邮电大学信息与通信工程学院,-4-,5.1 函数概述,函数 接口(规定接口形式) 函数名(命名规则与变量相同,见名知意) 函数类型(返回值类型) 形式参数表 函数体(实现算法三种基本结构组合而成) 常用的函数 C+的库函数 自定义的函数,2019/6/6,北京邮电大学信息与通信工程学院,-5-,5.1.1 自定义函数概述,编程者在处理具体问题时,将程序中多处使用的、实现一定功能的特定代码段定义成函数。这样的函数称为自定义函数。 在同一个程序中,一个函数只能定义一次。 一般是通过函数调用来使用函数。 函数调用需要指定函数名并且提供被调用函数所需的信息(即函数参数)。,2019/6/6,北京邮电大学信息与通信工程学院,-6-,5.1.1 自定义函数概述,例如要打印某一年某一月的月历,2019/6/6,北京邮电大学信息与通信工程学院,-7-,5.1.2 库函数概述,C+ 标准库提供了丰富的函数集合,可以进行常用的数学计算、字符串操作、字符操作、输入/输出、错误检查和许多其他操作。 要熟悉C+ 标准库提供的类和函数集合,不要事事从头做起,要尽可能利用C+ 标准库提供的函数,以便减少程序开发的时间。这是程序设计的技巧之一。,2019/6/6,北京邮电大学信息与通信工程学院,-8-,5.1.2 库函数概述,数学库函数 实现常见的数学计算 使用时,在程序中嵌入cmath头文件,按对应库函数的接口形式写调用语句。 调用数学函数: 函数名(参数1,参数n) 例如: double x; x=sqrt(900.0); coutx; 数学函数库中的多数函数都返回double类型结果。,2019/6/6,北京邮电大学信息与通信工程学院,-9-,2019/6/6,北京邮电大学信息与通信工程学院,-10-,常用数学库函数,2019/6/6,北京邮电大学信息与通信工程学院,-11-,#include #include using namespace std; int main() cout a b c; if ( (a != 0) ,调用函数 或主调函数,被调函数,库函数,2019/6/6,北京邮电大学信息与通信工程学院,-12-,#include using namespace std; float CircleArea(float r); int main() / manage circle computation cout MyRadius; float Area = CircleArea(MyRadius); cout “Circle has area “ Area; return 0; / CircleArea(): compute area of radius r circle float CircleArea(float r) const float Pi = 3.1415; return Pi * r * r; ,自定义函数,5.2 函数定义及使用,2019/6/6,北京邮电大学信息与通信工程学院,-13-,一个C+控制台程序可以由一个主函数(main()函数)和若干子函数构成。 主函数main()是程序执行的开始点,由主函数调用子函数,子函数还可以再调用其他子函数。 调用其他函数的函数被称为主调函数。 被其他函数调用的函数称为被调函数。 一个函数既可以是主调函数,又可以是被调函数(main()除外)。,5.2.1 函数的定义,每一个函数都是一个具有一定功能的语句模块,函数定义的语法形式: 返回值类型 函数名(形式参数表) 函数体(变量声明和执行语句) ,2019/6/6,北京邮电大学信息与通信工程学院,-14-,约定接口 形式,函数体完 成功能,int maximum(int x, int y) int maxv; maxv=x=y?x:y; return maxv; ,2019/6/6,北京邮电大学信息与通信工程学院,-15-,float CircleArea (float r) const float Pi = 3.1415; return Pi * r * r; ,5.2.1 函数的定义,函数体,返回值语句,局部变量定义,形式参数,函数类型,函数名,5.2.1 函数的定义,函数名是函数体代码段的外部标识符 函数定义之后,即可通过函数名调用函数。 例: / Sum(): compute sum of integers in a . b int Sum(int a, int b) int Total = 0; for (int i = a; i = b; +i) Total += i; return Total; ,2019/6/6,北京邮电大学信息与通信工程学院,-16-,5.2.1 函数的定义,函数的形式参数表,简称形参表 形式: (类型1 形式参数1,类型n 形式参数n),2019/6/6,北京邮电大学信息与通信工程学院,-17-,/ Sum(): compute sum of integers in a . b int Sum(int a, int b) int Total = 0; for (int i = a; i = b; +i) Total += i; return Total; ,形式参数表示主调函数和被调函数之间需要交换的信息 (1)传给被调函数的待处理的数据; (2)控制被调函数执行操作的信息; (3)被调函数执行的结果。 形式参数表从参数的类型、个数、排列顺序上规定了主调函数和被调函数之间信息交换的形式。 float func(int k, int b, float x) return k*x+b; ,2019/6/6,北京邮电大学信息与通信工程学院,-18-,5.2.1 函数的定义,如果函数之间没有需要交换的信息,也可以没有形参,形参表内写void或空着。 int Read() cout Response; return Response; ,2019/6/6,北京邮电大学信息与通信工程学院,-19-,5.2.1 函数的定义,5.2.1 函数的定义,函数体是实现函数功能的代码部分 变量声明 完成函数功能的语句两部分 从组成结构看,函数体是由程序的三种基本控制结构即顺序、选择、循环结构组合而成的。,2019/6/6,北京邮电大学信息与通信工程学院,-20-,int Sum(int a, int b) int Total = 0; for (int i = a; i = b; +i) Total += i; return Total; ,2019/6/6,北京邮电大学信息与通信工程学院,-21-,函数是由函数名、函数类型、形参表 和函数体四部分组成的,使用时通过 函数名和参数表调用函数.,例: 编写一个函数cube,计算整数的立方。调用函数cube计算从1到10相邻整数的立方差。,2019/6/6,北京邮电大学信息与通信工程学院,-22-,尽可能避免在循环体内调用函数!,/计算整数的立方 #include using namespace std; int cube( int ); / 函数原型声明 void main() int last, cb; last=1; cout “the difference of cube: “endl; for ( int x = 2; x = 10; x+ ) cb=cube( x ); cout cb-last “ “; last=cb; cout endl; ,/函数定义 int cube( int y ) return y*y*y; ,2019/6/6,北京邮电大学信息与通信工程学院,-23-,/ 在三个浮点中找出最大值 #include using namespace std; float maximum(float x, float y, float z); / 函数原型声明 void main() float a, b, c; cout a b c; /调用maximum函数,a,b,c为实际参数 cout “Maximum is: “ maximum( a, b, c ) endl; /函数调用 ,例: 在三个浮点中确定最大值,使用自定义函数maximum完成。,2019/6/6,北京邮电大学信息与通信工程学院,-24-,/ maximum函数定义 / 函数的形式参数x,y ,z float maximum(float x, float y, float z) float max; max = x=y?x:y; max = max=z?max:z; return max; ,5.2.1 函数的定义,注意 如果没有函数原型声明,要先写函数定义,后调用函数。 C + 语言不允许函数嵌套定义,所有函数的定义都是自成一体,即函数体中只包含实现其自身功能的基本语句,不可包含其他函数的定义体。,2019/6/6,北京邮电大学信息与通信工程学院,-25-,5.2.2 函数原型,引用函数之前,要先指定函数的接口形式 函数原型 函数定义 函数原型声明格式: 函数类型 函数名(形式参数表); 例: int Max(int a, int b); 函数原型声明使编译器获得关于函数名称、函数类型、函数形参个数、形参类型和形参顺序的信息。 函数调用时,编译器根据函数原型声明验证函数调用正确与否。,2019/6/6,北京邮电大学信息与通信工程学院,-26-,5.2.2 函数原型,程序中,如果调用自定义的函数,且函数定义在后,调用在先,则必须在调用函数之前有函数原型声明。 void subfun1(int x, float a, float b);/原型声明 main() int x = 20; float a=1.0f, b=0.5f; subfun1();/函数调用 void subfun1(int x, float a, float b)/函数定义 ,2019/6/6,北京邮电大学信息与通信工程学院,-27-,5.2.2 函数原型,如果是函数定义在先,调用在后,则不必进行函数原型声明。因为编译器已经从函数定义得到关于函数的信息。 void subfun1(int x, float a, float b)/函数定义 main() subfun1(i, f1, f2);/函数调用 ,2019/6/6,北京邮电大学信息与通信工程学院,-28-,5.2.2 函数原型,源文件中,如果在所有函数定义体之外声明函数原型,则该函数可被位于其原型声明之后的所有函数调用。,2019/6/6,北京邮电大学信息与通信工程学院,-29-,void subfun1();/原型声明 main() subfun1();/函数调用 void subfun2() subfun1();/函数调用 void subfun1()/函数定义 ,main() void subfun1();/函数原型声明 subfun1();/函数调用 void subfun2() subfun1();/函数调用, void subfun1() ,2019/6/6,北京邮电大学信息与通信工程学院,-30-,错误,编译器不识别sunfun1标识符。,5.2.2 函数原型,库函数的声明在相应库的头文件中,使用库函数时要包含对应的头文件。 例: #include 调用数学库函数: sqrt() sin() abs() ,2019/6/6,北京邮电大学信息与通信工程学院,-31-,2019/6/6,北京邮电大学信息与通信工程学院,-32-,常用C+ 标准库头文件 cassert包含增加诊断以帮助程序调试的宏和信息 cctype 包含测试某些字符属性的函数原型和将小写字母变为 大写字母、将大写字母变为小写字母的函数原型 cmath 包含数学库函数的函数原型 cstdio 包含标准输入/输出库函数的函数原型及其使用的信息 cstdlib 包含将数字变为文本、将文本变为数字、内存分配、 随机数和各种其他工具函数的函数原型 cstring 包含C语言方式的字符串处理函数原型 ctime 包含操作时间和日期的函数原型和类型 iostream 包含标准输入/输出函数原型 iomanip 包含能够格式化数据流的流操纵运算子的函数原型 fstream 包含和磁盘文件读/写有关的函数原型,5.2.2 函数原型,例5-2 计算3个整数绝对值的平均值。,2019/6/6,北京邮电大学信息与通信工程学院,-33-,2019/6/6,北京邮电大学信息与通信工程学院,-34-,/例5-2 计算3个数绝对值的平均值 #include #include using namespace std; int CalAbsMean(int a, int b, int c); /自定义函数的原型声明 void main() int a, b, c; coutabc; cout“绝对值的均值为:“CalAbsMean(a, b, c)endl; int CalAbsMean(int a, int b, int c) int sum = abs(a) + abs(b) + abs(c); sum /= 3; return sum; ,运行结果: 输入 a,b,c: -10 20 -30 绝对值的均值为:20,5.2.3 return语句,return语句使程序执行流程从被调函数返回主调函数,有两种形式: (1) 不返回值的形式 return; (2) 返回值的形式 return 表达式;,2019/6/6,北京邮电大学信息与通信工程学院,-35-,int Sum(int a, int b) int Total = 0; for (int i = a; i = b; +i) Total += i; return Total; ,void DisplayMessage () cout“只显示确定信息的简单函数不带参数“endl; return; ,函数返回值类型规定了函数返回给主调函数的值的类型,也称为函数类型。 当被调函数只需要把一个数值结果返回给主调函数时,使用return语句返回比较合适。 由return语句返回的值的类型必须与函数返回值类型一致。 若表达式的结果与函数类型不一致,不能通过编译,需要作强制类型转换,将表达式的类型强制成与函数类型。 例如,如果mean是float型,而函数是int型,则return语句应为: return (int)mean;,2019/6/6,北京邮电大学信息与通信工程学院,-36-,int Sum(int a, int b) int Total = 0; for (int i = a; i = b; +i) Total += i; return Total; ,5.2.3 return语句,5.2.3 return语句,注意 如果不需要向主调函数返回值,函数可以定义成无类型的,函数类型写成void,函数结束时也不必用return语句。 例: void display() cout“no return”endl; ,2019/6/6,北京邮电大学信息与通信工程学院,-37-,5.2.3 return语句,例5-3 根据输入的颜色符号,显示不同的字符串表示的不同颜色。,2019/6/6,北京邮电大学信息与通信工程学院,-38-,2019/6/6,北京邮电大学信息与通信工程学院,-39-,/例5-3 根据输入的颜色符号,显示不同的字符串表示的不同颜色 #include using namespace std; void DispColor (char color); void main() char color; coutcolor; DispColor (color); ,2019/6/6,北京邮电大学信息与通信工程学院,-40-,/根据输入,显示颜色字符串 void DispColor (char color) switch(color) case r: cout“red. “; break; case g: cout“green. “; break; case b: cout“blue“; break; default: break; return; ,5.2.3 return语句,例5-4 从输入文件中读入学生人数和每人考试成绩,统计成绩的平均值。,2019/6/6,北京邮电大学信息与通信工程学院,-41-,2019/6/6,北京邮电大学信息与通信工程学院,-42-,/例5-4.从输入文件中读入学生人数和每人考试成绩,统计成绩均值。 #include #include using namespace std; int CalMean(char chFileName); /函数原型声明 void main() char chFileName80=“; cout chFileName; /输入文件名 int mean=ChlMean(chFileName); /得到平均值 cout“平均值=“ meanendl; ,2019/6/6,北京邮电大学信息与通信工程学院,-43-,/计算均值,函数定义如下 int CalMean(char chFileName) int count; /数据个数 int score; /分数 int sum(0), mean; ifstream infile(chFileName); if(!infile) coutscore)/从文件读取成绩,并累计总成绩; cout0) mean=sum/count; /计算平均值 else mean=0; return mean;/将平均值返回主调函数 ,运行结果: 成绩个数:10 成绩: 59 39 24 36 87 98 52 67 52 60 平均值=57,5.2.4 函数调用方式,函数语句 函数语句形式: 函数名(实参数表); TriAreabySide(a, b, c); 函数表达式 函数调用出现在表达式中,形式:函数名(实际参数表) x=max(a,b); y=sqrt(x); 此时函数要使用return语句向主调函数返回一个确定的值,参与它所在的表达式的运算。 float max(float a,float b) return a=b?a:b; 函数参数 函数参数调用方式是将函数调用写在另一次函数调用的实际参数位置。例如: m=max(a,max(b, c);,2019/6/6,北京邮电大学信息与通信工程学院,-44-,5.2.4 函数调用方式,实际参数表可简称为实参表,是按与被调函数形式参数表一一对应的格式组织的参数表,即参数的类型、个数和排列顺序必须与被调函数声明的形式参数表严格一致。 实际参数表的各实际参数以逗号间隔,实际参数可以是常量、变量或表达式,变量和表达式必须具有确定值。 如果被调函数无形式参数,则实参表也是空的。 实际编程中,从可读性考虑,一般使用变量作为实际参数。,2019/6/6,北京邮电大学信息与通信工程学院,-45-,例: 计算y=kx+b的函数 float func(int k,int b,float x) return k*x+b; void main() int k,b; float x,y; cinkbx; y=func(k,b,x); ,例:找最高分数 int FindMaxValue(int array, int n) int maxValue = array0; for(int k=1; k maxValue ) maxValue = arrayk; return maxValue; void main() int score30, num=30; for(int k=0; kscorek; int maxScore = FindMaxScore(score, num); coutmaxScoreendl; ,2019/6/6,北京邮电大学信息与通信工程学院,-46-,实际参数以数据值(值传递)或实际存储空间(地址传递)提供了形式参数所需的内容。,#include using namespace std; void DisplayMessage(); void main() DisplayMessage (); /函数调用语句 void DisplayMessage () cout“只显示确定信息的简单函数不带参数“endl; ,2019/6/6,北京邮电大学信息与通信工程学院,-47-,如果被调函数无形参,则实参表也是空的。,5.2.4 函数调用方式,5.2.4 函数调用方式,例5-5 编写程序,实现坐标旋转公式:,2019/6/6,北京邮电大学信息与通信工程学院,-48-,2019/6/6,北京邮电大学信息与通信工程学院,-49-,/实现坐标旋转公式 #include #include using namespace std; void main() const double PI=3.14; int x,y;/旋转后坐标 int x0,y0;/原始坐标 int angle; /旋转角度 /输入数据 cout“input point(x,y):“;,cinx0y0; coutangle; /计算旋转后的坐标 double theta=angle*PI/180; x=x0*cos(theta)-y0*sin(theta); y=x0*sin(theta)+y0*cos(theta); /输出结果 cout“x=“xendl; cout“y=“yendl; ,5.3 函数调用的执行机制和参数传递方式,函数调用过程是如何实现的? 程序执行流程能够从主调函数到被调函数,再由被调函数正确返回主调函数的断点继续执行,是基于函数调用工作栈来实现的。 函数的参数传递方式 值传递 地址传递,2019/6/6,北京邮电大学信息与通信工程学院,-50-,5.3.1 函数调用的执行机制,栈是函数调用正确执行的物理基础. 栈是一种数据结构,它的工作原理就像在子弹匣压子弹一样,最先压入的子弹要等到最后才飞射出去,而最后压入的子弹则首先飞射出去。,2019/6/6,北京邮电大学信息与通信工程学院,-51-,00401056 00401057 00401058 00401059 0040105A 0040106B,A,B,C,D,栈的管理原则: 先进后出 或 后进先出,5.3.1 函数调用的执行机制,函数调用能够正确执行的物理基础是操作系统在内存中开辟了一块叫做栈的内存空间。 断点 工作记录 断点地址 被调函数的形式参数 自动局部变量,2019/6/6,北京邮电大学信息与通信工程学院,-52-,5.3.1 函数调用的执行机制,例5-6 从键盘输入屏幕上两点的坐标(x, y),计算两点之间的距离。 (分析函数调用时活动记录 ),2019/6/6,北京邮电大学信息与通信工程学院,-53-,2019/6/6,北京邮电大学信息与通信工程学院,-54-,void main() int x1,y1,x2,y2;/两点坐标 float dist; /两点间距离 coutx1y1; coutx2y2; dist=CalDistance(x1,y1,x2,y2); cout“distance between point (“x1“,“y1“) and point (“x2“,“y2“): “distendl; ,栈,仅一个工作记录,活动工作记录,2019/6/6,北京邮电大学信息与通信工程学院,-55-,/计算距离 float CalDistance(int xx1, int yy1, int xx2, int yy2) int dx,dy; dx=xx2-xx1; dy=yy2-yy1; float dist=sqrt(dx*dx+dy*dy); return dist; ,栈,工作记录示意,工作记录,活动工作记录,5.3.2 函数的参数传递方式,函数之间的信息交换的一种重要形式是函数的参数传递,由函数的形式参数和实际参数实现。 函数在没有被调用时,函数的形式参数并不占有实际的内存空间,也没有实际的值。C+语言中函数的参数传递方式分为两种: 值传递 地址传递,2019/6/6,北京邮电大学信息与通信工程学院,-56-,2019/6/6,北京邮电大学信息与通信工程学院,-57-,值传递,如果函数的形式参数为普通变量,当函数被调用时,系统为这些形式参数分配内存空间,并用实际参数值初始化对应的形式参数,形式上实际参数的值传递给了形式参数。这就是函数调用时参数的值传递。,值传递方式,实际参数和形式参数各自占有自己的内存空间;参数传递方向只能由实际参数到形式参数;不论函数对形式参数作任何修改,对相应的实际参数都没有影响。,5.3.2 函数的参数传递方式,5.3.2 函数的参数传递方式,例5-7 从键盘输入两整数,交换次序后输出。,2019/6/6,北京邮电大学信息与通信工程学院,-58-,2019/6/6,北京邮电大学信息与通信工程学院,-59-,/演示函数参数值传递单向性的例程 #include void swap(int a, int b); int main() int x(5), y(10); cout“x=“x“ y=“yendl; swap(x,y); cout“x=“x“ y=“yendl; return 0; ,5,10,x,y,1024,1028,运行结果: x=5 y=10 x=5 y=10,2019/6/6,北京邮电大学信息与通信工程学院,-60-,void swap(int a, int b) int t; t=a; a=b; b=t; ,5,a,2048,10,b,2052,t,2056,5,10,5,编程技巧: 交换两个变量的值,需要引入第三个变量缓存数据。,例,如果一个数的所有真因子(包括1,但不包括这个数本身)之和正好等于这个数本身,则称此数为完美数。例如: 6=123,而 1+2+3=6; 28=147=1214, 而 1+2+4+7+14=28。 如何确定完美数,欧几里得发现,只要 是一个素数,则 一定是一个完美数。编写程序找出最小的5个完美数。,2019/6/6,北京邮电大学信息与通信工程学院,-61-,体会函数参数的值传递,2019/6/6,北京邮电大学信息与通信工程学院,-62-,/寻找最小的五个完美数 #include #include using namespace std; bool DecidePrime(unsigned int number); unsigned int power(unsigned int x, unsigned int y); void main() unsigned int perfect_number; unsigned int num,temp; short n(2); short counter(0);/计数器,2019/6/6,北京邮电大学信息与通信工程学院,-63-,while (counter5) temp=power(2,n); num=temp-1; if(DecidePrime(num) perfect_number=temp/2*num; cout“n=“n“,“perfect number=“perfect_numberendl; counter+; n+; ,2019/6/6,北京邮电大学信息与通信工程学院,-64-,/计算指数 unsigned int power(unsigned int x, unsigned int y) unsigned int mul(1); for(int i=1;i=y;i+) mul*=x; return mul; ,2019/6/6,北京邮电大学信息与通信工程学院,-65-,/判别素数 bool DecidePrime(unsigned int number) unsigned int i, k; k=sqrt(number); for(i=2; i=k+1) /判断number是否被小于number的数整除 return true; else return false; ,5.3.2 函数的参数传递方式,地址传递 地址变量做形参 数组名 指针变量 引用,2019/6/6,北京邮电大学信息与通信工程学院,-66-,5.3.2 函数的参数传递方式,冒泡排序 int array5 = 5,4,3,2,1;,2019/6/6,北京邮电大学信息与通信工程学院,-67-,5.3.2 函数的参数传递方式,例5-9 用整型数组存储数据,编写冒泡排序函数BubbleSort(),在主调函数中用随机数产生函数生成数组元素,并输出排序的结果。,2019/6/6,北京邮电大学信息与通信工程学院,-68-,2019/6/6,北京邮电大学信息与通信工程学院,-69-,/例5-9 基于数组的冒泡排序例 #include #include using namespace std; void BubbleSort (int array,int n); /函数原型声明,2019/6/6,北京邮电大学信息与通信工程学院,-70-,void main() const int N = 20; int arrayN = 0; srand(unsigned int)time(NULL); int k; cout“待排序数据:“endl; for(k=0; kN; k+) /数据生成 arrayk = rand()%100; cout arrayk “,“; BubbleSort (array, N); /调用排序函数 cout endl“排序后数据:“endl; for(k=0; kN; k+) /数据生成 cout arrayk “,“; coutendl; ,2019/6/6,北京邮电大学信息与通信工程学院,-71-,/冒泡排序 void BubbleSort (int a,int n) int temp; for(int pass=1; passak+1) temp=ak; ak=ak+1; ak+1=temp; ,运行结果: 待排序数据: 37,99,56,87,48,96,71,88,63,44,34,21,59,0,36,92,53,25,4,20 排序后数据: 0,4,20,21,25,34,36,37,44,48,53,56,59,63,71,87,88,92,96,99,注意,(1)数组名作为形式参数,只将数组的起始地址传递给了被调函数,数组的大小需要单独通过值传递的方式传给被调函数。例5-9中的用法是一维数组名形式参数,只传一个大小即可;如果是多维数组名作为函数的形式参数,则数组的每一维的大小都需要传给被调函数。例如,定义求一个矩阵的转置矩阵的函数TransposeMatrix(),矩阵用二维数组表示,函数接口如下: void TransposeMatrix(int matrixN, int tMatrixM, int rows ,int cols );,2019/6/6,北京邮电大学信息与通信工程学院,-72-,注意,(2)多维数组名作为形式参数,只可以省略第一维(最左边)的大小,也可以不省略。在被调函数中访问这个形式上的数组时,切忌下标越界问题。,2019/6/6,北京邮电大学信息与通信工程学院,-73-,5.4 递归函数和递归调用,递归函数是函数的一种特殊形式,适合实现数学上的一些递归问题。 使用递归函数可以简单明了地表达算法(算法的可读性好),但算法的效率一般不高。,2019/6/6,北京邮电大学信息与通信工程学院,-74-,5.4.1 嵌套调用,C+的函数不能嵌套定义 C+的函数可以嵌套调用,2019/6/6,北京邮电大学信息与通信工程学院,-75-,不能嵌套定义 void main() int x,y; int sub(int a,int b) int c=a+b; ,可以嵌套调用 main() DecidePrime() sqrt() if(DecidePrime(num) k=sqrt(number);,5.4.2 递归函数和递归调用,递归函数是函数体内有调用函数自己的语句或通过其它函数间接调用函数自己的函数。 递归调用是调用递归函数而形成的一种函数调用方式。 递归函数用于实现数学中的递归问题比较直观方便。,2019/6/6,北京邮电大学信息与通信工程学院,-76-,经典递归调用问题,阶乘定义式:,2019/6/6,北京邮电大学信息与通信工程学院,-77-,2019/6/6,北京邮电大学信息与通信工程学院,-78-,#include using namespace std; int factorial( int n); void main() coutn; n_fact=factorial(n); cout“the factorial of “n“is: “n_factendl; ,返回地址1,2019/6/6,北京邮电大学信息与通信工程学院,-79-,int factorial( int n) int fn; if(n=0) fn = 1; else fn=n*factorial(n-1); return fn; ,返回地址2,栈状态,断点地址,参数,局部变量,top,top,top,top,实例演示,2019/6/6,北京邮电大学信息与通信工程学院,-80-,int factorial( int n) int fn; if(n=0) fn = 1; else fn=n*factorial(n-1); return fn; ,返回地址2,栈状态,top,top,top,top,递归问题的求解实际分成两个阶段: 化简问题的递推阶段; 达到递归终止条件得到基本情况的结果,并逐步回推结果阶段。 递归函数的主要两部分 具有更简单参数的递归调用 停止递归的终止条件(递归终止条件),2019/6/6,北京邮电大学信息与通信工程学院,-81-,例5-11,整数x和y的最大公约数是x和y能够整除的最大整数。编写一个递归函数GcommonDivisor,返回整数x和y的最大公约数。 算法:整数x和y的最大公约数的递归实现: 如果y等于0,则GcommonDivisor(x,y)为x; 否则GcommonDivisor(x,y)为GcommonDivisor(y,x%y). 其中%是求余运算符。,2019/6/6,北京邮电大学信息与通信工程学院,-82-,理解递归问题,2019/6/6,北京邮电大学信息与通信工程学院,-83-,/计算x和y的最大公约数(递归函数) #include using namespace std; int GcommonDivisor(int x, int y); void main() int x,y; coutxy; cout“the greatest common divisor of “x“and “y“: “ GcommonDivisor(x,y)endl; ,地址1,2019/6/6,北京邮电大学信息与通信工程学院,-84-,int GcommonDivisor(int x, int y) int gcd; if (y=0) gcd=x; else gcd=GcommonDivisor(y, x%y); return gcd; ,以输入10,8为例,地址2,问题:用循环能实现吗?(作业),5.5 内 联 函 数,函数调用时,系统首先要保存主调函数的相关信息,再将控制转入被调函数,这些操作增加了程序执行的时间开销。 C+提供的内联函数形式可以减少函数调用的额外开销(时间空间开销),特别是一些常用的短小的函数适合采用内联函数形式。,2019/6/6,北京邮电大学信息与通信工程学院,-85-,5.5 内 联 函 数,内联函数的定义形式: inline 函数类型 函数名(形式参数表) 函数体 ,2019/6/6,北京邮电大学信息与通信工程学院,-86-,5.5 内 联 函 数,例5-13 使用内联函数求三个整数中的最大值。,2019/6/6,北京邮电大学信息与通信工程学院,-87-,2019/6/6,北京邮电大学信息与通信工程学院,-88-,/内联函数例 #include using namespace std; inline int max(int x, int y, int z) return (x=y) ? (x=z ? x : z) : (y=z ? y : z); ,void main() int a,b,c; coutabc; cout“Maximum is “max(a,b,c)endl; ,(a=b) ? (a=c ? a : c) : (b=c ? b : c),2019/6/6,北京邮电大学信息与通信工程学院,-89-,内联函数之所以能够减少函数调用时的系统空间和时间开销,是因为系统在编译程序时就已经把内联函数的函数体代码插入到相应的函数调用位置,成为主调函数内的一段代码,可以直接执行,不必再转换流程控制权。 这样的结构,自然节省了时间和空间开销,但使得主调函数代码变长。 一般是只把短小的函数写成内联函数。,2019/6/6,北京邮电大学信息与通信工程学院,-90-,注意: (1)内联函数体不能包含循环语句、switch语句和异常接口声明。 (2)内联函数要先定义,后调用。因为编译器需要用内联函数的函数体代码替换对应的函数调用。 如果内联函数不符合要求,编译器就将内联函数当一般函数处理。,5.6 重 载 函 数,重载函数也是函数的一种特殊情况。 C+允许几个功能类似函数同名,但这些同名函数的形式参数必须不同,称这些同名函数为重载函数。 例: int max(int x, int y)return xy?x:y; float max(float x, float y) return xy?x:y; ,2019/6/6,北京邮电大学信息与通信工程学院,-91-,2019/6/6,北京邮电大学信息与通信工程学院,-92-,各重载函数形式参数的不同是指参数的个数、类型或顺序彼此不同,不包括参数标识符的不同。如: int max(int a, int b)return ab?a:b; int max(int x, int y)return xy?x:y; int max(int x, int y, int z) return (xy?x:y)z? (xy?x:y):z; 实际是一个函数,如果写在同一个文件中,编译时会出现编译错误。若或在同一个文件中可形成重载函数。编译器将以形式参数个数的不同来认定和区分重载函数。,2019/6/6,北京邮电大学信息与通信工程学院,-93-,#include using namespace std; int min(int x, int y) return xy?x:y; double min(double x, double y) return xy?x:y; ,void main() int ia(10),ib(20); double da(0.1), db(0.5); cout“minimum of integer . is “min(ia,ib)endl; cout“minimum of double is “min(da,db)endl; ,2019/6/6,北京邮电大学信息与通信工程学院,-94-,在使用重载函数时需要注意下面三点: 编译器不以形式参数的标识符区分重载函数。 例 int max(int a, int b); int max(int x, int y); 编译器认为这是同一个函数声明两次,编译时出错。,2019/6/6,北京邮电大学信息与通信工程学院,-95-,(2) 编译器不以函数类型区分重载函数。 float fun(int x,int y); int fun(int x,int y); 如果函数名和形式参数表相同,只是函数类型不同,编译器同样认为它们是同一个函数声明两次,编译出错。 (3)不应该将完成不同功能的函数写成重载函数,破坏程序的可读性。,2019/6/6,北京邮电大学信息与通信工程学院,-96-,重载函数常用于实现功能类似而所处理的数据类型不同的问题,5.7 默认参数值的函数,具有默认参数值的函数是一种特殊的函数形式, C+允许函数的形式参数有默认值。 例如:计算圆面积的函数: double CircleArea(double radius=1.0) const double PI=3.14; return PI*radius*radius; ,2019/6/6,北京邮电大学信息与通信工程学院,-97-,2019/6/6,北京邮电大学信息与通信工程学院,-98-,调用具有默认参数值的函数时,如果提供实际参数值,则函数的形参值取自实际参数;如果不提供实际参数值,函数的形参采用默认参数值。例如调用CircleArea函数: #include usi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 河北省任丘市2025年上半年公开招聘村务工作者试题含答案分析
- 河北省清苑县2025年上半年公开招聘村务工作者试题含答案分析
- 2025版企业员工薪酬福利管理合同
- 2025年度房地产项目代办手续专项服务与支持合同
- 2025年度豪华车队雇用与品牌推广服务合同范本
- 2025版配电箱进出口贸易合同范本解析
- 2025年度砂石资源开采与运输安全合作协议
- 2025年度土方资源开发与保护合作合同范本
- 2025标准商铺租赁合同附带商业数据分析与市场调研服务
- 2025版劳动法培训与劳动法规解读合同
- 急性胸痛患者的快速诊断与鉴别
- 部编版八年级语文下册全册教学教案
- 铝合金门窗厂财务管理制度
- 钟南山南的事迹课件
- 中建项目收费站施工方案
- 化工厂降本增效专项培训
- 企业员工居家办公管理制度
- 2024年保育师考试测试题库及答案
- 生理健康课件教学课件
- 招聘笔试题及解答(某大型央企)2025年
- DB34T∕ 2615-2016 公路沥青路面同步碎石封层施工技术规程
评论
0/150
提交评论