第五部分函数.ppt

上传人:本田雅阁 文档编号:3123958 上传时间:2019-07-13 格式:PPT 页数:58 大小:263.02KB
返回 下载 相关 举报
第五部分函数.ppt_第1页
第1页 / 共58页
第五部分函数.ppt_第2页
第2页 / 共58页
第五部分函数.ppt_第3页
第3页 / 共58页
第五部分函数.ppt_第4页
第4页 / 共58页
第五部分函数.ppt_第5页
第5页 / 共58页
点击查看更多>>
资源描述

《第五部分函数.ppt》由会员分享,可在线阅读,更多相关《第五部分函数.ppt(58页珍藏版)》请在三一文库上搜索。

1、第五章 函数,5.1 函数的定义、调用与说明 5.2 函数间参数传递 5.3 递归函数 5.4 函数参数缺省 5.5 函数重载 5.6 函数模板 5.7 作用域与存储类,5.1.1 引例 已知五边形的各条边的长度,计算其面积 计算多边形面积,可将多边形分解成若干个三角形,计算三角形面积的公式如下:,5.1 函数的定义、调用与说明,用前面所学的知识实现:,#include “math.h“ #include “iostream.h“ void main() float a,b,c,d,e,f,g,p1,p2,p3,s1,s2,s3,s; cinabcdefg; p1=(a+b+c)/2; s1=

