第 五 章 函数 调用
description
Transcript of 第 五 章 函数 调用
高级语言程序设计 (第 5章 )
第五章 函数调用
5.1 void 函数5.2 传值调用与传引用调用5.3 使用过程抽象5.4 测试和调试函数5.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);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);}
函数调用
函数声明
函数定义
高级语言程序设计 (第 5章 )
返回一个值的函数特征:1. 它是完成子任务的一个小程序;2. 传给这个小程序的实参是它的输入;它的传值调用形参是局部于函数的变量(局部变量),它接收主调程序传送的实参的值。
3. 它生成一个值作为它惟一的结果,这个返回值相当于这个小程序的输出。
总之,这样的函数总是返回一个值,它是黑盒函数定义的理想模式。事实上,一个子任务有三种情况:( 1)产生一个值;( 2)不产生值或其它子任务不需要它产生的值;( 3)产生多个值;
不返回值的函数称为 void 函数
高级语言程序设计 (第 5章 )
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语句
}
高级语言程序设计 (第 5章 )
5.1.2 void函数编程实例
例 5_1 将华氏温度转换为摄氏温度转换公式为: C=(5/9)(F-32)
华伦海托( 1714),德国物理学家,制定了华氏温度,他 发现水银气压表的指示刻度会随着温度的变化而变化 。
摄尔西乌斯( 1742),瑞典天文学家。依据冰水混合( 0oC)和与水的沸点( 100oC)制定了摄氏温度。
如: 104oF=40oC
高级语言程序设计 (第 5章 )
任务分解将一个总任务分解成四个子任务,每个子任务都
有一个独立的函数来完成:
将华氏温度转换为摄氏温度
屏幕初始化
主函数完成数据的输入
温度转换函数
温度输出函数
高级语言程序设计 (第 5章 )
函数的完整声明四个子任务由四个函数来实现,我们首先写出这三个函
数的完整声明(主函数不用声明):void initialize_screen();
//将当前输出与上个程序分开或清屏;
double celsuis(double fahrenheit);
//前条件:形参 fahrenheit是华氏温度。//后条件:将华氏温度转换为摄氏温度 ;
void show_results(double f_degree,double c_degree);
//显示华氏温度及相应的摄氏温度。
高级语言程序设计 (第 5章 )
函数的实现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是可选的 ,并可多次出
现
这个 return是必须的
高级语言程序设计 (第 5章 )
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是可选的 ,并可多次出现 , 它标志着函数运行
的终止。
高级语言程序设计 (第 5章 )
在主函数中调用自定义函数int main(){
double f,c;initialize_screen();cout<<"我们将华氏温度转换为摄氏温度! "<<endl;cout<<"请输入华氏温度: ";cin>>f;c=celsuis(f);show_results(f,c);return 0;
}
Void 函数的调用是一个独立的可
执行语句
高级语言程序设计 (第 5章 )
关于 return语句
return语句(称为返回语句)具有如下三种使用格式:return;return <表达式 >;return ( <表达式 > );
第一种格式的 return用于立即从被调函数中返回 , 当函数类型为 void时,应使用这种格式的返回语句。当函数类型为非 void型时,应使用第二或第三种格式的
return语句,此两种格式的语句效果完全相同(可将第二种格式看成是第三种格式的省略形式),系统此时都将计算
“ ”出表达式的值,并 携带 该值立即从被调函数中返回。
高级语言程序设计 (第 5章 )
5.2 值调用与引用调用
一个子任务的功能有三种情况: ( 1)产生一个值; ( 2)产生多个值;( 3)不产生值或其它子任务不需要它产生的值,但需要完成一项任务(如显示、存储文件等)。
引用形参能将函数产生的多个值返回
高级语言程序设计 (第 5章 )
5.2.1 引用参数的概念
若参数表中某参数的类型被指定为“ <类型 >
&”,则称该参数为引用参数,否则为赋值参数。如:void show_results(double f_degree,double c_degree);
//它所用的两个参数均为赋值参数。void swap(int& a, int& b);
//它所用的两个参数均为引用参数。 语法要求:调用函数时,引用参数对应的实参必须是指定类型的变量。
高级语言程序设计 (第 5章 )
对函数进行调用的执行过程(步骤):( 1) 将对应实参表达式的值赋给赋值形参(若参数为赋值参数的话);
( 2) 用实参变量替换相应的形参(若参数为引用参数的话);
( 3) “ ”按各形参的 当前值 (或已被“ ”赋值 ,或已被“ ”换名 )去执行一遍函数体并返回调用处。
f(1,2)___void f(int x,int y)
f(a,b)___void f(int &x,int &y)
高级语言程序设计 (第 5章 )
结论:
( 1 ) 通过赋值参数来传值的方式是一种“单向传值”方式,它只可向被调函数的形参“传入”值,而不可通过该形参“传出”值。
即函数中对形参的各种修改不改变实参。 ( 2 ) 通过引用参数来传值的方式是一种“双
向传值”方式,它不仅可向被调函数的形参“传入”值,而且还可通过该形参“传出”值。
即函数中对形参的任何修改都直接改变了实参。
高级语言程序设计 (第 5章 )
5.2.2 编程实例: swap函数例 5_2 交换内存中两个变量之值。函数描述即函数声明:
void swap (int& a,int& b);//交换形参 a与 b的值
a
3 4b
a
4 3b
交换后:
交换前:
高级语言程序设计 (第 5章 )
函数算法实现:
void swap(int &x,int &y)//引用参数//void swap(int a ,int b )//值参{
int t=a;
a=b;
b=t;
}
高级语言程序设计 (第 5章 )例程编码
“(实例演示 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;}
高级语言程序设计 (第 5章 )
//函数体void swap(int &x,int &y)//引用参数//void swap(int a ,int b )//值参{ int t=a;a=b;b=t; }
a
3 4
b
a4
b
3
实参
形参
按值传送 引用调用
a
3 4
b
x y
高级语言程序设计 (第 5章 )
思考
1.在什么情况下选用赋值参数?在什么情况下选用引用参数?
2. 比较赋值参数与引用参数各自的优缺点
赋值参数功能上的缺陷引用参数的副作用
高级语言程序设计 (第 5章 )
5.3 使用过程抽象
5.3.1 函数的嵌套调用与递归调用5.3.2 前条件与后条件5.3.3 案例分析 :超市定价系统
高级语言程序设计 (第 5章 )
5.3.1 函数的嵌套调用
1.函数嵌套的概念一个函数体中又包含了一个或多个函数的调用,称为函数的嵌套。
main() func1(x) func2(x)
高级语言程序设计 (第 5章 )
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;
}
高级语言程序设计 (第 5章 )
函数嵌套调用关系
main() order(x) swap(x)
高级语言程序设计 (第 5章 )
3. 函数的递归调用一个函数体中又调用了它自已,称为函数的递归调用。
main() function(x) function(x)
高级语言程序设计 (第 5章 )
//递归函数的定义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”
高级语言程序设计 (第 5章 )
5.3.2 前条件与后条件为函数声明写注释信息时,可将说明信息分为两种。
前条件: 指出函数调用时要满足的条件,称为前条件 ;
后条件: 对函数调用结果的描述,即在满足前条件的前提下,指出函数执行之后将满足什么条件(得到什么结果),称为后条件。 具体的说就是对于要返回一个值的函数,后条件是对该返回值的描述;对于产生多个返回值的函数后条件是对这批值的描述,实际是对引用参数的修改描述。
高级语言程序设计 (第 5章 )
如:void swap (int& a,int& b);
//前条件: a,b已被赋值//后条件 :交换 a与 b的值
double celsuis(double fahrenheit);
//前条件:形参 fahrenheit是华氏温度。//后条件:将华氏温度转换后的摄氏温
度 ;
高级语言程序设计 (第 5章 )
5.3.3 案例分析 :超市定价系统1.问题定义
Quick_shop连锁超市的定价策略:预计当 7天之内售出时 (<=7):
商品零售价 =批发价 +批发价 *5%
预计当 7天之后才能售出时( >=8):商品零售价 =批发价 +批发价 *10%
输入:商品批发价(进价)、预计售出的天数 输出:商品零售价
高级语言程序设计 (第 5章 )
2.问题分析
将这个问题分成三个子任务:( 1)输入数据;( 2)计算商品零售价;( 3)输出结果。
三个任务由三个函数来完成:
1 )输入函数void get_input(double &cost,int &turnover);
//前条件:用户准备好从键盘输入二个正确数据至内存//后条件: cost设为一商品的批发价, rurnover为商品预计售出的天数
高级语言程序设计 (第 5章 )
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的值
高级语言程序设计 (第 5章 )
3.算法设计
//返回商品的零售价double price(double &cost,int &turnover)
{
if(turnover>THRESHOLD)
return cost+cost*LOW_MARKUP;
else
return cost+cost*HIGH_MARKUP;
}
高级语言程序设计 (第 5章 )
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);
}
高级语言程序设计 (第 5章 )
5.程序测试
(1)输入的种类低涨幅: 5%
高涨幅: 10%
(2)边界值测试预计售出天数
THRESHOLD=7
相差 1错误:THRESHOLD=6
THRESHOLD=8
高级语言程序设计 (第 5章 )
ERROR1:">"--"<";
高级语言程序设计 (第 5章 )
高级语言程序设计 (第 5章 )
ERROR2;"<"__"<="
高级语言程序设计 (第 5章 )
5.4 测试和调试函数
1.驱动程序测试法写一个特殊的程序,以尽可能简单的方法为函数获取参数值,然后执行函数,并显示结果。
高级语言程序设计 (第 5章 )
函数 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”
高级语言程序设计 (第 5章 )
2. stub(占位函数)测试法
在测试一个函数 A时,要用到另一个还没有被测试的函数 B,用 B的简化版替代 B,则称此 B的简化版为 stub.
高级语言程序设计 (第 5章 )
这是一个占位函数( 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”
高级语言程序设计 (第 5章 )
5.5 常规调试技术1. 常见错误( 1)未初始化的变量;( 2)相差 1错误; //<——<==
( 3)超过数据边界; //35!
( 4)自动类型转换; //5/9,重载函数形参( 5 “)该用 ==” “的地方用了 =”。 //逻辑表达式中2.定位错误( 1)利用 cout语句设置跟踪标志( 2)利用调试器( debugger)设置断点。
高级语言程序设计 (第 5章 )
3.利用调试器调试程序( 1)利用调试器( debugger)设置断点
1)设置固定断点鼠标左单击某个有效语句行首,单击【 F9】键,
该行左端出现圆点标记,说明该行设置了断点,调试到该行就会临时中断,单击【 F5】继续调试 .
2 ) 设置与条件相关的断点使用【 edit】菜单下的【 Breakpoint】命令可以设
置与某个条件有关的断点。( 2)调试执行调试命令,单击【 F5】键即可,继续执行,仍单击【 F5】键。
高级语言程序设计 (第 5章 )
5.6 案例分析 :长度的换算1.问题定义
5_8 写一个程序,要求它读入一个用成米和厘米表示的长度,换算英尺和英寸。或它读入一个用英尺和英寸成表示的长度,换算米和厘米 , 采用那种换算由用户选择。
1 英尺 =0.3048 米, 1米 =100 厘米,1 英尺 =12 英寸。
高级语言程序设计 (第 5章 )
长度的换算的功能目标
高级语言程序设计 (第 5章 )
2.问题分析将这个问题分成四个层次的子任务 (共11个小任务 )
main()
menu_select()
Britesh_metric() metric_British()
input_British(…)British_metric(…) give_results(…)
input_British(…)metric_British (…) give_results(…)
introduction()
高级语言程序设计 (第 5章 )
//函数声明部分void introduction();//本系统的说明void menu_select();//后条件:根据用户的选择,执行相应的换算
void British_metric();//执行英制到公制的转换过程void metric_British();//执行英制到公制的转换过程
void input_metric(double &meter,double ¢imeter);//前条件:用户准备好从键盘输入二个正确数据至内存//后条件:meter和 centimetetr为一个长度的米数和厘米数
void input_British(double &food,double &inch);//前条件:用户准备好从键盘输入二个正确数据至内存//后条件: food和 inch设为一个长度的英尺数和英寸数
高级语言程序设计 (第 5章 )
void British_metric(double food,double inch,double &meter,double ¢imeter);
//前条件: 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的值
高级语言程序设计 (第 5章 )
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');
高级语言程序设计 (第 5章 )
if(select=='1') {
cout<<"将一个英制长度换算成公制长度 \n";British_metric();
} else {
cout<<"将一个公制长度换算成英制长度 \n";metric_British();
}}
高级语言程序设计 (第 5章 )
4.程序编码(完整编码见习题 5_8)void main()
{
system("color f0");
char ans;
introduction();
do
{
menu_select();
cout<<"继续吗?( y or n) ";
cin>>ans;
}while(ans=='y'||ans=='Y');
}
高级语言程序设计 (第 5章 )
5.程序测试
程序测试输入下述几组数据,写出程序执行结果0 米 0 厘米—— 0 英尺 0 英寸0 米 2.54 厘米—— 0 英尺 1 英寸1 米 0 厘米—— 3 英尺 3 英寸30米 48 厘米—— 99 英尺 11 英寸
0 英尺 0 英寸—— 0 米 0 厘米1 英尺 0 英寸—— 0 米 30 厘米0 英尺 12 英寸—— 0 米 30 厘米6 英尺 9 英寸—— 2 米 4 厘米100 英尺 0——30米 48 厘米
高级语言程序设计 (第 5章 )
5_12习题程序的结构
Britesh_metric_weight() metric_British_weight ()
input_British_weightBritish_metric_weight output_weight
input_British_weightmetric_British_weight output_weight
Britesh_metric_length metric_British_length ()
input_British_lengthBritish_metric_length output_length
input_British_lengthmetric_British_length output_weight
main()
menu_select() introduction()
menu_select_weight () menu_select_length ()
高级语言程序设计 (第 5章 )
小结函数的功能不一定仅仅是求一个数值。一个 c++函数还可以求出多个数值。一个 c++函数通常可以完成一项任务。函数有声明、定义、调用之分。函数有参数。定义时的参数称为形参,调用时的参数称为实参。根据参数的作用不同,又分为传值参数、引用参数。设计函数时,首先要搞清楚前条件、后条件。对设计的函数要进行科学严密的测试。
高级语言程序设计 (第 5章 )
书面作业1.P170 自测题 6.2.P178 自测题 7.3.P185 自测题 134.P188 自测题 19,225.P195 编程项目 第 6,7,8 小题补充作业题:利用递归函数计算 e=1+1/1!+1/2!+…+1/n! ,其中 n为正整数。
补充选作题: 利用递归函数计算组合数 ,其中m,n为正整数。
利用递归函数求菲波那契数列的第 n项(见 P116 ex3_10)。
Cmn
高级语言程序设计 (第 5章 )
实验四 函数实验类型 :综合型实验目的:1.进一步熟悉 VC++6.0集成开发环境;2.进一步熟悉控制结构程序设计方法;3.掌握函数的定义和调用方法;4.掌握函数嵌套(或递归)调用的方法;5.理解变量的作用域和生存期;
高级语言程序设计 (第 5章 )
实验内容:1.编制程序,利用递归函数计算 e=1+1/1!+1/2!+…+1/n! 其中 n为正整数。分别输入 n=0、 1、 10、 170、 171,测试程序,写出对应的每个输入值的程序的运行结果,并与理论值进行比较。
2. “ ”参考例程 超市定价系统 ,假设函数 get_input和 give_output都已通过测试, price函数还没有测试,试写出利用 stub方法测试函数 introduction的程序源代码。
( 1)写出测试运行结果;( 2)分析程序中全局常量与局部变量的作用域与生存期。