C++ 程序设计课件:第三章 函数

上传人:壹****1 文档编号:569567544 上传时间:2024-07-30 格式:PPT 页数:94 大小:958KB
返回 下载 相关 举报
C++ 程序设计课件:第三章 函数_第1页
第1页 / 共94页
C++ 程序设计课件:第三章 函数_第2页
第2页 / 共94页
C++ 程序设计课件:第三章 函数_第3页
第3页 / 共94页
C++ 程序设计课件:第三章 函数_第4页
第4页 / 共94页
C++ 程序设计课件:第三章 函数_第5页
第5页 / 共94页
点击查看更多>>
资源描述

《C++ 程序设计课件:第三章 函数》由会员分享,可在线阅读,更多相关《C++ 程序设计课件:第三章 函数(94页珍藏版)》请在金锄头文库上搜索。

1、 在结构化程序设计中,函数是将任务进行模块划分的基在结构化程序设计中,函数是将任务进行模块划分的基本单位。一个函数实现一项功能。本单位。一个函数实现一项功能。 在面向对象在面向对象程序设计中,程序设计中,函数是对数据的一项操作,也函数是对数据的一项操作,也是实现一项功能。是实现一项功能。第三章第三章 函数函数 要掌握函数的使用,必须理解函数调用时的内部实现机要掌握函数的使用,必须理解函数调用时的内部实现机制,以及与此相关的内存分配机制、变量生命期和作用域。制,以及与此相关的内存分配机制、变量生命期和作用域。 本章还将介绍关于函数重载的概念,介绍递归算法、本章还将介绍关于函数重载的概念,介绍递归

2、算法、内联函数、默认参数函数以及多文件组织、编译预处理、内联函数、默认参数函数以及多文件组织、编译预处理、工程文件的概念和运行库函数。工程文件的概念和运行库函数。第三章第三章 函数函数 3.1 函数的定义与调用函数的定义与调用 3. 5 作用域与标识符的可见性作用域与标识符的可见性 3.4 函数调用机制函数调用机制 3.3 全局变量和局部变量全局变量和局部变量 3.2 函数的参数传递函数的参数传递,返回值及函数声明返回值及函数声明 3.10 编译预处理编译预处理 3.9 头文件头文件与多文件结构与多文件结构 3.6 存储类型与标识符的生命期存储类型与标识符的生命期 3.8 函数的一些高级议题函

3、数的一些高级议题 3.7 函数的递归调用函数的递归调用 3.1 函数的定义与调用函数的定义与调用3.1.1 函数概述函数概述3.1.2 函数的定义函数的定义3.1.3 函数的调用函数的调用 3.1.1 函数概述函数概述函数是函数是C+C+程序的基本组成模块。程序的基本组成模块。通通过过函函数数,可可以以把把一一个个复复杂杂任任务务分分解解成成为为若若干干个易于解决的小任务。充分体现逐步细化的设计思想。个易于解决的小任务。充分体现逐步细化的设计思想。组组 成成 C+C+程程 序序 的的 若若 干干 函函 数数 中中 , 有有 一一 个个 称称 为为main()main()(WinmainWinm

4、ain()())函函数数,是是程程序序执执行行的的入入口口,它它可可以以调调用用其其他他函函数数,但但不不可可以以被被调调用用。而而其其他他一一般般函函数既可以调用也可以被调用数既可以调用也可以被调用。函数概念的引入:函数概念的引入:入口函数:入口函数:3.1.1 函数概述函数概述main ( )fun2( )fun1( )fun3( )funa( )funb( )func( )图图3.1 3.1 函数调用层次关系函数调用层次关系3.1.1 函数概述函数概述3.1.1结束结束库函数和自定义函数:库函数和自定义函数: 库函数库函数或或标准函数标准函数,是由编译系统预定义的,是由编译系统预定义的,

5、如一些常用的数学计算函数、字符串处理函数、图如一些常用的数学计算函数、字符串处理函数、图形处理函数、标准输入输出函数等。形处理函数、标准输入输出函数等。 库函数都按功能分类,集中说明在不同的头文库函数都按功能分类,集中说明在不同的头文件中件中。用户只需在自己的程序中包含某个头文件,。用户只需在自己的程序中包含某个头文件,就可直接使用该文件中定义的函数。就可直接使用该文件中定义的函数。 用户根据需要将某个具有相对独立功能的程序用户根据需要将某个具有相对独立功能的程序定义为函数,称定义为函数,称自定义函数自定义函数。3.1.2 函数的定义函数的定义无参函数定义格式为:无参函数定义格式为:数据类型数

6、据类型函数名函数名( (voidvoid)函数体函数体 说明:说明: 数数据据类类型型指指函函数数返返回回值值类类型型,可可以以是是任任一一种种数数据据类类型型, ,默默认认为为返返回回整整型型值值(但但新新标标准准要要求求写写明明,不不用用默默认认方方式式)。没有返回值应将返回值类型定义为没有返回值应将返回值类型定义为voidvoid。 函数名采用合法标识符表示。函数名采用合法标识符表示。 对对无无参参函函数数,参参数数括括号号中中的的voidvoid通通常常省省略略,但但括括号号不不能能省略。省略。 函函数数体体由由一一系系列列语语句句组组成成。函函数数体体可可以以为为空空,称称为为空空函

7、函数。数。 1 1 无参函数无参函数3.1.2 函数的定义函数的定义/打印一个表头打印一个表头void TableHead ( ) cout*endl;cout* example *endl;cout*endl;int input ( )/输入满足要求的数据输入满足要求的数据int n;cout输入一个大于输入一个大于5的整数:的整数:n;while(n=b?a:b); 有参函数的参数表中列出所有有参函数的参数表中列出所有形式参数形式参数的类型和参数名的类型和参数名称。各参数即使类型相同也必须分别加以说明。称。各参数即使类型相同也必须分别加以说明。 形式参数简称形参,形式参数简称形参,只能是变

8、量名只能是变量名,不允许是常量或表,不允许是常量或表达式。达式。 void delay(long n)int i; for (i=0;ichoice; while(choice=4); switch(choice) case 1: account_report(); break; case 2: engineering_report(); break; case 3: marketing_report(); break; return 0;void menu_print() cout”系统功能:系统功能:”endl; cout”1 财务报表财务报表”endl; cout”2 工程报表工程报表”

9、endl; cout”3 市场报表市场报表”endl; cout”选择业务序号:选择业务序号:”; void account_report() /生成财务报表生成财务报表void engineering_report() /生成工程报表生成工程报表 void marketing_report() /生成市场报表;生成市场报表;3.2.3 函数声明函数声明【例例3.4】 输输出出所所有有满满足足下下列列条条件件的的正正整整数数m:10m1000且且m、m2、m3均为回文数。均为回文数。分析:分析:回文指左右对称的序列。如回文指左右对称的序列。如121、353等就是回等就是回文数。判断整数是否回文

10、数用函数实现,其思想是将文数。判断整数是否回文数用函数实现,其思想是将该数各位拆开后反向组成新的整数,如果该整数与原该数各位拆开后反向组成新的整数,如果该整数与原数相等则为回文数。数相等则为回文数。m m*m m*m*m11 121 1331101 10201 1030301111 12321 1367631 运行结果:运行结果:3.3 全局变量和局部变量全局变量和局部变量3 33 31 1 变量的存储机制与变量的存储机制与变量的存储机制与变量的存储机制与C+C+的内存布局的内存布局的内存布局的内存布局 3 33 32 2 全局变量全局变量全局变量全局变量 3 33 33 3 局部变量局部变量

11、局部变量局部变量 3.3.1 变量的存储机制与变量的存储机制与C+的内存布局的内存布局自由存储区自由存储区 ( (动态数据动态数据) ) 操操作作系系统统为为一一个个C+C+程程序序的的运运行行所所分分配配的的内内存分为四个区域,如图存分为四个区域,如图3.33.3 所示:所示:栈区(函数局部数据)栈区(函数局部数据)全局数据区全局数据区( (全局、静态全局、静态) )代码区(程序代码)代码区(程序代码)(main()函数局部数据)函数局部数据)自由存储区自由存储区 ( (动态数据动态数据) )存储区域说明:存储区域说明:(1)代码区()代码区(Code area):存放程序代码,即程序中):

