1 / 58

第 五 章 函数 调用

第 五 章 函数 调用. 5.1 void 函数 5. 2 传值调用与传引用调用 5. 3 使用过程抽象 5. 4 测试和调试函数 5.5 常规调试技术 作业. 5.1 void 函数. 函数声明. // 习题 4_10… double clothing_size(double height ,double weight,int age); // 返回用户服装(上衣)的尺码 ( 英寸 ) int main(){ … blouse_size=clothing_size( height,weight,age+10);

cybele
Download Presentation

第 五 章 函数 调用

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第五章 函数调用 • 5.1 void 函数 • 5.2 传值调用与传引用调用 • 5.3 使用过程抽象 • 5.4 测试和调试函数 • 5.5 常规调试技术 • 作业

  2. 5.1 void 函数 函数声明 • //习题 4_10… • double clothing_size(double height ,double weight,int age); • //返回用户服装(上衣)的尺码(英寸) • int main(){ … • blouse_size=clothing_size( height,weight,age+10); • pants_size=clothing_size(weight,age+10); … • } • double clothing_size(double height ,double weight,int age) • {//返回用户服装(上衣)的尺码(英寸) • double size=weight*height/288; • if(age>30) //30岁以后,每增加10岁尺码加1/8 • size=size+(1/8.0)*(age-30)/10; • return (size);} 函数调用 函数定义

  3. 返回一个值的函数特征: • 1. 它是完成子任务的一个小程序; • 2. 传给这个小程序的实参是它的输入;它的传值调用形参是局部于函数的变量(局部变量),它接收主调程序传送的实参的值。 • 3. 它生成一个值作为它惟一的结果,这个返回值相当于这个小程序的输出。 • 总之,这样的函数总是返回一个值,它是黑盒函数定义的理想模式。 • 事实上,一个子任务有三种情况: • (1)产生一个值; • (2)不产生值或其它子任务不需要它产生的值; • (3)产生多个值; • 不返回值的函数称为void 函数

  4. 5.1.1 void函数的定义 • //已知华氏温度及相应的摄氏温度,输出这两个温度值。 • void show_results(double f_degree,double c_degree) • { • cout.setf(ios::fixed); • cout.setf(ios::showpoint); • cout.precision(1); • cout<<f_degree<<“华氏温度相当于" • <<c_degree<<"摄氏温度。"<<endl; • return; • }

  5. 5.1.1 void函数的定义 • (1)声明部分: • void function_name(parameter_list); • (2) 调用部分:一个独立的可执行语句 • Void main() • { … • function_name(real_parameter_list); • } • (3) void函数定义: • void function_name(parameter_list); • { • … • return;//可以包含一个或多个return语句,也可以没有return语句 • }

  6. 5.1.2 void函数编程实例 • 例 5_1 将华氏温度转换为摄氏温度 • 转换公式为:C=(5/9)(F-32) • 华伦海托(1714),德国物理学家,制定了华氏温度,他发现水银气压表的指示刻度会随着温度的变化而变化 。 • 摄尔西乌斯(1742),瑞典天文学家。依据冰水混合(0oC)和与水的沸点(100oC)制定了摄氏温度。 • 如:104oF=40oC

  7. 将华氏温度转换为摄氏温度 主函数完成数据的输入 屏幕初始化 温度转换函数 温度输出函数 任务分解 • 将一个总任务分解成四个子任务,每个子任务都有一个独立的函数来完成:

  8. 函数的完整声明 • 四个子任务由四个函数来实现,我们首先写出这三个函数的完整声明(主函数不用声明): • void initialize_screen(); • //将当前输出与上个程序分开或清屏; • double celsuis(double fahrenheit); • //前条件:形参fahrenheit是华氏温度。 • //后条件:将华氏温度转换为摄氏温度; • void show_results(double f_degree,double c_degree); • //显示华氏温度及相应的摄氏温度。

  9. 函数的实现 这个return是必须的 • double celsuis(double fahrenheit) • { • return ((5.0/9.0)*(fahrenheit-32)); • } • void show_results(double f_degree,double c_degree) • { • cout.setf(ios::fixed); • cout.setf(ios::showpoint); • cout.precision(1); • cout<<f_degree<<"华氏温度等价于"; • cout<<c_degree<<"摄氏温度。"<<endl; • return; • } 这个return是可选的,并可多次出现

  10. void 函数中的 return语句 • void show_results(double f_degree,double c_degree) • { • if(c_degree>0) • { • cout<<f_degree<<"华氏温度等价于" • <<c_degree<<"摄氏温度。"<<endl; • return; • } • cout<<“数据错误!"<<endl; • return; • } 这个return是可选的,并可多次出现,它标志着函数运行的终止。

  11. Void 函数的调用是一个独立的可执行语句 在主函数中调用自定义函数 • int main() • { • double f,c; • initialize_screen(); • cout<<"我们将华氏温度转换为摄氏温度!"<<endl; • cout<<"请输入华氏温度:"; • cin>>f; • c=celsuis(f); • show_results(f,c); • return 0; • }

  12. 关于return语句 • return语句(称为返回语句)具有如下三种使用格式: • return; • return <表达式>; • return ( <表达式> ); • 第一种格式的return用于立即从被调函数中返回, 当函数类型为void时,应使用这种格式的返回语句。 • 当函数类型为非void型时,应使用第二或第三种格式的return语句,此两种格式的语句效果完全相同(可将第二种格式看成是第三种格式的省略形式),系统此时都将计算出表达式的值,并“携带”该值立即从被调函数中返回。

  13. 5.2 值调用与引用调用 • 一个子任务的功能有三种情况: • (1)产生一个值; • (2)产生多个值; • (3)不产生值或其它子任务不需要它产生的值,但需要完成一项任务(如显示、存储文件等)。 • 引用形参能将函数产生的多个值返回

  14. 5.2.1 引用参数的概念 • 若参数表中某参数的类型被指定为“<类型> &”,则称该参数为引用参数,否则为赋值参数。如: • void show_results(double f_degree,double c_degree); • //它所用的两个参数均为赋值参数。 • void swap(int& a, int& b); • //它所用的两个参数均为引用参数。 • 语法要求:调用函数时,引用参数对应的实参必须是指定类型的变量。

  15. 对函数进行调用的执行过程(步骤): • (1) 将对应实参表达式的值赋给赋值形参(若参数为赋值参数的话); • (2) 用实参变量替换相应的形参(若参数为引用参数的话); • (3) 按各形参的“当前值”(或已被“赋值”,或已被“换名”)去执行一遍函数体并返回调用处。 • f(1,2)___void f(int x,int y) • f(a,b)___void f(int &x,int &y)

  16. 结论: • (1) 通过赋值参数来传值的方式是一种“单向传值”方式,它只可向被调函数的形参“传入”值,而不可通过该形参“传出”值。 • 即函数中对形参的各种修改不改变实参。 • (2) 通过引用参数来传值的方式是一种“双向传值”方式,它不仅可向被调函数的形参“传入”值,而且还可通过该形参“传出”值。 • 即函数中对形参的任何修改都直接改变了实参。

  17. a b a b 3 4 4 3 5.2.2 编程实例:swap函数 • 例5_2 交换内存中两个变量之值。 • 函数描述即函数声明: • void swap (int& a,int& b); • //交换形参a与b的值 交换前: 交换后:

  18. 函数算法实现: • void swap(int &x,int &y)//引用参数 • //void swap(int a ,int b )//值参 • { • int t=a; • a=b; • b=t; • }

  19. 例程编码(实例演示“5_2交换两个变量的值.cpp”)例程编码(实例演示“5_2交换两个变量的值.cpp”) • #include<iostream.h> • void swap(int &,int &);//引用参数 • //void swap(int ,int );//值参 • void main(){ • int a=3,b=4; • cout<<"交换前:a,b="; • cout<<a<<" ,"<<b<<endl; • swap(a,b); • cout<<"交换后:a,b="; • cout<<a<<" ,"<<b<<endl; • }

  20. b a b a a b 4 3 4 4 3 3 //函数体 • void swap(int &x,int &y)//引用参数 • //void swap(int a ,int b )//值参 • { int t=a;a=b;b=t; } 实参 y 形参 x 引用调用 按值传送

  21. 思考 • 1.在什么情况下选用赋值参数?在什么情况下选用引用参数? 2.比较赋值参数与引用参数各自的优缺点 赋值参数功能上的缺陷 引用参数的副作用

  22. 5.3 使用过程抽象 • 5.3.1 函数的嵌套调用与递归调用 • 5.3.2 前条件与后条件 • 5.3.3 案例分析:超市定价系统

  23. main() func1(x) func2(x) 5.3.1 函数的嵌套调用 • 1.函数嵌套的概念 • 一个函数体中又包含了一个或多个函数的调用,称为函数的嵌套。

  24. 2. 一个函数调用另一个函数举例 • 例5_3 将变量值按从小到大的顺序排列。(见例程演示) • void swap(int &x,int &y)//引用参数 • { • int t=x;x=y;y=t; • } • void order(int &a,int&b,int&c) • { • if(a>b) swap(a,b); • if(a>c) swap(a,c); • if(b>c) swap(b,c); • return; • }

  25. main() order(x) swap(x) • 函数嵌套调用关系

  26. main() function(x) function(x) • 3. 函数的递归调用 • 一个函数体中又调用了它自已,称为函数的递归调用。

  27. //递归函数的定义 • double factor(int number) • { • double f; • if(number<=1) • f=1; • else • { • f=number*factor(number-1); • cout<<f<<endl;; • } • return f; • } • 见例程“5_5递归法求n!.cpp”

  28. 5.3.2 前条件与后条件 • 为函数声明写注释信息时,可将说明信息分为两种。 • 前条件: • 指出函数调用时要满足的条件,称为前条件; • 后条件: • 对函数调用结果的描述,即在满足前条件的前提下,指出函数执行之后将满足什么条件(得到什么结果),称为后条件。 • 具体的说就是对于要返回一个值的函数,后条件是对该返回值的描述;对于产生多个返回值的函数后条件是对这批值的描述,实际是对引用参数的修改描述。

  29. 如:void swap (int& a,int& b); • //前条件:a,b已被赋值 • //后条件:交换a与b的值 • double celsuis(double fahrenheit); • //前条件:形参fahrenheit是华氏温度。 • //后条件:将华氏温度转换后的摄氏温度;

  30. 5.3.3 案例分析:超市定价系统 • 1.问题定义 • Quick_shop连锁超市的定价策略: • 预计当7天之内售出时(<=7): • 商品零售价=批发价+批发价*5% • 预计当7天之后才能售出时(>=8): • 商品零售价=批发价+批发价*10% • 输入:商品批发价(进价)、预计售出的天数 • 输出:商品零售价

  31. 2.问题分析 • 将这个问题分成三个子任务: • (1)输入数据; • (2)计算商品零售价; • (3)输出结果。 • 三个任务由三个函数来完成: • 1)输入函数 • void get_input(double &cost,int &turnover); • //前条件:用户准备好从键盘输入二个正确数据至内存 • //后条件:cost设为一商品的批发价,rurnover为商品预计售出的天数

  32. 2)计算函数 • double price(double &cost,int &turnover); • //前条件:cost设为一商品的批发价, • rurnover为商品预计售出的天数 • //后条件:返回商品的零售价 • 3)输出函数 • void give_results(double cost,int turnover,double price); • //前条件:cost设为一商品的批发价, • // rurnover为商品预计售出的天数 • // cost为商品的零售价 • //后条件:在屏幕上显示cost、turnover、price的值

  33. 3.算法设计 • //返回商品的零售价 • double price(double &cost,int &turnover) • { • if(turnover>THRESHOLD) • return cost+cost*LOW_MARKUP; • else • return cost+cost*HIGH_MARKUP; • }

  34. 4.程序编码(完整编码见例程5_5) • void main() • { • double wholesale_cost,retail_price; • //批发价和零售价 • int sheft_time;//估计出售的时间 • introduction(); • get_input(wholesale_cost,sheft_time); • retail_price=price(wholesale_cost,sheft_time); • give_results(wholesale_cost,sheft_time,retail_price); • }

  35. 5.程序测试 • (1)输入的种类 • 低涨幅:5% • 高涨幅:10% • (2)边界值测试 • 预计售出天数 • THRESHOLD=7 • 相差1错误: • THRESHOLD=6 • THRESHOLD=8

  36. ERROR1:">"--"<";

  37. ERROR2;"<"__"<="

  38. 5.4 测试和调试函数 • 1.驱动程序测试法 • 写一个特殊的程序,以尽可能简单的方法为函数获取参数值,然后执行函数,并显示结果。

  39. 函数get_input( )的驱动程序 • void main() • { … char ans; • do { • get_input(wholesale_cost,sheft_time); • cout<<"商品批发价: $"<<wholesale_cost<<endl; • cout<<"商品预计售出天数: "<<sheft_time<<"天"<<endl; • cout<<"继续吗?(y or n)"<<endl; • cin>>ans; cout<<endl; • }while(ans=='y'||ans=='Y'); • … • }//见例程“5_6函数的驱动程序.cpp”

  40. 2. stub(占位函数)测试法 • 在测试一个函数A时,要用到另一个还没有被测试的函数B,用B的简化版替代B,则称此B的简化版为stub.

  41. 这是一个占位函数(stub) • double price(double &cost,int &turnover) • { • if(turnover<=7) • return cost+cost*0.05; • else • return cost+cost*0.10; • return 23.9; • } • 见见例程“5_7测试超市定价系统.cpp”

  42. 5.5 常规调试技术 • 1. 常见错误 • (1)未初始化的变量; • (2)相差1错误;//<——<== • (3)超过数据边界;//35! • (4)自动类型转换;//5/9,重载函数形参 • (5)该用“==”的地方用了 “=”。//逻辑表达式中 • 2.定位错误 • (1)利用cout语句设置跟踪标志 • (2)利用调试器(debugger)设置断点。

  43. 3.利用调试器调试程序 • (1)利用调试器(debugger)设置断点 • 1)设置固定断点 • 鼠标左单击某个有效语句行首,单击【F9】键,该行左端出现圆点标记,说明该行设置了断点,调试到该行就会临时中断,单击【F5】继续调试. • 2) 设置与条件相关的断点 • 使用【edit】菜单下的【Breakpoint】命令可以设置与某个条件有关的断点。 • (2)调试 • 执行调试命令,单击【F5】键即可,继续执行,仍单击【F5】键。

  44. 5.6 案例分析:长度的换算 • 1.问题定义 • 5_8 写一个程序,要求它读入一个用成米和厘米表示的长度,换算英尺和英寸。或它读入一个用英尺和英寸成表示的长度,换算米和厘米,采用那种换算由用户选择。 • 1英尺=0.3048米,1米=100厘米, • 1英尺=12英寸。

  45. 长度的换算的功能目标

  46. main() menu_select() introduction() Britesh_metric() metric_British() input_British(…) British_metric(…) give_results(…) input_British(…) metric_British (…) give_results(…) 2.问题分析 • 将这个问题分成四个层次的子任务(共11个小任务)

  47. //函数声明部分 • void introduction(); • //本系统的说明 • void menu_select(); • //后条件:根据用户的选择,执行相应的换算 • void British_metric(); • //执行英制到公制的转换过程 • void metric_British(); • //执行英制到公制的转换过程 • void input_metric(double &meter,double &centimeter); • //前条件:用户准备好从键盘输入二个正确数据至内存 • //后条件:meter和centimetetr为一个长度的米数和厘米数 • void input_British(double &food,double &inch); • //前条件:用户准备好从键盘输入二个正确数据至内存 • //后条件:food和inch设为一个长度的英尺数和英寸数

  48. void British_metric(double food,double inch,double &meter,double &centimeter); • //前条件:food和inch为给定的一个长度的英尺数和英寸数 • //后条件:meter和centimetetr为返回的一个长度的米数和厘米数 • void metric_British(double meter,double centimeter,double&food,double&inch); • //前条件:meter和centimetetr为给定的一个长度的米数和厘米数 • //后条件:food和inch为返回的一个长度的英尺数和英寸数 • void give_results(double food,double inch,double meter,double centimeter); • //前条件:food、inch、meter、centimeter分别为给定的一个长度的英尺数、英寸数、米数和厘米数 • //后条件:在屏幕上显示food、inch、meter、centimeter的值

  49. 3.算法设计 • void menu_select() • { • char select; • do • { • cout<<"---------------------------------------\n"; • cout<<"\t1--将一个英制长度换算成公制长度\n"; • cout<<"\t2--将一个公制长度换算成英制长度\n"; • cout<<"---------------------------------------\n"; • cout<<"请选择:"; • cin>>select; • }while(select!='1'&&select!='2');

More Related