版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C++高级语言程序设计第5章函数北京邮电大学信息与通信工程学院程序设计中,把具有一定功能的程序模块用函数或类来实现。2025/9/27北京邮电大学信息与通信工程学院-2-第5章函数内容函数定义、声明、函数的调用、函数参数传递机制函数的特殊形式,包括递归函数、内联函数、带默认参数值的函数标识符的作用域和可见性变量的存储类型和生存期2025/9/27北京邮电大学信息与通信工程学院-3-5.1函数概述结构化程序设计,将整个程序自顶向下分为若干个程序模块,每个模块用来实现一个特定的功能。C++中的模块以函数和类的形式实现。函数是具有一定功能又经常使用的相对独立代码段。无论是面向过程的程序设计还是面向对象的程序设计,函数都是一种实现算法的重要形式。2025/9/27北京邮电大学信息与通信工程学院-4-5.1函数概述函数接口(规定接口形式)函数名(命名规则与变量相同,见名知意)函数类型(返回值类型)形式参数表函数体(实现算法—三种基本结构组合而成)常用的函数C++的库函数自定义的函数2025/9/27北京邮电大学信息与通信工程学院-5-5.1.1自定义函数概述编程者在处理具体问题时,将程序中多处使用的、实现一定功能的特定代码段定义成函数。这样的函数称为自定义函数。在同一个程序中,一个函数只能定义一次。一般是通过函数调用来使用函数。函数调用需要指定函数名并且提供被调用函数所需的信息(即函数参数)。2025/9/27北京邮电大学信息与通信工程学院-6-5.1.1自定义函数概述例如要打印某一年某一月的月历2025/9/27北京邮电大学信息与通信工程学院-7-5.1.2库函数概述C++
标准库提供了丰富的函数集合,可以进行常用的数学计算、字符串操作、字符操作、输入/输出、错误检查和许多其他操作。要熟悉C++
标准库提供的类和函数集合,不要事事从头做起,要尽可能利用C++
标准库提供的函数,以便减少程序开发的时间。这是程序设计的技巧之一。2025/9/27北京邮电大学信息与通信工程学院-8-5.1.2库函数概述数学库函数实现常见的数学计算使用时,在程序中嵌入cmath头文件,按对应库函数的接口形式写调用语句。调用数学函数:函数名(参数1,…,参数n)
例如:doublex;x=sqrt(900.0);cout<<x;数学函数库中的多数函数都返回double类型结果。2025/9/27北京邮电大学信息与通信工程学院-9-2025/9/27北京邮电大学信息与通信工程学院-10-常用数学库函数函
数说
明举
例ceil(x)将x取整为不小于x的最小整数ceil(9.2)
=
10ceil(−9.8)
=
−9cos(x)x(弧度)的余弦cos(0.0)
=
1.0exp(x)指数函数exexp(1.0)=
2.71828exp(2.0)
=
7.38906fabs(x)x的绝对值fabs(−5)
=
5floor(x)将x取整为不大于x的最大整数floor(9.2)
=
9floor(−9.8)
=
−10fmod(x,y)x/y的浮点数余数fmod(13.657,2.333)
=
1.992log(x)x的自然对数(底数为e)log(2.718282)
=
1.0log(7.389056)
=
2.0log10(x)x的对数(底数为10)log(10.0)
=
1.0 log(100.0)
=
2.0pow(x,y)x的y次方(xy)pow(2,7)
=
128pow(9,0.5)
=
3sin(x)x(弧度)的正弦sin(0.0)
=
0sqrt(x)x的平方根sqrt(900.0)
=
30.0tan(x)x(弧度)的正切tan(0.0)
=
02025/9/27北京邮电大学信息与通信工程学院-11-#include<iostream>#include<cmath>usingnamespacestd;intmain(){ cout<<"EnterQuadraticcoefficients:"; doublea,b,c; cin>>a>>b>>c; if((a!=0)&&(b*b-4*a*c>0)){ doubleradical=
sqrt(b*b-4*a*c);
doubleroot1=(-b+radical)/(2*a); doubleroot2=(-b-radical)/(2*a); cout<<"Roots:"<<root1<<""<<root2; } else{ cout<<"Doesnothavetworealroots"; } return0;}调用函数或主调函数被调函数库函数2025/9/27北京邮电大学信息与通信工程学院-12-#include<iostream>usingnamespacestd;floatCircleArea(floatr);intmain()//managecirclecomputation{cout<<"Enterradius:";floatMyRadius;cin>>MyRadius;floatArea=
CircleArea(MyRadius);
cout<<"Circlehasarea"<<Area;return0;}//CircleArea():computeareaofradiusrcirclefloatCircleArea(floatr){constfloatPi=3.1415;returnPi*r*r;}自定义函数5.2函数定义及使用2025/9/27北京邮电大学信息与通信工程学院-13-一个C++控制台程序可以由一个主函数(main()函数)和若干子函数构成。主函数main()是程序执行的开始点,由主函数调用子函数,子函数还可以再调用其他子函数。调用其他函数的函数被称为主调函数。被其他函数调用的函数称为被调函数。一个函数既可以是主调函数,又可以是被调函数(main()除外)。5.2.1函数的定义
每一个函数都是一个具有一定功能的语句模块,函数定义的语法形式:
返回值类型
函数名(形式参数表){
函数体(变量声明和执行语句)}2025/9/27北京邮电大学信息与通信工程学院-14-约定接口形式函数体完成功能intmaximum(intx,inty){intmaxv;maxv=x>=y?x:y;returnmaxv;}2025/9/27北京邮电大学信息与通信工程学院-15-
floatCircleArea(floatr){ constfloatPi=3.1415; returnPi*r*r; }5.2.1函数的定义
函数体返回值语句局部变量定义形式参数函数类型函数名5.2.1函数的定义函数名是函数体代码段的外部标识符函数定义之后,即可通过函数名调用函数。例://Sum():computesumofintegersina...bint
Sum(inta,intb){ intTotal=0; for(inti=a;i<=b;++i) { Total+=i; } returnTotal;} 2025/9/27北京邮电大学信息与通信工程学院-16-5.2.1函数的定义函数的形式参数表,简称形参表形式:
(类型1形式参数1,…,类型n
形式参数n)
2025/9/27北京邮电大学信息与通信工程学院-17-//Sum():computesumofintegersina...bintSum(inta,intb){ intTotal=0; for(inti=a;i<=b;++i){ Total+=i; } returnTotal;}形式参数表示主调函数和被调函数之间需要交换的信息(1)传给被调函数的待处理的数据;(2)控制被调函数执行操作的信息;(3)被调函数执行的结果。形式参数表从参数的类型、个数、排列顺序上规定了主调函数和被调函数之间信息交换的形式。floatfunc(intk,intb,floatx){returnk*x+b;}2025/9/27北京邮电大学信息与通信工程学院-18-5.2.1函数的定义如果函数之间没有需要交换的信息,也可以没有形参,形参表内写void或空着。intRead(){ cout<<"Enternumber(integer):"; intResponse; cin>>Response; returnResponse;}2025/9/27北京邮电大学信息与通信工程学院-19-5.2.1函数的定义5.2.1函数的定义函数体是实现函数功能的代码部分变量声明完成函数功能的语句两部分从组成结构看,函数体是由程序的三种基本控制结构即顺序、选择、循环结构组合而成的。2025/9/27北京邮电大学信息与通信工程学院-20-intSum(inta,intb){ intTotal=0; for(inti=a;i<=b;++i)Total+=i; returnTotal;}2025/9/27北京邮电大学信息与通信工程学院-21-函数是由函数名、函数类型、形参表和函数体四部分组成的,使用时通过函数名和参数表调用函数.
例:编写一个函数cube,计算整数的立方。调用函数cube计算从1到10相邻整数的立方差。2025/9/27北京邮电大学信息与通信工程学院-22-尽可能避免在循环体内调用函数!!!//计算整数的立方#include<iostream>using
namespace
std;int
cube(int);//函数原型声明void
main(){
int
last,cb;
last=1;
cout<<"thedifferenceofcube:"<<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;}2025/9/27北京邮电大学信息与通信工程学院-23-//在三个浮点中找出最大值#include<iostream>using
namespace
std;float
maximum(float
x,float
y,float
z);//函数原型声明
void
main(){
float
a,b,c;
cout<<"Enterthreefloatingnumbers:";
cin>>a>>b>>c;
//调用maximum函数,a,b,c为实际参数
cout<<"Maximumis:"<<maximum(a,b,c)<<endl;//函数调用}例:在三个浮点中确定最大值,使用自定义函数maximum完成。2025/9/27北京邮电大学信息与通信工程学院-24-//maximum函数定义//函数的形式参数x,y,zfloat
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
++
语言不允许函数嵌套定义,所有函数的定义都是自成一体,即函数体中只包含实现其自身功能的基本语句,不可包含其他函数的定义体。2025/9/27北京邮电大学信息与通信工程学院-25-5.2.2函数原型引用函数之前,要先指定函数的接口形式函数原型函数定义函数原型声明格式:
函数类型函数名(形式参数表);例:intMax(inta,intb);函数原型声明使编译器获得关于函数名称、函数类型、函数形参个数、形参类型和形参顺序的信息。函数调用时,编译器根据函数原型声明验证函数调用正确与否。
2025/9/27北京邮电大学信息与通信工程学院-26-5.2.2函数原型程序中,如果调用自定义的函数,且函数定义在后,调用在先,则必须在调用函数之前有函数原型声明。voidsubfun1(intx,floata,floatb);//原型声明main(){
intx=20;floata=1.0f,b=0.5f;subfun1(…);//函数调用┆}voidsubfun1(intx,floata,floatb)//函数定义{
…}2025/9/27北京邮电大学信息与通信工程学院-27-5.2.2函数原型如果是函数定义在先,调用在后,则不必进行函数原型声明。因为编译器已经从函数定义得到关于函数的信息。voidsubfun1(intx,floata,floatb)//函数定义{
…}main(){
┆subfun1(i,f1,f2);//函数调用┆}
2025/9/27北京邮电大学信息与通信工程学院-28-5.2.2函数原型源文件中,如果在所有函数定义体之外声明函数原型,则该函数可被位于其原型声明之后的所有函数调用。2025/9/27北京邮电大学信息与通信工程学院-29-voidsubfun1(…);//原型声明main(){
┆subfun1(…);//函数调用┆}voidsubfun2(){
┆subfun1(…);//函数调用┆}voidsubfun1(…)//函数定义{
…}main(){voidsubfun1(…);//函数原型声明
┆
subfun1(…);//函数调用┆}voidsubfun2(){
┆subfun1(…);//函数调用,┆}voidsubfun1(…){
…}2025/9/27北京邮电大学信息与通信工程学院-30-错误,编译器不识别sunfun1标识符。5.2.2函数原型库函数的声明在相应库的头文件中,使用库函数时要包含对应的头文件。例:#include<cmath>
调用数学库函数:
sqrt(…)sin(…)abs(…)
……2025/9/27北京邮电大学信息与通信工程学院-31-2025/9/27北京邮电大学信息与通信工程学院-32-常用C++标准库头文件cassert包含增加诊断以帮助程序调试的宏和信息cctype包含测试某些字符属性的函数原型和将小写字母变为
大写字母、将大写字母变为小写字母的函数原型cmath包含数学库函数的函数原型cstdio包含标准输入/输出库函数的函数原型及其使用的信息cstdlib包含将数字变为文本、将文本变为数字、内存分配、随机数和各种其他工具函数的函数原型cstring包含C语言方式的字符串处理函数原型ctime 包含操作时间和日期的函数原型和类型iostream包含标准输入/输出函数原型iomanip包含能够格式化数据流的流操纵运算子的函数原型fstream包含和磁盘文件读/写有关的函数原型5.2.2函数原型例5-2计算3个整数绝对值的平均值。2025/9/27北京邮电大学信息与通信工程学院-33-2025/9/27北京邮电大学信息与通信工程学院-34-//例5-2计算3个数绝对值的平均值#include<iostream>#include<cmath>usingnamespacestd;intCalAbsMean(inta,intb,intc);//自定义函数的原型声明voidmain(){inta,b,c;cout<<"输入a,b,c:";cin>>a>>b>>c;cout<<"绝对值的均值为:"<<CalAbsMean(a,b,c)<<endl;}intCalAbsMean(inta,intb,intc){intsum=abs(a)+abs(b)+abs(c);sum/=3;returnsum;}运行结果:输入a,b,c:-1020-30
绝对值的均值为:205.2.3return语句return语句使程序执行流程从被调函数返回主调函数,有两种形式:(1)不返回值的形式
return;(2)返回值的形式
return表达式;2025/9/27北京邮电大学信息与通信工程学院-35-intSum(inta,intb){ intTotal=0; for(inti=a;i<=b;++i) Total+=i;
returnTotal;}void
DisplayMessage(){
cout<<"只显示确定信息的简单函数不带参数"<<endl;return;}函数返回值类型规定了函数返回给主调函数的值的类型,也称为函数类型。
当被调函数只需要把一个数值结果返回给主调函数时,使用return语句返回比较合适。由return语句返回的值的类型必须与函数返回值类型一致。若表达式的结果与函数类型不一致,不能通过编译,需要作强制类型转换,将表达式的类型强制成与函数类型。例如,如果mean是float型,而函数是int型,则return语句应为:
return(int)mean;
2025/9/27北京邮电大学信息与通信工程学院-36-intSum(inta,intb){ intTotal=0; for(inti=a;i<=b;++i) Total+=i;
returnTotal;}5.2.3return语句5.2.3return语句注意如果不需要向主调函数返回值,函数可以定义成无类型的,函数类型写成void,函数结束时也不必用return语句。例:
voiddisplay(){cout<<“noreturn”<<endl;}2025/9/27北京邮电大学信息与通信工程学院-37-5.2.3return语句例5-3根据输入的颜色符号,显示不同的字符串表示的不同颜色。2025/9/27北京邮电大学信息与通信工程学院-38-2025/9/27北京邮电大学信息与通信工程学院-39-//例5-3根据输入的颜色符号,显示不同的字符串表示的不同颜色#include<iostream>usingnamespacestd;voidDispColor(charcolor);voidmain(){charcolor;cout<<"选择颜色(r-read,g-green,b-blue):";cin>>color;DispColor(color);}2025/9/27北京邮电大学信息与通信工程学院-40-//根据输入,显示颜色字符串voidDispColor(charcolor){switch(color){case'r':cout<<"red.";break;case'g':cout<<"green.";break;case'b':cout<<"blue";break;default:break;}return;}5.2.3return语句例5-4从输入文件中读入学生人数和每人考试成绩,统计成绩的平均值。2025/9/27北京邮电大学信息与通信工程学院-41-2025/9/27北京邮电大学信息与通信工程学院-42-//例5-4.从输入文件中读入学生人数和每人考试成绩,统计成绩均值。#include<iostream>#include<fstream>usingnamespacestd;intCalMean(charchFileName[]); //函数原型声明voidmain(){charchFileName[80]="";cout<<"输入文件名:";cin>>chFileName;//输入文件名
intmean=ChlMean(chFileName);//得到平均值
cout<<"平均值="<<mean<<endl;}2025/9/27北京邮电大学信息与通信工程学院-43-//计算均值,函数定义如下intCalMean(charchFileName[]) {intcount; //数据个数
intscore; //分数
intsum(0),mean;ifstreaminfile(chFileName);if(!infile)cout<<"!infile"<<endl;infile<<count;cout<<"成绩个数:";
cout<<count<<endl;cout<<"成绩:"<<endl;while(infile>>score)//从文件读取成绩,并累计总成绩;
{ cout<<score<<""; sum+=score; //累积分数
}cout<<endl;if(count>0)mean=sum/count; //计算平均值
elsemean=0;returnmean;//将平均值返回主调函数}运行结果:
成绩个数:10
成绩:59392436879852675260
平均值=575.2.4函数调用方式函数语句函数语句形式:函数名(实参数表);TriAreabySide(a,b,c);
函数表达式函数调用出现在表达式中,形式:函数名(实际参数表)x=max(a,b);y=sqrt(x);此时函数要使用return语句向主调函数返回一个确定的值,参与它所在的表达式的运算。floatmax(floata,floatb){returna>=b?a:b;}函数参数
函数参数调用方式是将函数调用写在另一次函数调用的实际参数位置。例如:m=max(a,max(b,c));
2025/9/27北京邮电大学信息与通信工程学院-44-5.2.4函数调用方式实际参数表可简称为实参表,是按与被调函数形式参数表一一对应的格式组织的参数表,即参数的类型、个数和排列顺序必须与被调函数声明的形式参数表严格一致。实际参数表的各实际参数以逗号间隔,实际参数可以是常量、变量或表达式,变量和表达式必须具有确定值。如果被调函数无形式参数,则实参表也是空的。实际编程中,从可读性考虑,一般使用变量作为实际参数。2025/9/27北京邮电大学信息与通信工程学院-45-例:计算y=kx+b的函数floatfunc(intk,intb,floatx){returnk*x+b;}voidmain(){intk,b;floatx,y;cin>>k>>b>>x;y=func(k,b,x);}例:找最高分数
intFindMaxValue(intarray[],intn){intmaxValue=array[0];for(intk=1;k<n;k++){if(array[k]>maxValue)maxValue=array[k];}returnmaxValue;}
voidmain(){intscore[30],num=30;for(intk=0;k<num;k++){cin>>score[k];}intmaxScore=FindMaxScore(score,num);cout<<maxScore<<endl;}2025/9/27北京邮电大学信息与通信工程学院-46-实际参数以数据值(值传递)或实际存储空间(地址传递)提供了形式参数所需的内容。#include<iostream>using
namespace
std;void
DisplayMessage();void
main(){
DisplayMessage();//函数调用语句}void
DisplayMessage(){
cout<<"只显示确定信息的简单函数不带参数"<<endl;}2025/9/27北京邮电大学信息与通信工程学院-47-如果被调函数无形参,则实参表也是空的。5.2.4函数调用方式5.2.4函数调用方式例5-5编写程序,实现坐标旋转公式:2025/9/27北京邮电大学信息与通信工程学院-48-2025/9/27北京邮电大学信息与通信工程学院-49-//实现坐标旋转公式#include<iostream>#include<cmath>using
namespace
std;
void
main(){ const
double
PI=3.14;
int
x,y;//旋转后坐标
int
x0,y0;//原始坐标
int
angle;//旋转角度//输入数据
cout<<"inputpoint(x,y):";
cin>>x0>>y0;
cout<<"inputangleofrotation:";
cin>>angle;
//计算旋转后的坐标
double
theta=angle*PI/180;
x=x0*cos(theta)-y0*sin(theta);
y=x0*sin(theta)+y0*cos(theta);
//输出结果
cout<<"x="<<x<<endl;
cout<<"y="<<y<<endl;}5.3函数调用的执行机制和参数传递方式函数调用过程是如何实现的?程序执行流程能够从主调函数到被调函数,再由被调函数正确返回主调函数的断点继续执行,是基于函数调用工作栈来实现的。函数的参数传递方式值传递地址传递2025/9/27北京邮电大学信息与通信工程学院-50-5.3.1函数调用的执行机制栈是函数调用正确执行的物理基础.栈是一种数据结构,它的工作原理就像在子弹匣压子弹一样,最先压入的子弹要等到最后才飞射出去,而最后压入的子弹则首先飞射出去。2025/9/27北京邮电大学信息与通信工程学院-51-004010560040105700401058004010590040105A0040106BABCD栈的管理原则:先进后出或后进先出5.3.1函数调用的执行机制函数调用能够正确执行的物理基础是操作系统在内存中开辟了一块叫做栈的内存空间。断点工作记录断点地址被调函数的形式参数自动局部变量2025/9/27北京邮电大学信息与通信工程学院-52-5.3.1函数调用的执行机制例5-6从键盘输入屏幕上两点的坐标(x,y),计算两点之间的距离。(分析函数调用时活动记录)2025/9/27北京邮电大学信息与通信工程学院-53-2025/9/27北京邮电大学信息与通信工程学院-54-void
main(){ int
x1,y1,x2,y2;//两点坐标
float
dist;//两点间距离
cout<<"inputpoint1(x1,y1):";
cin>>x1>>y1;
cout<<"inputpoint2(x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distancebetweenpoint("<<x1<<","<<y1<<")andpoint("<<x2<<","<<y2<<"):"<<dist<<endl;}
栈main函数中的自动局部变量断点地址…仅一个工作记录活动工作记录2025/9/27北京邮电大学信息与通信工程学院-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;}
栈main函数中的自动局部变量断点地址…工作记录示意工作记录CalDistance函数中的自动局部变量断点地址…活动工作记录5.3.2函数的参数传递方式函数之间的信息交换的一种重要形式是函数的参数传递,由函数的形式参数和实际参数实现。函数在没有被调用时,函数的形式参数并不占有实际的内存空间,也没有实际的值。C++语言中函数的参数传递方式分为两种:·值传递·地址传递2025/9/27北京邮电大学信息与通信工程学院-56-2025/9/27北京邮电大学信息与通信工程学院-57-值传递如果函数的形式参数为普通变量,当函数被调用时,系统为这些形式参数分配内存空间,并用实际参数值初始化对应的形式参数,形式上实际参数的值传递给了形式参数。这就是函数调用时参数的值传递。值传递方式,实际参数和形式参数各自占有自己的内存空间;参数传递方向只能由实际参数到形式参数;不论函数对形式参数作任何修改,对相应的实际参数都没有影响。5.3.2函数的参数传递方式5.3.2函数的参数传递方式例5-7从键盘输入两整数,交换次序后输出。
2025/9/27北京邮电大学信息与通信工程学院-58-2025/9/27北京邮电大学信息与通信工程学院-59-//演示函数参数值传递单向性的例程#include<iostream.h>void
swap(int
a,int
b);int
main(){
int
x(5),y(10);
cout<<"x="<<x<<"y="<<y<<endl;
swap(x,y);
cout<<"x="<<x<<"y="<<y<<endl;
return0;}510xy10241028运行结果:
x=5y=10 x=5y=102025/9/27北京邮电大学信息与通信工程学院-60-void
swap(int
a,int
b){
int
t;
t=a;
a=b;
b=t;}5a204810b2052t20565105编程技巧:交换两个变量的值,需要引入第三个变量缓存数据。例如果一个数的所有真因子(包括1,但不包括这个数本身)之和正好等于这个数本身,则称此数为完美数。例如:6=1×2×3,而1+2+3=6;28=1×4×7=1×2×14,而1+2+4+7+14=28。如何确定完美数,欧几里得发现,只要是一个素数,则一定是一个完美数。编写程序找出最小的5个完美数。2025/9/27北京邮电大学信息与通信工程学院-61-体会函数参数的值传递2025/9/27北京邮电大学信息与通信工程学院-62-//寻找最小的五个完美数#include<iostream>#include<cmath>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);//计数器
2025/9/27北京邮电大学信息与通信工程学院-63-
while(counter<5) { temp=power(2,n);
num=temp-1;
if(DecidePrime(num)) {perfect_number=temp/2*num;
cout<<"n="<<n<<","<<"perfectnumber="<<perfect_number<<endl;
counter++; }
n++; }}2025/9/27北京邮电大学信息与通信工程学院-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;}2025/9/27北京邮电大学信息与通信工程学院-65-
//判别素数bool
DecidePrime(unsigned
int
number){ unsigned
int
i,k;k=sqrt(number);
for(i=2;i<=k;i++){
//找number的因数
if(number%i==0)
break; }if(i>=k+1)//判断number是否被小于number的数整除
return
true;
else
return
false;}5.3.2函数的参数传递方式地址传递地址变量做形参数组名指针变量引用2025/9/27北京邮电大学信息与通信工程学院-66-5.3.2函数的参数传递方式冒泡排序intarray[5]={5,4,3,2,1};2025/9/27北京邮电大学信息与通信工程学院-67-5.3.2函数的参数传递方式例5-9用整型数组存储数据,编写冒泡排序函数BubbleSort(),在主调函数中用随机数产生函数生成数组元素,并输出排序的结果。2025/9/27北京邮电大学信息与通信工程学院-68-2025/9/27北京邮电大学信息与通信工程学院-69-//例5-9基于数组的冒泡排序例#include<iostream>#include<ctime>usingnamespacestd;voidBubbleSort(intarray[],intn);//函数原型声明2025/9/27北京邮电大学信息与通信工程学院-70-voidmain(){constintN=20;intarray[N]={0};srand((unsignedint)time(NULL));intk;cout<<"待排序数据:"<<endl;for(k=0;k<N;k++)//数据生成
{ array[k]=rand()%100; cout<<array[k]<<",";}BubbleSort(array,N); //调用排序函数
cout<<endl<<"排序后数据:"<<endl;for(k=0;k<N;k++)//数据生成
{ cout<<array[k]<<",";}cout<<endl;}2025/9/27北京邮电大学信息与通信工程学院-71-//冒泡排序voidBubbleSort(inta[],intn){inttemp;for(intpass=1;pass<n;pass++) //共比较size-1轮
{ for(intk=0;k<n-pass;k++)//比较一轮
{ if(a[k]>a[k+1]){temp=a[k];a[k]=a[k+1];a[k+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(),矩阵用二维数组表示,函数接口如下:voidTransposeMatrix(intmatrix[][N],inttMatrix[][M],introws,intcols);2025/9/27北京邮电大学信息与通信工程学院-72-注意(2)多维数组名作为形式参数,只可以省略第一维(最左边)的大小,也可以不省略。在被调函数中访问这个形式上的数组时,切忌下标越界问题。2025/9/27北京邮电大学信息与通信工程学院-73-5.4递归函数和递归调用递归函数是函数的一种特殊形式,适合实现数学上的一些递归问题。使用递归函数可以简单明了地表达算法(算法的可读性好),但算法的效率一般不高。2025/9/27北京邮电大学信息与通信工程学院-74-5.4.1嵌套调用C++的函数不能嵌套定义
C++的函数可以嵌套调用
2025/9/27北京邮电大学信息与通信工程学院-75-不能嵌套定义voidmain(){intx,y;
intsub(inta,intb){intc=a+b;}}
可以嵌套调用main()DecidePrime(…)sqrt(…)if(DecidePrime(num))k=sqrt(number);
5.4.2递归函数和递归调用递归函数是函数体内有调用函数自己的语句或通过其它函数间接调用函数自己的函数。递归调用是调用递归函数而形成的一种函数调用方式。递归函数用于实现数学中的递归问题比较直观方便。2025/9/27北京邮电大学信息与通信工程学院-76-经典递归调用问题
阶乘定义式:
2025/9/27北京邮电大学信息与通信工程学院-77-2025/9/27北京邮电大学信息与通信工程学院-78-#include<iostream>using
namespace
std;int
factorial(int
n);void
main(){
cout<<"enterapositioninteger:";
int
n,n_fact;
cin>>n;
n_fact=factorial(n);
cout<<"thefactorialof"<<n<<"is:"<<n_fact<<endl;}返回地址12025/9/27北京邮电大学信息与通信工程学院-79-int
factorial(int
n){
intfn;
if(n==0)fn=1;
elsefn=n*factorial(n-1);
returnfn;}返回地址2n=3地址1栈状态fn=?n=2地址2fn=?n=1地址2fn=?n=0地址2断点地址参数局部变量toptoptoptop实例演示2025/9/27北京邮电大学信息与通信工程学院-80-int
factorial(int
n){
intfn;
if(n==0)fn=1;
elsefn=n*factorial(n-1);
returnfn;}返回地址2n=3地址1栈状态fn=?n=2地址2fn=?n=1地址2fn=1n=0地址2topfn=1n=1地址2fn=2n=2地址2toptoptop递归问题的求解实际分成两个阶段:化简问题的递推阶段;达到递归终止条件得到基本情况的结果,并逐步回推结果阶段。递归函数的主要两部分
具有更简单参数的递归调用
停止递归的终止条件(递归终止条件)
2025/9/27北京邮电大学信息与通信工程学院-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).其中%是求余运算符。2025/9/27北京邮电大学信息与通信工程学院-82-xy1088220xy1228281212440理解递归问题2025/9/27北京邮电大学信息与通信工程学院-83-//计算x和y的最大公约数(递归函数)#include<iostream>using
namespace
std;
int
GcommonDivisor(int
x,int
y);
void
main(){int
x,y;cout<<"inputx,y:";
cin>>x>>y;
cout<<"thegreatestcommondivisorof"<<x<<"and"<<y<<":" <<GcommonDivisor(x,y)<<endl;}
地址12025/9/27北京邮电大学信息与通信工程学院-84-int
GcommonDivisor(int
x,int
y){intgcd;
if(y==0)
gcd=x;
else
gcd=GcommonDivisor(y,x%y);returngcd;}
以输入10,8为例地址2X(10)y(8)地址1gcd=?X(8)y(2)地址2gcd=?X(2)y(0)地址2gcd=?X(2)y(0)地址2gcd=2X(2)y(0)地址2gcd=2X(8)y(2)地址2问题:用循环能实现吗?(作业)5.5内联函数
函数调用时,系统首先要保存主调函数的相关信息,再将控制转入被调函数,这些操作增加了程序执行的时间开销。C++提供的内联函数形式可以减少函数调用的额外开销(时间空间开销),特别是一些常用的短小的函数适合采用内联函数形式。2025/9/27北京邮电大学信息与通信工程学院-85-5.5内联函数内联函数的定义形式:inline函数类型函数名(形式参数表){函数体}
2025/9/27北京邮电大学信息与通信工程学院-86-5.5内联函数例5-13
使用内联函数求三个整数中的最大值。
2025/9/27北京邮电大学信息与通信工程学院-87-2025/9/27北京邮电大学信息与通信工程学院-88-//内联函数例#include<iostream>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;
cout<<"enterthreeintegers:"
cin>>a>>b>>c;
cout<<"Maximumis"<<max(a,b,c)<<endl;}(a>=b)?(a>=c?a:c):(b>=c?b:c)2025/9/27北京邮电大学信息与通信工程学院-89-
内联函数之所以能够减少函数调用时的系统空间和时间开销,是因为系统在编译程序时就已经把内联函数的函数体代码插入到相应的函数调用位置,成为主调函数内的一段代码,可以直接执行,不必再转换流程控制权。这样的结构,自然节省了时间和空间开销,但使得主调函数代码变长。一般是只把短小的函数写成内联函数。2025/9/27北京邮电大学信息与通信工程学院-90-注意:(1)内联函数体不能包含循环语句、switch语句和异常接口声明。(2)内联函数要先定义,后调用。因为编译器需要用内联函数的函数体代码替换对应的函数调用。如果内联函数不符合要求,编译器就将内联函数当一般函数处理。5.6重载函数重载函数也是函数的一种特殊情况。C++允许几个功能类似函数同名,但这些同名函数的形式参数必须不同,称这些同名函数为重载函数。例:intmax(intx,inty){returnx>y?x:y;}floatmax(floatx,floaty){returnx>y?x:y;}2025/9/27北京邮电大学信息与通信工程学院-91-2025/9/27北京邮电大学信息与通信工程学院-92-各重载函数形式参数的不同是指参数的个数、类型或顺序彼此不同,不包括参数标识符的不同。如:①intmax(inta,intb){returna>b?a:b;}②intmax(intx,inty){returnx>y?x:y;}③intmax(intx,inty,intz){return(x>y?x:y)>z?(x>y?x:y):z;}①②实际是一个函数,如果写在同一个文件中,编译时会出现编译错误。若①③或②③在同一个文件中可形成重载函数。编译器将以形式参数个数的不同来认定和区分重载函数。2025/9/27北京邮电大学信息与通信工程学院-93-#include<iostream>using
namespace
std;
int
min(int
x,int
y){return
x<y?x:y;}double
min(double
x,double
y){return
x<y?x:y;}void
main(){int
ia(10),ib(20);
double
da(0.1),db(0.5);
cout<<"minimumofinteger.is"<<min(ia,ib)<<endl;
cout<<"minimumofdoubleis"<<min(da,db)<<endl;}2025/9/27北京邮电大学信息与通信工程学院-94-在使用重载函数时需要注意下面三点:编译器不以形式参数的标识符区分重载函数。例intmax(inta,intb);intmax(intx,inty);编译器认为这是同一个函数声明两次,编译时出错。2025/9/27北京邮电大学信息与通信工程学院-95-(2)
编译器不以函数类型区分重载函数。floatfun(intx,inty);intfun(intx,inty);如果函数名和形式参数表相同,只是函数类型不同,编译器同样认为它们是同一个函数声明两次,编译出错。(3)不应该将完成不同功能的函数写成重载函数,破坏程序的可读性。2025/9/27北京邮电大学信息与通信工程学院-96-重载函数常用于实现功能类似而所处理的数据类型不同的问题5.7默认参数值的函数具有默认参数值的函数是一种特殊的函数形式,C++允许函数的形式参数有默认值。例如:计算圆面积的函数:double
CircleArea(double
radius=1.0){
const
double
PI=3.14;
return
PI*radius*radius;}
2025/9/27北京邮电大学信息与通信工程学院-97-2025/9/27北京邮电大学信息与通信工程学院-98-调用具有默认参数值的函数时,如果提供实际参数值,则函数的形参值取自实际参数;如果不提供实际参数值,函数的形参采用默认参数值。例如调用CircleArea函数:#include<iostream>using
namespace
std;void
main(){
cout<<CircleArea(10.0)<<endl;//提供实际参数值
cout<<CircleArea()<<endl;//不提供实际参数值}2025/9/27北京邮电大学信息与通信工程学院-99-默认参数值函数如果有多个参数,而其中只有部分参数具有默认值,则这些具有默认值的参数值应该位于形参表的最右端。或者说,形参表中具有默认参数值的参数的右边,不能出现没有默认值的参数。例如:intCuboidVolume(intlength=1,intwidth=1,intheight=1);//正确intCuboidVolume(intlength,intwidth=1,intheight=1);//正确intCuboidVolume(intlength,intwidth,intheight=1);//正确
intCuboidVolume(intlength=1,intwidth,intheight=1);//错误intCuboidVolume(intlength,intwidth=1,intheight);//错误intCuboidVolume(intlength=1,intwidth=1,intheight);//错误2025/9/27北京邮电大学信息与通信工程学院-100-如果默认参数值函数是先声明,后定义的,则在声明函数原型时就指定默认参数值。如果函数定义在先(无需原型声明),则在函数定义的形参表中指定默认值。
例5-13
编写具有默认函数值的函数,计算直角三角形的面积。
//使用默认形式参数值的函数编写计算直角三角形面积的程序#include<iostream>using
namespace
std;float
areaRATriangle(int
side1=3,int
side2=4);void
main(){ cout<<"Theareaofdefaultright-angledtriangle(3,4)is:“<<areaRATriangle()<<endl;
cout<<"Theareaofright-angledtriangle(6,4)is:“<<areaRATriangle(6)<<endl;
cout<<"Theareaofright-angledtriangle(6,8)is:"
<<areaRATriangle(6,8)<<endl;}//计算直角三角形面积
float
areaRATriangle(int
side1,int
side2){ return
side1*side2/2.0;}//使用默认形式参数值的函数编写计算直角三角形面积的程序#include<iostream>using
namespace
std;//计算直角三角形面积float
areaRATriangle(int
side1=3,int
side2=4){ return
side1*side2/2.0;}void
main(){ cout<<"Theareaofdefaultright-angledtriangle(3,4)is:“<<areaRATriangle()<<endl;
cout<<"Theareaofright-angledtriangle(6,4)is:“<<areaRATriangle(6)<<endl;
cout<<"Theareaofright-angledtriangle(6,8)is:"
<<areaRATriangle(6,8)<<endl;}5.8全局变量与局部变量程序内存空间2025/9/27北京邮电大学信息与通信工程学院-103-代码区(存放程序的代码)全局区(存放程序中的全局数据和静态数据)堆区(存放程序的动态数据)栈区(存放程序的局部数据)5.8全局变量与局部变量编译器根据变量定义的位置局部变量(在函数内部定义的变量、函数的形参)全局变量(在函数外部定义的变量为全局变量)作用域由于变量定义的位置不同,所以变量起作用的范围也不同。我们把程序中一个标识符起作用的范围称为其作用域。
2025/9/27北京邮电大学信息与通信工程学院-104-5.8.1局部变量局部变量包括在函数体内定义的变量和函数的形式参数,它们的作用域就在函数体内,只能在本函数内使用,不能被其它函数直接访问。
2025/9/27北京邮电大学信息与通信工程学院-105-2025/9/27北京邮电大学信息与通信工程学院-106-#include<iostream>using
namespace
std;int
fun1(int
x,int
y);int
fun2(int
x,int
y);void
main(){int
a,b;
cout<<"inputa,b:"
cin>>a>>b;
cout<<fun1(a,b)<<endl;
cout<<fun2(a,b)<<endl;}int
fun
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年云南省瑞丽市高二生物下册期末考试模拟卷附完整答案【各地真题】
- 2026年山东省邹城市高二生物下册期末考试考试卷及参考答案【模拟题】
- 2025年吉林省榆树市高二生物下册期末考试检测卷附参考答案【B卷】
- 2025年河南省义马市高二生物下册期末考试检测卷【满分必刷】附答案
- 2026年河北省高碑店市高二生物下册期末考试检测卷(综合卷)附答案
- 2026年河北省南宫市高二生物下册期末考试测试卷及参考答案【能力提升】
- 2025年河南省汝州市高二生物下册期末考试测试卷含完整答案(全优)
- 2026年云南省芒市高二生物下册期末考试检测卷【基础题】附答案
- 2026年河北省深州市高二生物下册期末考试模拟卷及参考答案【培优B卷】
- 2026年广东省鹤山市高二生物下册期末考试模拟卷【突破训练】附答案
- 2026四川甘孜州甘孜县人民医院考试招聘护士8人笔试备考题库及答案详解
- 2026年镇江市中医院医护人员招聘笔试备考试题及答案详解
- 2026年北京市丰台区九年级中考语文二模试卷附答案解析
- 2026春人教版六年级语文下册全单元知识点归纳
- 村级干部保密协议书
- 2026年超星尔雅学习通《当代大学生国家安全教育》章节通关试题库及完整答案详解(有一套)
- 新版人教版八年级语文下册名著阅读理解能力测试卷(含试题及答案)
- 2026年上半年中学教师资格证综合素质真题及答案解析
- 新华保险绩效考核制度
- 产品开发项目流程及执行规范
- 医疗器械经营质量管理规范自查报告
评论
0/150
提交评论