12、存放程序代码,即程序中各个函数的代码块;各个函数的代码块;(2)全局数据区()全局数据区(Data area):存放全局数据和静态):存放全局数据和静态数据;数据;分配该区时内存全部清零分配该区时内存全部清零,结果变量的所有字节,结果变量的所有字节等效初始化为全等效初始化为全。(3)栈区()栈区(Stack area):存放局部变量,如函数中):存放局部变量,如函数中的变量等;的变量等;分配栈区时不处理内存分配栈区时不处理内存,即变量取随机值。,即变量取随机值。(4)自由存储区(自由存储区(Free store area):):存放与指针相存放与指针相关的动态数据。关的动态数据。分配分配自由存

13、储自由存储区时不处理内存区时不处理内存。参见第。参见第七章。七章。3.3.1 变量的存储机制与变量的存储机制与C+的内存布局的内存布局 3.3.2 全局变量全局变量 在在所有函数之外定义的变量称为所有函数之外定义的变量称为全局变量全局变量。全全局局变变量量存存放放在在全全局局数数据据区区,因因编编译译器器自自动动将将该该区区清清为为全全0,如如果果用用户户在在定定义义时时不不显显式式给给出出初初始始化值,则化值,则等效初始化为全等效初始化为全0 。全全局局变变量量可可定定义义在在程程序序开开头头,也也可可定定义义在在中中间间位位置置,该该全全局局变变量量在在定定义义处处之之后后的的任任何何位位

14、置置都都是是可可以访问的,称为以访问的,称为可见的可见的。【例例3.5】 多个函数使用全局变量的例子。多个函数使用全局变量的例子。全局变量引入:全局变量引入:3.3.3 局部变量局部变量 定义在函数内或块内的变量称为定义在函数内或块内的变量称为局部变量局部变量。程序中使用的绝大多数变量都是局部变量。程序中使用的绝大多数变量都是局部变量。局局部部变变量量在在程程序序运运行行到到它它所所在在的的块块时时建建立立在在栈栈中中,该该块块执执行行完完毕毕局局部部变变量量占占有有的的空空间间即即被被释释放放。故故亦亦称称为为自动变量自动变量。局局部部变变量量在在定定义义时时可可加加修修饰饰词词auto,但

15、但通通常常省省略略。局部变量在定义时若未初始化,其值为局部变量在定义时若未初始化,其值为随机数随机数。局部变量引入:局部变量引入:【例例3.6】 使用局部变量的例子。使用局部变量的例子。3.4 函数调用机制函数调用机制 局局部部变变量量占占用用的的内内存存是是在在程程序序执执行行过过程程中中“动动态态”地地建建立立和释放的。这种和释放的。这种“动态动态”是通过栈由系统是通过栈由系统自动自动管理进行的。管理进行的。(1)建立栈空间;)建立栈空间;(6)恢复现场:取主调函数运行状态及返回地址,释放栈空间;)恢复现场:取主调函数运行状态及返回地址,释放栈空间;(7)继续主调函数后续语句。)继续主调函

16、数后续语句。(5)释放被调函数中局部变量占用的栈空间;)释放被调函数中局部变量占用的栈空间;(4)执行被调函数函数体;)执行被调函数函数体;(3)为被调函数中的局部变量分配空间,完成参数传递;)为被调函数中的局部变量分配空间,完成参数传递;(2)保护现场:主调函数运行状态和返回地址入栈;)保护现场:主调函数运行状态和返回地址入栈;调用过程:调用过程:3.4 函数调用机制函数调用机制 void fun1(int, int);void fun2(float);int main() int x=1;y=2; fun1(x, y); return o;void fun1(int a,int b) fl

17、oat x=3; fun2(x);void fun2(float y) int x; x栈顶栈顶栈底栈底y3fun2()fun1()运行状态及返回地址运行状态及返回地址x3b2a1fun1()main()运行状态及返回地址运行状态及返回地址y2x1main()操作系统运行状态及返回地址操作系统运行状态及返回地址此图例说明此图例说明在程序执行过程中怎样通过栈在程序执行过程中怎样通过栈“动态动态”地建立和地建立和释放局部变量占用的内存的释放局部变量占用的内存的 3.5 作用域与标识符的可见性作用域与标识符的可见性3 文件域文件域 2 函数声明域函数声明域 作作用用域域:指指标标识识符符能能够够被被

18、使使用用的的范范围围。只只有有在在作作用域内标识符才可以被访问(称为可见)。用域内标识符才可以被访问(称为可见)。本本节节重重点点讨讨论论局局部部域域和和文文件件域域(全全局局域域),其其中中局局部部域域包包括括块块域域和和函函数数声声明明域域。任任何何标标识识符符作作用用域域的的起始点均为起始点均为标识符说明标识符说明处。处。下面分别介绍下面分别介绍:1 块域块域 函函数数中中定定义义的的标标识识符符,包包括括形形参参和和函函数数体体中中定定义义的局部变量,作用域都在该函数内,也称作的局部变量,作用域都在该函数内,也称作函数域函数域。1.块域块域块块指指一一对对大大括括号号括括起起来来的的程