2、sqrt(p1*(p1-a)*(p1-b)*(p1-c); p2=(c+d+e)/2; s2=sqrt(p2*(p2-c)*(p2-d)*(p2-e); p3=(e+f+g)/2; s3=sqrt(p3*(p3-e)*(p3-f)*(p3-g); s=s1+s2+s3; coutsendl; ,用函数实现:,#include “math.h“ #include “iostream.h“ float area(float x, float y, float z) /定义求三角形面积函数 float c,s ; c = (x + y + z)/2; s = sqrt(c*(c-x) * (c-y)

3、 * (c-z); return s; void main() /主函数 float a,b,c,d,e,f,g,s; cinabcdefg; s=area(a,b,c)+area(c,d,e) +area(e,f,g); coutsendl; ,特点: 函数具有相对独立的功能 函数与函数之间通过参数(输入)和返回值(输出)来联系 使用函数有利于代码重用,提高开发效率,5.1.2 函数的定义,函数类型 函数名(形式参数类型表) 函数体,将两数的比较独立出来编一函数:,【例5.1】求三个整型数中最大的数。,int max(int x,int y) int z; if(xy) z=x; else

4、z=y; return z; /将大的数返回 ,void main() int a,b,c,m; cinabc; m=max(a,b); m=max(c,m); coutmendl; ,【例5.2】编一程序,输出如右图形。,void pic(int n) for(int i=0;in;i+) cout.width(10-i); /控制每行输出的起始位 for(int j=0;j2*i+1;j+)cout“*“; coutendl; void main() pic(4); pic(6); ,将n行构成的三角形独立出来编一函数:,非void型函数 函数体中必须有return语句,形式为: retu

5、rn 表达式 ; 或 return (表达式) ; 用于返回函数值。表达式值的类型与函数类型最好一致。 void型函数 函数体中return语句可以不出现。若出现,则不能带表达式。,说明: 函数类型指函数返回值的数据类型 函数体由语句和其它分程序组成。 形式参数可以为空,但圆括号不能省略。 函数体中不允许再嵌套定义函数 对没有返回值的函数,函数类型定为void型(无类型或空类型)。,5.1.3 函数调用,形式:,函数名(实在参数表),注意: 实参与形参的个数、位置与类型必须一致。它可以是同类型的常量、变量或表达式。 调用的形式可以是表达式,也可以是语句。 函数定义中的形参只有当发生函数调用时,

6、才被分配内存单元。,函数调用的过程:,#include “iostream.h“ #include “iomanip.h“ void main() pic(4); /以语句形式调用 pic(6); ,void pic(int n) for(int i=0;in;i+) cout.width(10-i); for(int j=0;j2*i+1;j+) cout“*“; coutendl; ,函数调用和返回的过程:,主函数,输入数据,调用函数,输出,自定义函数,处理过程,函数结束或 函数值返回,注意:数据的输入、输出一般放在主函数中,保存:返回地址、当前现场,恢复:主调程序现场、返回地址,结束,【

7、例5.3】 求正整数m,n的最大公约数和最小公倍数 。 分析:m、n的最小公倍数为: m*n/最大公约数。,注意: 函数中参数传递是单向“传值”。,int gcd(int m,int n) /求最大公约数 while(int r=m%n) m=n;n=r; return(n); ,int sct(int m,int n) /求最小公倍数 return( m*n/gcd(m,n) ); ,#include “iostream.h“ void main() int m,n; cinmn; coutgcd(m,n)endl; coutsct(m,n)endl; ,函数嵌套调用的示意图:,5.1.4

8、函数说明(函数原型),形式: 函数类型 函数名(形式参数类型表);,#include “iostream.h“ void main() int a,b,c; int max(int x,int y); /函数说明,也可int max(int,int); cinab; c=max(a,b); couty?x:y ; ,【例5.4】函数说明示例,省略参数名,注意: 函数调用在前,定义在后,则必须对函数进行说明,函数说明可以放在函数调用之前所在的函数内,也可以放在源文件开头、函数的外部。 函数说明和函数定义在返回类型、函数名和参数表上必须要完全一致。,5.2 函数间参数传递,5.2.1 传值参数 特

9、点:形参的改变不会影响实参的值 【例5.5】m是一个3位的正整数,将满足m、m2、m3均为回文数的正整数输出。所谓回文数是指顺读与倒读数字相同,如4、151、34543。 分析:将正整数的每位数取出,构造一个逆序的正整数,若该数与原来的相同,即为回文数。,bool palindrome(int x) int m=x,n=0,k; while(x!=0) /构造一逆序数 k=x%10; n=n*10+k; x/=10; return m=n; ,实参:常量、变量和表达式。 形参:变量,#include “iostream.h“ void swap(int x,int y) int temp; t

10、emp=x;x=y;y=temp; void main() int a,b; cinab; swap(a,b); cout“a=“a“ b=“bendl; ,【例5.6】分析下面程序,能否交换两个变量的值?,5.2.1 指针参数 1形参为指针变量 特点:形参的改变能影响实参值 【例5.7】交换两个变量的值,形参:指针变量 实参:变量的地址、指针变量或数组名,#include “iostream.h“ void swap(int * ,int * ); void main() int a,b;cinab; swap(,【例5.8】随机生成10个1100之间的数放在一维数组中,求其平均值及最大的元

11、素值 。,程序:,#include “iostream.h“ #include “stdlib.h“ const int N=10; void fun(float *p,float *p1,int *p2) float sum,max1; sum=max1=*p+; for(int i=1;iN;i+) if (max1*p) max1=*p; sum=sum+*p;p+; *p1=sum/N; *p2=max1; void main() float a10,aver,max,x; for(int i=0;i10;i+) x=rand()%100+1; ai=x; fun(a, ,【例5.9】

12、字符串的复制,#include “iostream.h“ void copy_string(char *from, char *to) while(*from!=0) *to+=*from+; *to=0; void main() char a=“I am a teacher.“, b=“You are a student.“; coutaendlbendl; copy_string(a,b); coutaendlbendl; ,程序:,注意:若对应的实参是指针变量,则该指针应有确定的指向。,void main() char *a,*b; a=new char40; b=new char20;

13、 cinab; copy_string(a,b); couta bendl; delete a; delete b; ,若该二语句删除,程序运行时将异常终止。,2形参为常指针 防止被调函数对实参所指对象的修改,#include “iostream.h “ int f(const int * p) int a=100; a=*p; return a; void main() int x=5; coutf( ,*p=a; return *p;,错误,不能修改const对象,注意:若实参是常对象的地址,则形参必须定义为常指针。,#include “iostream.h“ int f(const in

14、t *p) int a=100; a=*p; return a; void main() const int x=5; coutf( ,形参不能定义为int *p,3函数返回值为指针 即函数的返回值可以是变量的地址、数组名或指针变量等。 如:,float *fun(float x,float y); char *strcat(char *strDest,const char *strSource);,在说明或定义返回值为指针的函数时,只须在函数名前加一指针类型说明符即可。,【例5.10】拼接两个字符串s1和s2,将拼接后的字符串存于s1中返回。,char *strcat1(char *s1,c

15、onst char *s2) char *p=s1; while(*p+); -p; while(*p+=*s2+) ; return(s1); ,思考:若不定义为返回指针值的函数,则程序应如何修改?,注意:不能返回一个局部变量(在函数内定义的变量)的地址,#include “iostream.h“ int *fun(int x) int y=x*x; return ,p指向的对象已经不存在,5.2.2 引用参数,#include “iostream.h“ void swap(int ,&为引用声明符。 x是a的引用, y是b的引用。,引用是一种特殊类型的变量,可认为是另一个变量的别名,它不占

16、用存储空间,对引用的操作就是对被引用者的操作,它们代表的是同一存储单元。,特点:形参的改变可影响实参值。,形参是引用 实参只能是变量名,【例5.11】编一函数,判别一个自然数N是否是降序数,同时,求出该数各位数和。并加以调用,若是降序数输出“yes”,否则输出“no”。例如:3、441、531是降序数;而412不是降序数。,bool drop(int x,int ,5.2.3 数组名作参数,特点:在被调函数中对形参数组的任何改变均会影响实参所指地址里的内容 。,形参:数组名 实参:数组名或指针变量,【例5.12】对含有n个元素的整型数组a,从大到小进行排序。,调用:sort(a,10);,vo

17、id sort(int x,int n) int i,j,k,w; for(i=0;in-1;i+) k=i; for(j=i+1;jn;j+)if(xkxj)k=j; if(i!=k)w=xi;xi=xk;xk=w; ,数值型数组的元素个数一般须传给形参,【例5.13】 求字符串长度,并调用之。,int len(char s) int i=0; while(si!=0)i+; return i; ,调用: coutlen(str);,字符型数组的元素个数一般不用传给形参,注意: 形参和实参的类型应保持一致。 函数头里的参数,要一个一个地分别说明或 列出。 下面是几种函数头正确与错误的写法:,

18、int m(int x4,int y),int m(int x,int y),5.2.4 对象参数,【例5.14】 统计字符串str1中出现子串sub的个数,实参为CString对象,则形参可以是: (1) CString 参数,对形参的改变不影响实参; (2) CString &参数, 对形参的改变将影响实参; (3) const CString &参数,不允许改变形参值。,int count(CString str1,const CString sub) int i,count=0,k; i=str1.Find(sub); while(i=0) count+; k=str1.GetLeng

19、th(); str1=str1.Mid(i+1,k-i); i=str1.Find(sub); return count; ,5.3 递归函数,用自身的结构来描述自身就称为递归。 最典型的例子是对阶乘运算:,特点: 原始问题可转化为解决方法相同的新问题; 新问题的规模比原始问题小; 新问题又可转化为解决方法相同的规模更小的新问题,直至终结条件为止。,fac(2)=2*fac(1),fac(1)=1,fac(4)=4*6,fac(3)=3*2,fac(2)=2*1,fac(3)=3*fac(2),fac(4)=4*fac(3),【例5.15】编fac(n)=n! 的递归函数,long fac(i

20、nt n) if(n=1) return(1); return (n*fac(n-1); ,递推过程 每调用自身,当前参数压栈,直到达到递归结束条件。 回归过程 不断从栈中弹出当前的参数,直到栈空。,思考:若fac函数中没有语句 if(n=1) return(1);程序运行结果将如何?,【例5.16】用递归函数实现将一个十进制整数转换成二至十六任意进制的字符,void convert(int m,int r) char b17=“0123456789ABCDEF“; if(m!=0) convert(m/r,r);coutbm%r; ,任何有意义的递归必须具有: 递归结束条件及结束时的值; 能

21、用递归形式表示,并且递归向终止条件发展。,递归算法设计简单,程序代码简洁易读,但它消耗的机时和占据的内存空间比非递归大。,5.4 函数参数缺省,#include “iostream.h“ #include “math.h“ double s(double x , double eps=1e-6) int n=1; double w=0.0, t=1.0 ; while(fabs(t)=eps) w+=t; t=t*x/(n+); return w; ,【例5.17】求下面级数的部分和。精度为:,默认参数的说明必须出现在函数调用之前。若一个函数说明已给出参数的默认值,则在函数定义中不允许再设置。

22、 要求赋予默认值的参数必须放在形参表列中的最右端。,说明:,分析下面各例: void fun(int i, int j, int k, int m=3,int n=4); 假设函数调用语句为: fun(1,2); /错误,至少应有三个实参 fun(10,20,30); /正确,m、n取默认值 fun(10,20,30,40); /正确,m取40 、n取默认值4 fun(10,20,30, ,50); /错误,只能从左至右匹配,5.5 函数重载 引例:求不同类型数据的绝对值,#include #include void main() int x1=-1; double x2=2.5; long

23、x3=3L; coutabs(x1)endl; coutfabs(x2)endl; coutlabs(x3)endl; ,不足:易出错、难记忆 函数重载:一组参数(个数或类型)不同的函数共用一个函数名。,不同名函数实现同一类的操作,#include int abs(int x) return x0?x:-x; double abs(double x) return x0?x:-x; long abs(long x) return x0?x:-x; void main() int x1=1; double x2=2.5; long x3=3L; coutabs(x1)endl; coutabs(

24、x2)endl; coutabs(x3)endl; ,一. 参数类型不同的重载函数,编译器根据函数参数的类型来确定应该调用哪个函数,【例5.18】,二. 参数个数不同的重载函数,可见:重载使得函数的使用更加灵活、方便。 它体现了c+对多态性的支持一个名字,多个入口 。,【例5.19】,#include int min(int a,int b) return ab?a:b; int min(int a,int b,int c) int t=min(a,b); return min(t,c); int min(int a,int b,int c,int d) int t1=min(a,b); in

25、t t2=min(c,d); return min(t1,t2); void main() coutmin(13,5,4,9)endl; coutmin(-2,8,0)endl; ,编译器根据调用语句中实参的个数来确定应该调用哪个函数,注意:不要同时使用重载函数和缺省参数函数。,5.6 函数模板,使用函数重载需编写多个函数,而利用函数模板只需定义一个通用函数即可。 利用函数模板定义的函数称为模板函数,形式:,template 类型 函数名( 参数表) ,#include template T min(T a,T b) return ab?a:b; void main() coutmin(3,5

26、)endl; coutmin(8.5,5.6)endl; ,【例5.20】,定义一个数据类型T 使用模板函数时,模板中的类型参数T用实参的类型替换,分析以下几种模板函数:,template T fun1(T a,int b) /可含有模板参数表中未给出的数据类型 ,template /模板中可带有多个参数 void fun1(T1 a,T2 b,T3 c) ,template void fun1(int a,int b) /必须至少有一个参数的类型为模板的类型参数 ,template void fun1(int a,int b) T i,j; ,【例5.21】定义一个通用的函数,对n个数按递增

27、排序。,#include “iostream.h “ template void sort(TEM x,int n) int i,j,k; TEM w; for(i=0;ixj)k=j; if(i!=k) w=xi;xi=xk;xk=w; ,void main() int i,a6=6,9,2,4,1,0; double b4=5.5,8.0,3.3,0; sort(a,10); sort(b,5); for(i=0;i10;i+) coutaiendl; for(i=0;i5;i+) coutbiendl; ,注意w变量的定义,5.7 作用域与存储类别,#include “iostream.

28、h“ int digit(long n) int k=0; while(n!=0) n/=10; k+=1; return k; void main() long x; cinx; cout digit(x)endl; ,从下面三方面分析各变量 作用域(可见性): 在什么范围内可以访问 空间概念 生存期: 在什么时间存在 时间概念 初始化,【例5.22】,5.7.1 自动变量,作用域:从定义点开始到所在的分程序结束 生存期:开始执行分程序就生成,分程序执行结束就消亡 初始化:可以初始化,缺省值为随机值。 作用域不可以扩展,#include “iostream.h“ int f(int x) x

29、+; int y=5; /auto int k=5; y+; return x+y; void main() int k=2; coutf(k)endl; coutf(k+1)endl; ,缺省的存储类别:auto 注意:只有内部变量存储类别才能auto,【例5.23】,5.7.2 静态局部变量,作用域:从定义点开始到所在的分程序结束。 生存期:程序的执行周期 初始化:可以初始化,缺省值为0或0 。 初始化一次 在开始执行程序时初始化 作用域不可以扩展 一个函数可能被调用多次, 前一次调用的结果带到下一次去。,#include “iostream.h“ int fac(int n) stati

30、c int f=1; f=f*n; return(f); void main() auto int i; for(i=1;i=5;i+) cout“i!=“fac(i); ,【例5.24】,5.7.3 全局变量,作用域:从定义点开始到所在的文件结束 生存期:程序的整个执行周期 初始化:可以初始化,缺省值为0或0 。 作用域可以扩展: 向上扩展 横向扩展,扩展到另一个文件 注意:扩展的地方不能初始化,#include “iostream.h“ int m=10; void f1(int n) n=2*n;m=m/3; int n; void f2() n=5;m+;n+; void main()

31、 int n=2; f1(n); f2(); coutmnendl; ,【例5.25】外部变量示例,注意: 外部变量的作用域只限于定义处到文件结束,定义点之前的函数或其它文件中的函数不可以引用该外部变量。 可以使用extern声明符来扩展外部变量的作用域,外部变量与局部变量同名,起作用的是局部变量,(1)作用域向定义点之前的函数扩展,#include extern int i; void fun() /extern int i; 错误 couti; void g() i+; int i=5; void main() int j=20; coutj; g(); fun(); ,#include

32、extern int i; /不能初始化 void fun() / extern int i; couti; int i=5; void main() int j=20; coutj; fun(); ,(2)作用域扩展到另一个文件 【例5.26】作用域横向扩展示例,/file1.cpp extern max,min; #include “iostream.h“ void main() void maxmin(int x,int n); int a10=11,2,3,-4,5,6,7,8,0,20; maxmin(a,10); coutmax“ “minendl; ,/file2.cpp int

33、 max,min; void maxmin(int x,int n) max=x0;min=x0; for(int i=0;imax)max=xi; if(ximin)min=xi; ,总结:,5.8 程序举例,【例5.27】编一判断质数的函数,验证歌德巴赫猜想:任何大于2的偶数均可表示为两个素数的和。例如:4=2+2(特例,仅此一个),6=3+3,8=3+5,。程序要求输入任一偶数,输出6到该数范围内的各个满足条件的组合。 分析:对一个偶数,分解为两个质数和,既n=a+b。方法是从找最小的质数a为3开始(因2是偶数,另一个必定是偶数,不可能是质数),判断b=n-a是否是质数,若b也是质数,则

34、n符合要求;否则,找下一个质数a,再判断b。,程序: #include “iostream.h“ int isprime(int m) /判别m是否为质数 for(int i=2;m%i!=0;i+); return (i=m); void main() int n,x,a,b; cinx; for(n=6;n=x;n+=2) for(a=3;a=n/2;a+=2) if(isprime(a) b=n-a; if(isprime(b) coutn“=“a“+“bendl; break; /退出a循环,判别下一个n的组合 ,【例5.28】写一函数itoc(),把数字转变成字符串。如数字-123,

35、经过itoc(-123)后,变为-123。 分析:函数itoc()先判断n是否有符号,若有符号,应先保存加以处理。数字变为对应的字符须将其ASCII码加上30H,即加上字符0。把一个数(如n)的每一位分离出来可以用n%10,而循环结束条件为n/100。但这样处理的数据是从个位向前的,所以还要作反转处理。,程序: #include “iostream.h“ #include “string.h“ void main() void itoc(int,char ); int n;char s100; cinn; itoc(n,s); coutsendl; ,void itoc(int n,char

36、s) void reverse(char ); int i=0; int sign; if(sign=n)0); if(sign0) si+=-; si=0; reverse(s); ,void reverse(char s) int c,i,j; j=strlen(s)-1; for(i=0;ij;i+,j-) c=si;si=sj;sj=c; si+j+1=0; ,【例5.29】用梯形法求积分:,分析:n等分积分区间a,b,每一个小梯型的面积和即近似为f(x)在a,b的积分值。即将求积分转化求和。,#include “iostream.h“ #include “math.h“ double

37、 f(double x) return exp(-x*x/2); double integral(double a,double b,int n) int sum;double h=(b-a)/n; sum=(f(a)+f(b)/2; int x=a+h; for(int i=1;iabn; coutintegral(a,b,n)endl; ,程序:,【例5.30】 统计字符串中各个字母(不区分大、小写)出现的频率,同时找出频率出现最高的字母及次数。 分析:由于函数需要返回多个值,故可通过传址调用或引用调用实现。将要处理的数据及处理的结果设为形参。,#include “iostream.h“

38、#include “stdio.h“ #include “string.h“ void freq(char s,int p,char ,程序:,【例5.31】编写两个重载的同名函数find,功能为查找指定的字符或子字符串在串中的位置。既实现Cstring类中二个Find成员函数的功能。,int find(char s,char ch) for(int i=0;si;i+) if(si=ch)break; return i; int find(char s1,char s2) char s80; for(int i=0;s1i;i+) for(int j=0;s2j;j+) sj=s1i+j; sj=0; if(!strcmp(s,s2) return i; ,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1