19、程序序段段。块块中中定定义义的的标标识符,作用域在块内。识符,作用域在块内。复合语句是一个块。复合语句是一个块。函数也是一个块。函数也是一个块。复合语句中定义的标识符,复合语句中定义的标识符,作用域仅在该复合语句中。作用域仅在该复合语句中。【例例3.7】 输入两数,按从大到小的顺序保存。输入两数,按从大到小的顺序保存。块的引入:块的引入:1.块域块域由由VC+运行,结果如下:运行,结果如下:输入两整数:输入两整数:3 5调用前:实参调用前:实参a=3,b=5调用中调用中交换前:形参交换前:形参a=3,b=5交换后:形参交换后:形参a=5,b=3调用后:实参调用后:实参a=3,b=5 交换失败交

20、换失败局部变量具有局部作用域使得程序在不同块中可以使用同名变量。局部变量具有局部作用域使得程序在不同块中可以使用同名变量。这些同名变量各自在自己的作用域中可见,在其它地方不可见这些同名变量各自在自己的作用域中可见,在其它地方不可见。【例例3.8】设计函数完成两数设计函数完成两数交换,用主函数进行测试。交换,用主函数进行测试。操作系统运行状态及返回地址操作系统运行状态及返回地址main()3a5bmain()运行状态及返回地址运行状态及返回地址swap()3a5b3t351.块域块域 对于块中对于块中嵌套嵌套其它块的情况,如果嵌套块中有同其它块的情况,如果嵌套块中有同名局部变量,服从局部优先原则

21、,即在内层块中名局部变量,服从局部优先原则,即在内层块中屏屏蔽蔽外层块中的同名变量,换句话说,内层块中局部外层块中的同名变量,换句话说,内层块中局部变量的作用域为内层块;外层块中局部变量的作用变量的作用域为内层块;外层块中局部变量的作用域为外层除去包含同名变量的内层块部分。域为外层除去包含同名变量的内层块部分。如果块内定义的局部变量与全局变量同名,块内仍如果块内定义的局部变量与全局变量同名,块内仍然局部变量优先,但与块作用域不同的是,在块内然局部变量优先,但与块作用域不同的是,在块内可以通过域运算符可以通过域运算符“:”访问同名的全局变量。访问同名的全局变量。【例例3.9】 显示同名变量可见性

22、。显示同名变量可见性。2函数声明域函数声明域 函数声明不是定义函数,在作函数声明时,其中的形参作用域只在声明中,即作用域结束于右括号。正是由于形参不能被程序的其他地方引用,所以通常只要声明形参个数和类型,形参名可省略。3 3 文件域文件域 文文件件域域也也称称全全局局域域。定定义义在在所所有有函函数数之之外外的的标标识识符符作作用用域域为为从从定定义义处处到到整整个个源源文文件件结结束束,即即文文件件域域 。文文件件中定义的全局变量和函数的作用域为文件域。中定义的全局变量和函数的作用域为文件域。如如果果某某个个文文件件中中说说明明了了作作用用域域为为文文件件域域的的标标识识符符,该该文文件件又

23、又被被另另一一个个文文件件包包含含,则则该该标标识识符符的的作作用用域域延延伸伸到到新新的的文文件件中中。如如cincin和和coutcout是是在在头头文文件件iostreamiostream中中说说明明的的具具有有文文件件作作用用域域的的标标识识符符,它它们们的的作作用用域域也也延延伸伸到嵌入到嵌入iostreamiostream的文件中。的文件中。存存储储类类型型(storage class)决决定定标标识识符符的的存存储储区区域域,即即编编译译系系统统在在不不同同区区域域为为不不同同存存储储类类型型的的标标识识符符分分配配空空间间。由由于于存存储储区区域域不不同同,标标识识符符的的生生

24、命命期期也也不不同同。所所谓谓生生命命期期,指指的的是是标标识识符符从从获获得得空空间间到到空空间间释释放放之之间间的的期期间间,标标识识符符只只有有在在生生存存期期中中、并且在其自己的作用域中才能被访问。并且在其自己的作用域中才能被访问。3.6 存储类型与标识符的生命期存储类型与标识符的生命期 3.6.1 3.6.1 存储类型存储类型存储类型存储类型 3.3.3.2 3.2 生命期生命期生命期生命期 自动变量为用自动变量为用auto说明的变量,通常说明的变量,通常auto缺省。局部变量都是自缺省。局部变量都是自动变量,生命期开始于块的执行,结束于块的结束,其原动变量,生命期开始于块的执行,结

25、束于块的结束,其原因是自动变量的空间分配在栈中,块开始执行时系统自动因是自动变量的空间分配在栈中,块开始执行时系统自动分配空间,块执行结束时系统自动释放空间。故自动变量分配空间,块执行结束时系统自动释放空间。故自动变量的生命期和作用域是一致的。的生命期和作用域是一致的。3.6.1 存储类型存储类型 为为提提高高程程序序运运行行效效率率,可可以以将将某某些些变变量量保保存存在在寄寄存存器器中中,即即用用register说明为寄存器变量,说明为寄存器变量,但不提倡使用但不提倡使用。C+中关于存储类型的说明符(中关于存储类型的说明符(storage class specifier)有四)有四个:个:

26、auto、register、static和和extern。其中用。其中用auto和和register修修饰的称为自动存储类型,用饰的称为自动存储类型,用static修饰的称为静态存储类型,修饰的称为静态存储类型,用用extern修饰的称为外部存储类型。修饰的称为外部存储类型。1 1 自动存储类型自动存储类型static说说明明的的变变量量称称为为静静态态变变量量。根根据据定定义义的的位位置置不不同同,还还分分为为局局部部静静态态变变量量和和全全局局静静态态变变量量,也也称称内内部部静静态态变变量量和和外外部部静静态态变变量量。静静态态变变量量均均存存储储在在全全局局数数据据区区,如如果果程程序

27、序未未显显式式给给出出初初始始化化值值,则则等等效效初初始始化化为为全全0;静静态态变变量量占占有有的的空空间间要要到到整整个个程程序序执执行行结结束束才才释释放放,故故静静态态变变量量具具有有整整个个程程序序执执行行期期间间的的生命期。生命期。3.6.1 存储类型存储类型局局部部静静态态变变量量是是定定义义在在块块中中的的静静态态变变量量,编编译译系系统统在在全全局局数数据据区区为为其其开开辟辟空空间间并并保保存存数数据据,该该空空间间一一直直到到整整个个程程序序结结束束才才释释放放。局局部部静静态态变变量量具具有有局局部部作作用用域域,但但却却具具有有整整个个程程序序执执行行期期间间的的生

28、生命命期期。如如果果显显式式给给出出初初始始化化值值,则则在在该该块块第第一一次次执执行行时时完成,且只进行一次。完成,且只进行一次。2 2 2 2 静态存储类型静态存储类型静态存储类型静态存储类型【例例3.10】 自动变量与局部静态变量的区别自动变量与局部静态变量的区别3.6.1 存储类型存储类型3 3 3 3 外部存储类型外部存储类型外部存储类型外部存储类型一个一个C+程序可以由多个源程序文件组成。多文件程序系统可程序可以由多个源程序文件组成。多文件程序系统可以通过以通过外部存储类型外部存储类型的变量和函数来的变量和函数来共享共享某些数据和操作。某些数据和操作。在一个程序文件中定义的全局变

29、量和函数缺省为外部的,即其作在一个程序文件中定义的全局变量和函数缺省为外部的,即其作用域可以延伸到程序的其他文件中。其他文件如果要使用这个文用域可以延伸到程序的其他文件中。其他文件如果要使用这个文件中定义的全局变量和函数,应该在使用前用件中定义的全局变量和函数,应该在使用前用“extern”作外部作外部声明。外部声明通常放在文件的开头(声明。外部声明通常放在文件的开头(函数函数总是总是省略省略extern)。)。外部变量声明不同于全局变量定义,变量定义时编译器为其分外部变量声明不同于全局变量定义,变量定义时编译器为其分配存储空间,而变量声明则表示该全局变量已在其他地方定义配存储空间,而变量声明

30、则表示该全局变量已在其他地方定义过,编译系统不再分配存储空间。过,编译系统不再分配存储空间。外部的全局变量或函数加上外部的全局变量或函数加上static修饰,就成为静态全局变量修饰,就成为静态全局变量或静态函数。静态的全局变量和函数作用域限制在本文件,其或静态函数。静态的全局变量和函数作用域限制在本文件,其他文件即使使用外部声明也无法使用该全局变量或函数。他文件即使使用外部声明也无法使用该全局变量或函数。 【例例3.11】外部存储类型的例子外部存储类型的例子3.6.2 生命期生命期1.1. 静态生命期静态生命期 静态生命期静态生命期(Static extent或或Static storage

31、duration)指)指的是标识符从程序开始运行时就存在,具有存储空间,到程的是标识符从程序开始运行时就存在,具有存储空间,到程序运行结束时消亡,释放存储空间。具有静态生命期的标识序运行结束时消亡,释放存储空间。具有静态生命期的标识符存放在全局数据区,如全局变量、静态全局变量、静态局符存放在全局数据区,如全局变量、静态全局变量、静态局部变量。具有静态生命期的标识符在未被用户初始化的情况部变量。具有静态生命期的标识符在未被用户初始化的情况下,系统会下,系统会等效等效将其初始化为全将其初始化为全0。 函数驻留在代码区,也具有静态生命期。所有具有文件函数驻留在代码区,也具有静态生命期。所有具有文件作

32、用域的标识符都具有静态生命期。作用域的标识符都具有静态生命期。 3.6.2 生命期生命期2. 2. 2. 2. 局部生命期局部生命期局部生命期局部生命期 在函数内部或块中定义的标识符具有在函数内部或块中定义的标识符具有局部生命期局部生命期(Automatic extent或或Automatic storage duration),),其生命期开始于执行到该函数或块的标识符定义处,其生命期开始于执行到该函数或块的标识符定义处,结束于该函数或块的结束处。具有局部生命期的标识结束于该函数或块的结束处。具有局部生命期的标识符存放在栈区。具有局部生命期的标识符如果未被初符存放在栈区。具有局部生命期的标识

33、符如果未被初始化,其内容是随机的,不可引用。始化,其内容是随机的,不可引用。 具有局部生命期的标识符必定具有局部作用域;具有局部生命期的标识符必定具有局部作用域;但反之不然,静态局部变量具有局部作用域,但却具但反之不然,静态局部变量具有局部作用域,但却具有静态生命期。有静态生命期。3.6.2 生命期生命期具有具有动态生命期动态生命期(dynamic extent或或dynamic storage duration)的标识符存放在自由存储区,)的标识符存放在自由存储区,由特定的函数调用或运算来创建和释放,如用由特定的函数调用或运算来创建和释放,如用new运算符(或调用运算符(或调用malloc(

34、)函数)为变量分配函数)为变量分配存储空间时,变量的生命期开始,而用存储空间时,变量的生命期开始,而用delete运运算符(或调用算符(或调用free()函数)释放空间或程序结束函数)释放空间或程序结束时,变量生命期结束。关于时,变量生命期结束。关于new运算符和运算符和delete运算符将在第七章中介绍。运算符将在第七章中介绍。3. 3. 动态生命期动态生命期3.7 函数的递归调用函数的递归调用 递递归归是是一一种种描描述述问问题题的的方方法法,或或称称算算法法。递递归归的的思思想想可可以以简单地描述为简单地描述为“自己调用自己自己调用自己”。例如用如下方法定义阶乘:。例如用如下方法定义阶乘

35、:可以看出是用阶乘定义阶可以看出是用阶乘定义阶乘,这种自己定义自己的乘,这种自己定义自己的方法称为递归定义。方法称为递归定义。递归的引入:递归的引入:递归的分类递归的分类在函数调用中,有这样两种情况,一种是在函数在函数调用中,有这样两种情况,一种是在函数A的定义中的定义中有调用函数有调用函数A的语句,即自己调用自己;另一种是函数的语句,即自己调用自己;另一种是函数A的的定义中出现调用函数定义中出现调用函数B的语句,而函数的语句,而函数B的定义中也出现调用的定义中也出现调用函数函数A的语句,即相互调用。前者称的语句,即相互调用。前者称直接递归直接递归,后者称,后者称间接间接递归递归。本节只介绍直

36、接递归。本节只介绍直接递归。递归定义的阶乘函数:递归定义的阶乘函数:fac(int n)int y;if (n=0|n=1) y=1;else y=n*fac(n-1);return y;只要设计主函数调用阶乘函数,即可实现计算阶乘。只要设计主函数调用阶乘函数,即可实现计算阶乘。递归函数必须定义递归递归函数必须定义递归终止条件终止条件(Stopping condition),),避免避免无穷递归无穷递归(Infinite Recursion)。)。3.7 函数的递归调函数的递归调用用【例例3.12】 求求4!运行结果:运行结果:4 3 2 1 1 2 6 244!=243.7 函数的递归调用函

37、数的递归调用探讨:探讨:计算是先右后左。请看下一条输出语句:计算是先右后左。请看下一条输出语句:coutn4!=fac(4) n3!=fac(3)endl;先算先算fac(3), 后算后算fac(4), 先右后左。但输出还是从左到右:先右后左。但输出还是从左到右:3 211264321126244!=243!=6说明:说明:coutn4!=fac(4)=0&ch=9?1:0;int main() char ch; while(cin.get(ch), ch!= n) if (IsNumber(ch) cout 是数字字符是数字字符 endl; else cout 不是数字字符不是数字字符 en

38、dl; return 0;因使用频度很高,说明为内联函数。因使用频度很高,说明为内联函数。3.8.3 内联函数内联函数 内联函数的调用机制与一般函数不同,编内联函数的调用机制与一般函数不同,编译器在编译过程中遇到译器在编译过程中遇到inline时,为该函数建时,为该函数建立一段代码,而后在每次调用时立一段代码,而后在每次调用时直接直接将该段将该段代码代码嵌入嵌入到调用函数中,从而到调用函数中,从而将函数调用方将函数调用方式变为顺序执行方式式变为顺序执行方式,这一过程称为内联函,这一过程称为内联函数的扩展或内联。数的扩展或内联。 因因inline指示符对编译器而言只是一个建指示符对编译器而言只是

39、一个建议,编译器也可以选择忽略该建议。议,编译器也可以选择忽略该建议。3.9 头文件与多文件结构头文件与多文件结构 (选读)(选读)3.9.1 头文件头文件标准库头文件:标准库头文件:考虑标识符在其他文件中的可见性。使用头文件是很有效的方考虑标识符在其他文件中的可见性。使用头文件是很有效的方法。如:法。如:#includeusing namespace std; 其中其中iostream是是在在标准名字空间域标准名字空间域std中定义的头文件。对应中定义的头文件。对应的传统方式的文件名为的传统方式的文件名为,头文件以,头文件以“.h”为后缀。为后缀。 系统定义的头文件系统定义的头文件中定义了一

40、些常用的公用标识符和函数,中定义了一些常用的公用标识符和函数,用户只要将头文件包含进自己的文件,就可使头文件中定义的用户只要将头文件包含进自己的文件,就可使头文件中定义的标识符在用户文件中变得可见,也就可以直接使用头文件中定标识符在用户文件中变得可见,也就可以直接使用头文件中定义的标识符和函数。义的标识符和函数。 3.9.1 头文件头文件自定义头文件:自定义头文件:除了系统定义的头文件外,用户还可以除了系统定义的头文件外,用户还可以自定义头文自定义头文件件。对于具有外部存储类型的标识符,可以在其他。对于具有外部存储类型的标识符,可以在其他任何一个源程序文件中经声明后引用,因此用户完任何一个源程

41、序文件中经声明后引用,因此用户完全可以将一些具有外部存储类型的标识符的声明放全可以将一些具有外部存储类型的标识符的声明放在一个头文件中。具体地说,头文件中可以包括:在一个头文件中。具体地说,头文件中可以包括:用户构造的数据类型(如枚举类型),外部变量,用户构造的数据类型(如枚举类型),外部变量,外部函数、常量和内联函数等具有一定通用性或常外部函数、常量和内联函数等具有一定通用性或常用的量,而一般性的变量和函数定义不宜放在头文用的量,而一般性的变量和函数定义不宜放在头文件中。件中。3.9.2 多文件结构多文件结构 在开发较大程序时,通常将其分解为多个源程序文件,每在开发较大程序时,通常将其分解为

42、多个源程序文件,每个较小的程序用一个源程序文件建立。程序经过建立、编译、个较小的程序用一个源程序文件建立。程序经过建立、编译、连接,成为一个完整的可执行程序。连接,成为一个完整的可执行程序。多文件结构通过工程进行多文件结构通过工程进行管理,在工程中建立若干用户定义的头文件管理,在工程中建立若干用户定义的头文件.h和源程序文件和源程序文件.cpp。头文件中定义用户自定义的数据类型,所有的程序实现。头文件中定义用户自定义的数据类型,所有的程序实现则放在不同的源程序文件中则放在不同的源程序文件中。编译时每个源程序文件单独编译,。编译时每个源程序文件单独编译,如果源程序文件中有编译预处理指令,则首先经

43、过编译预处理如果源程序文件中有编译预处理指令,则首先经过编译预处理生成临时文件存放在内存,之后对临时文件进行编译生成目标生成临时文件存放在内存,之后对临时文件进行编译生成目标文件文件.obj,编译后临时文件撤销。所有的目标文件经连接器连,编译后临时文件撤销。所有的目标文件经连接器连接最终生成一个完整的可执行文件接最终生成一个完整的可执行文件.exe。 图图3.11是一个多文件系统的开发过程。是一个多文件系统的开发过程。3.9.2 多文件结构多文件结构 编译 预编译编译 预编译 预编译编译图图3.11 C+程序开发过程程序开发过程file1.hfile1.cppfile2.hfile2.cppf

44、ilen.hfilen.cpp临时文件临时文件1临时文件临时文件2临时文件临时文件nfile1.objfile2.objfilen.objFilename.exe.libC+标准类库标准类库连接连接运行运行3.10 编译预处理编译预处理(选读选读) 3.10.1 宏定义指令宏定义指令 3.10.2 文件包含指令文件包含指令 3.10.3 条件编译指令条件编译指令 3.10.1 宏定义指令宏定义指令1 1 不带参宏定义不带参宏定义用来产生与一个字符串对应的常量字符串,格式为:用来产生与一个字符串对应的常量字符串,格式为:#define 宏名宏名 常量串常量串 预处理后文件中凡出现该字符串处均用其

45、对应的常量预处理后文件中凡出现该字符串处均用其对应的常量串代替。替换过程称为宏替换或宏展开。例如,如果串代替。替换过程称为宏替换或宏展开。例如,如果使用指令使用指令#define PI 3.1415926则程序中可以使用标识符则程序中可以使用标识符PIPI,编译预处理后产生一个,编译预处理后产生一个中间文件,文件中所有中间文件,文件中所有PIPI被替换为被替换为3.14159263.1415926。宏替换只是字符串和标识符之间的简单替换,预处理宏替换只是字符串和标识符之间的简单替换,预处理本身不做任何数据类型和合法性检查,也不分配内存本身不做任何数据类型和合法性检查,也不分配内存单元单元。3.

46、10.1 宏定义指令宏定义指令2 2 带参数的宏定义带参数的宏定义带参宏定义的形式很象定义一个函数,格式为:带参宏定义的形式很象定义一个函数,格式为:#define 宏名宏名 ( 形参表形参表 ) 表达式串表达式串 例如作如下宏定义:例如作如下宏定义:#define S(a,b) (a)*(b)/2程序中可使用程序中可使用S(a,b),预处理后产生中间文件,其中,预处理后产生中间文件,其中S(a,b)被被替换成替换成(a)*(b)/2。注意,宏定义形参通常要用括号括起来,否。注意,宏定义形参通常要用括号括起来,否则容易导致逻辑错误。例如,如果定义:则容易导致逻辑错误。例如,如果定义:#defi

47、ne S(a,b) a*b/2那么程序中的那么程序中的S(3+5,4+2)就会被宏展开为就会被宏展开为3+5*4+2/2,不,不符合定义的真正的意图。符合定义的真正的意图。带参宏定义形式上象定义函数,但它与函数的本质不同,宏定带参宏定义形式上象定义函数,但它与函数的本质不同,宏定义仍然只是产生字符串替代,不存在分配内存和参数传递。义仍然只是产生字符串替代,不存在分配内存和参数传递。 3.10.2 文件包含指令文件包含指令文文件件包包含含用用#include指指令令,预预处处理理后后将将指指令令中中指指明明的的源源程程序序文件嵌入到当前源程序文件的指令位置处。格式为:文件嵌入到当前源程序文件的指

48、令位置处。格式为:#include 或或#include 文件名文件名第第一一种种方方式式称称为为标标准准方方式式,预预处处理理器器将将在在include子子目目录录下下搜搜索索由由文文件件名名所所指指明明的的文文件件。这这种种方方式式适适用用于于嵌嵌入入C+提提供供的的头头文文件件,因因为为这这些些头头文文件件一一般般都都存存在在C+系系统统目目录录的的include子子目目录录下下。而而第第二二种种方方式式编编译译器器将将首首先先在在当当前前文文件件所所在在目目录录下下搜搜索索,如如果果找找不不到到再再按按标标准准方方式式搜搜索索。这这种种方方式式适适用于嵌入用户自己建立的头文件。用于嵌入

49、用户自己建立的头文件。一个被包含的头文件中还可以有一个被包含的头文件中还可以有#include指令,即指令,即include指令可以嵌套指令可以嵌套,但是,如果同一个头文件,但是,如果同一个头文件在同一个源程序文件中被在同一个源程序文件中被重复包含重复包含,就会出现,就会出现标识标识符重复定义的错误符重复定义的错误。例如:头文件。例如:头文件f2.h中包含了中包含了f1.h,如果文件,如果文件f3.cpp中既包含中既包含f1.h,又包含,又包含f2.h,那么编译将提示错误,原因是,那么编译将提示错误,原因是f1.h被包含了两次,被包含了两次,那么其中定义的标识符在那么其中定义的标识符在f3.c

50、pp中就被重复定义。中就被重复定义。避免重复包含可以用避免重复包含可以用条件编译指令条件编译指令。3.10.2 文件包含指令文件包含指令3.10.3 条件编译指令条件编译指令 1 用用宏名宏名作为编译的条件作为编译的条件格式为:格式为:#ifdef#else#endif2 表达式的值表达式的值作为编译条件作为编译条件格式为:格式为:#if #else#endif当希望在不同条件下编译程序的不同部分。这种情况就要使当希望在不同条件下编译程序的不同部分。这种情况就要使用条件编译指令。用条件编译指令。 其中程序段可以是程序也可以是编译预处理指令。可以通过其中程序段可以是程序也可以是编译预处理指令。可

51、以通过在该指令前面安排宏定义来控制编译不同的程序段。在该指令前面安排宏定义来控制编译不同的程序段。例:在调试程序时常常要输出调试信息,而调试完后不需要例:在调试程序时常常要输出调试信息,而调试完后不需要输出这些信息,则可以把输出调试信息的语句用条件编译指输出这些信息,则可以把输出调试信息的语句用条件编译指令括起来。形式如下:令括起来。形式如下:#ifdef DEBUGcout a=atx=xendl;#endif在程序调试期间,在该条件编译指令前增加宏定义:在程序调试期间,在该条件编译指令前增加宏定义:#define DEBUG调试好后,删除调试好后,删除DEBUG宏定义,将源程序重新编译一次

52、。宏定义,将源程序重新编译一次。条件编译指令包括:条件编译指令包括:#if、#else、#ifdef、#ifndef、#endif、#undef等。等。#ifndef与与#ifdef作用一样,只是选择的条件相反。作用一样,只是选择的条件相反。#undef指令用来取消指令用来取消#define指令所定义的符号,这样可指令所定义的符号,这样可以根据需要打开和关闭符号。以根据需要打开和关闭符号。第三章第三章 函数函数再见谢谢!谢谢!3.1.3 函数的调用函数的调用【例例3.1】 main( )函数函数调用调用max(2.5,4.7 )函数函数max(2.5,4.7 )return 4.7 主程序后主

53、程序后续语句续语句【例例3.1】 输输入入两两个个实实数数,输输出出其其中中较较大大的的数数。其其中中求两个实数中的较大数用函数完成。求两个实数中的较大数用函数完成。程序如下程序如下:#include using namespace std;float max(float a,float b)return(a=b?a:b);int main()float x,y;cout输入两个实数:输入两个实数:xy;coutx和和y中较大数为中较大数为max(x,y)endl;return 0; 3.2.1 函数的参数传递及传值调用函数的参数传递及传值调用【例例3.2】 调用调用power(4.6,3 )

54、函数函数power(4.6,3 )return 97.336 主程序后续语主程序后续语句句n= 3x= 4.6c= a【例例3.2】 实参和形参对应关系的示例。实参和形参对应关系的示例。float power(float x,int n)/求求x x的的n n次幂次幂float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;char c=a;coutpower(x,n)=power(x,n)endl;coutpower(c,n)=power(c,n)endl;coutpower(n,x)=power(n,x)endl;re

55、turn 0; 3.2.1 函数的参数传递及传值调用函数的参数传递及传值调用【例例3.2】调用调用power(a,3 )函数函数power(97,3 )return 912673 主程序后续语主程序后续语句句n= 3x= 4.6c= a【例例32】 实参和形参对应关系实参和形参对应关系。float power(float x,int n) /求求x x的的n n次幂次幂float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;char c=a;coutpower(x,n)=power(x,n)endl;coutpower(

56、c,n)=power(c,n)endl;coutpower(n,x)=power(n,x)endl;return 0; 3.2.1 函数的参数传递及传值调用函数的参数传递及传值调用【例例3.2】调用调用power(3,4.6 )函数函数power(3,4)return 81 主程序后续语主程序后续语句句n= 3x=4.6c= a【例例32】 实参和形参对应关系。实参和形参对应关系。float power(float x,int n) /求求x x的的n n次幂次幂float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;c

57、har c=a;coutpower (x,n)=power(x,n)endl;coutpower (c,n)=power(c,n)endl;coutpower (n,x)=power(n,x)endl;return 0;【例例3.33.3】程序:程序:float TriangleArea(float a, float b, float c) if (a+b=c)|(a+c=b)|(b+c=a) return -1; float s; s=(a+b+c)/2; return sqrt(s*(s-a)*(s-b)*(s-c) ;int main() float a,b,c,area; cout输入

58、三角形三边输入三角形三边a,b,c:abc; area=TriangleArea(a,b,c); if(area=-1) cout(a,b, c )不能构成三角形!不能构成三角形!endl; else cout三角形三角形(a,b,c )面积为:面积为:areaendl; return 0;bool palindrome(int); /函数声明函数声明int main() int m;coutsetw(10)msetw(20)m*m“setw(20)m*m*mendl;for(m=11;m1000;m+)if(palindrome(m)&palindrome(m*m) &palindrome(

59、m*m*m)coutsetw(10)msetw(20)m*msetw(20)m*m*0);for(j=0;ji;j+) n=n*10+digitj;return (n=m);【例例3.43.4】 输出回文数输出回文数3.3.2 全局变量全局变量【例例3.5】 打印打印200调用调用func( )函数函数func( )200*2=400打印打印400n=100n=100*2=200【例例3.53.5】 多个函数使用全局变量的例子。多个函数使用全局变量的例子。int n=100;void func()n*=2; int main()n*=2;coutnendl;func();coutnendl;

60、return 0;3.3.3 局部变量局部变量 打印打印main()中的中的t=3.5调用调用fun( )函数函数fun( )打印打印fun()中的中的t=5 打印打印main()中的中的t=3.5t= 3.5t = 5【例例3.6】 使用局部变量的例子。使用局部变量的例子。void fun()auto int t=5;/ fun()中的局部变量,中的局部变量,auto可省略可省略coutfun()中的中的t=tendl;int main()float t=3.5;/main()函数中的局部变量函数中的局部变量coutmain()中中的的t=tendl;fun();coutmain()中中的的

61、t=tendl;return 0;1.块域块域【例例3.7】 a= 3 b= 535a=3 b=5a=5 b=3【例例3.7】 输入两数,按从大到小的顺序保存,并输出结果。输入两数,按从大到小的顺序保存,并输出结果。结果结果栈栈t = 3 int main() int a,b; /具有函数域具有函数域 cout输入两整数:输入两整数:ab; cout“a=atb=b=a)int t; /具有块域具有块域 t=a; a=b; b=t; /交换交换a,b的值的值 couta=atb=bendl; return 0;上述程序若在最后一个上述程序若在最后一个cout语句处增加:语句处增加:coutte

62、ndl;则编译时会提示错误,因为变量则编译时会提示错误,因为变量t的作用域只在的作用域只在if语句中,其它地方语句中,其它地方不可见不可见。【例例3.8】设计函数完成两数交换,用主函数进行测试。设计函数完成两数交换,用主函数进行测试。void swap(int,int);int main() int a,b; /a,b作用域为作用域为main() cout输入两整数:输入两整数:ab; cout调用前:实参调用前:实参a=a,b=bendl; swap(a,b); /传值传值 cout调用后:实参调用后:实参a=a,b=bendl; return 0;void swap(int a,int b

63、) /a,b作用域为作用域为swap() cout调用中调用中endl; cout交换前:形参交换前:形参a=a,b=bendl; int t; t=a; a=b; b=t;/交换交换swap()中的中的a,b的值的值 cout交换后:形参交换后:形参a=a,b=bendl;全局全局n= 100100 200 300内内 i= 500内内 j= 600内内n=500+600 =11001100 500 600100200+300=500500 500 200 300外部外部 i=200外部外部 j=300【例例3.9】 显示同名变量可见性。显示同名变量可见性。int n=100;#includ

64、e int main() int i=200,j=300;cout ntitjendl; /内部块内部块 int i=500,j=600,n; n=i+j; cout ntitj endl; /输出局部变量输出局部变量n cout:nendl;/输出全局变量输出全局变量n n=i+j;/修改全局变量修改全局变量cout ntitj endl;return 0;【例例3.10】 自动变量与局部静态变量的区别自动变量与局部静态变量的区别 int st() static int t=100; /局部静态变量局部静态变量 t+; return t;int at() int t=100; /自动变量自动

65、变量 t+;return t;int main() int i; for(i=0;i5;i+) coutat()t; coutendl; for(i=0;i5;i+) coutst()t; coutendl; return 0;3.6.1 存储类型存储类型i= 0t= 10012 34 51011011011011013.6.1 存储类型存储类型i= 0t=1001 21013 4 5102103104105【例例3.10】 自动变量与局部静态变量的区别自动变量与局部静态变量的区别 int st() static int t=100; /局部静态变量局部静态变量 t+; return t;in

66、t at() int t=100; /自动变量自动变量 t+;return t;int main() int i; for(i=0;i5;i+) coutat()=t; coutendl; for(i=0;i5;i+) coutst()t; coutendl; return 0;【例例3.11】外部存储类型的例子。假定程序包含两个源程序文件外部存储类型的例子。假定程序包含两个源程序文件Ex3_11_1.cpp和和Ex3_11_2.cpp,程序结构如下:,程序结构如下:/* Ex3_11_1.cpp ,由,由main()组成组成*/void fun2(); /外部函数声明,等价于外部函数声明,等

67、价于extern void fun2();int n; /全局变量定义全局变量定义int main() n=1; fun2(); / fun2()定义在文件定义在文件Ex4_11_2.cpp中中 coutn=nendl; return 0;/* Ex3_11_2.cpp,由,由fun2()组成组成*/extern int n; /外部变量声明,外部变量声明,n定义在文件定义在文件Ex4_11_1.cpp中中void fun2() /fun2()被文件被文件Ex4_11_1.cpp中的函数调用中的函数调用n=3; 运行结果:运行结果:n=3【例例3.12】 求求4!#include int fa

68、c(int n)int y; coutnt;if(n=0|n=1) y=1; else y=n*fac(n-1);coutyt;return y;int main()coutn4!=fac(4)endl;return o; n=4cout4;y=4*fac(3);fac(4)=cout2;y=2*fac(1); n=2cout1;y=1;cout1;return 1; n=1 n=3cout3;y=3*fac(2);cout24;return 24;cout6;return 6;cout2;return 2;243.7 函数的递归调用函数的递归调用【例例3.13】 【例例3.13】 汉汉诺诺塔

69、塔问问题题。有有A、B、C三三根根柱柱子子,A柱柱上上有有n个个大大小小不不等等的的盘盘子子,大大盘盘在在下下,小小盘盘在在上上。要要求求将将所所有有盘盘子子由由A柱柱搬搬动动到到C柱柱上上,每每次次只只能能搬搬动动一一个个盘盘子子,搬搬动动过过程程中中可可以以借借助助任任何何一一根根柱柱子子,但但必必须须满满足足大大盘盘在在下,小盘在上。打印出搬动的步骤。下,小盘在上。打印出搬动的步骤。 A柱柱B柱柱C柱柱分析:分析:1 A1 A柱只有一个盘子的情况:柱只有一个盘子的情况: A A柱柱C C柱;柱;2 2 A A柱柱有有两两个个盘盘子子的的情情况况:小小盘盘A A柱柱B B柱柱,大大盘盘A

70、A柱柱C C柱,小盘柱,小盘B B柱柱C C柱。柱。3 3 A A柱柱有有n n个个盘盘子子的的情情况况:将将此此问问题题看看成成上上面面n-1n-1个个盘盘子子和和最最下下面面第第n n个个盘盘子子的的情情况况。n-1n-1个个盘盘子子A A柱柱B B柱柱,第第n n个个盘盘子子A A柱柱C C柱柱,n-1n-1个个盘盘子子B B柱柱C C柱柱。问问题题转转化化成成搬搬动动n-1n-1个个盘盘子子的的问问题题,同同样样,将将n-1n-1个个盘盘子子看看成成上上面面n-2n-2个个盘盘子子和和下下面面第第n-1n-1个个盘盘子子的的情情况况,进进一一步步转转化化为为搬搬动动n-2n-2个个盘盘

71、子子的的问问题题,类类推推下下去去,一一直直到到最最后后成成为为搬搬动动一一个个盘子的问题盘子的问题。这是一个典型的递归问题,递归结束于只搬动一个盘子。这是一个典型的递归问题,递归结束于只搬动一个盘子。3.7 函数的递归调用函数的递归调用【例例3.13】3.7 函数的递归调用函数的递归调用【例例3.13】算法:算法:1 n-1个盘子个盘子A柱柱B柱,借助于柱,借助于C柱;柱;2 第第n个盘子个盘子A柱柱C柱;柱;3 n-1个盘子个盘子B柱柱C柱,借助于柱,借助于A柱;柱;其中步骤其中步骤1和步骤和步骤3继续递归下去,直至搬动一个盘继续递归下去,直至搬动一个盘子为止。由此,可以定义两个函数子为止

72、。由此,可以定义两个函数: 一个是递归函数,命名为一个是递归函数,命名为hanoi(int n, char source, char temp, char target),实现将,实现将n个个盘子从源柱盘子从源柱source借助中间柱借助中间柱temp搬到目标柱搬到目标柱target; 另一个命名为另一个命名为move(char source, char target),用来输出搬动一个盘子的提示信息。,用来输出搬动一个盘子的提示信息。void move(char source,char target) coutsourcetargetendl;void hanoi(int n,char so

73、urce,char temp,char target) if(n=1) move(source,target); elsehanoi(n-1,source,target,temp); /将将n-1个盘子搬到中间柱个盘子搬到中间柱 move(source,target); /将最后一个盘子搬到目标柱将最后一个盘子搬到目标柱hanoi(n-1,temp,source,target); /将将n-1个盘子搬到目标柱个盘子搬到目标柱 int main()int n;cout输入盘子数:输入盘子数:n;hanoi(n,A,B,C);return 0;3.7 函数的递归调用函数的递归调用【例例3.13】b

74、anoi(2,A,C,B)A Cbanoi(3,A,B,C) banoi(1,A,B,C)banoi(1,B,C,A)C BB AA CB Cbanoi(1,A,B,C)A Bbanoi(1,C,A,B)A Cbanoi(2,B,A,C)汉诺塔程序执行框图汉诺塔程序执行框图输入盘子数:输入盘子数:3【例例3.14】 输入一个整数,用递归算法将整数倒序输出。输入一个整数,用递归算法将整数倒序输出。分析:分析:在递归过程的递推步骤中用求余运算将整数的各个位分在递归过程的递推步骤中用求余运算将整数的各个位分离,并打印出来。离,并打印出来。void backward(int n)coutn%10;if

75、(n10) return; else backward(n/10);void main()int n;cout输入整数:输入整数:n;cout原整数:原整数:nendl反向数:反向数:;backward(n);coutendl;return 0;3.7 函数的递归调用函数的递归调用【例例3.14】n=247cout7;backward(24); n=2cout2;return;n=24cout4;backward(2);backward(247) return; return; coutendl; 求余总是取当前整数的最右一位,所以先输出余数后递归求余总是取当前整数的最右一位,所以先输出余数后

76、递归可实现倒序输出。如果先递归后输出余数,则是在回归的过程可实现倒序输出。如果先递归后输出余数,则是在回归的过程中输出,实现的就是正序输出。中输出,实现的就是正序输出。【例例3.15】采用递推法求解采用递推法求解Fibonacii数列,本例的递归调用数列,本例的递归调用过程参见图过程参见图3.10。int fib(int n)if(n=0) return 0;else if(n=1) return 1;else return fib(n-1)+fib(n-2);int main()int i;for(i=0;i=19;i+) /将将19改为改为69,可以看出计算到后面越来越缓慢。,可以看出计算

77、到后面越来越缓慢。if(i%5=0) coutendl;coutsetw(6)fib(i);coutendl; return 0;3.7 函数的递归调用函数的递归调用【例例3.15】3.8.1 3.8.1 函数重载函数重载函数重载函数重载【例例3.16】 3+5=调用调用sum(3,5 )函数函数sum(3,5 )return 8 2.2+5.6=调用调用sum(2.2,5.6 )函数函数double sum(2.2,5.6 )return 7.8 3.5+4+8=调用调用sum(3.5, 4, 8 )函数函数float sum(3.5, 4.0, 8.0 )return 15.5 结束结束8

78、7.815.5【例例3.16】 重载函数的应用。重载函数的应用。int sum(int a,int b) return a+b;Double sum(double a,double b)return a+b;float sum(float a,float b,float c)return a+b+c;int main()cout3+5=sum(3,5) endl;cout2.2+5.6= sum(2.2,5.6)endl;cout3.5+4+8= sum(3.5,4,8)0; loops-); int main()delay(3);cout延时延时3个时间单位个时间单位endl;delay();/等同于等同于delay(5)cout延时延时5个时间单位个时间单位endl; return 0;3.8.2 3.8.2 默认参数默认参数【例例3.173.17】 123延时延时3个时间单位个时间单位12345延时延时5个时间单位个时间单位

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号