安徽理工大学软件教研室.ppt_第1页
安徽理工大学软件教研室.ppt_第2页
安徽理工大学软件教研室.ppt_第3页
安徽理工大学软件教研室.ppt_第4页
安徽理工大学软件教研室.ppt_第5页
已阅读5页,还剩67页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C+程序设计,An Introduction to c/c+ Programming,AnHui University of Science and Technology Department of Computer Science & Technology,安徽理工大学计算机科学技术系,11:23:09,安徽理工大学软件教研室,第五章 函数,安徽理工大学计算机软件教研室,11:23:09,安徽理工大学软件教研室,本章重点内容,5.1 函数的定义、调用与说明 5.2 函数间参数传递 5.3 递归函数 5.4 函数参数缺省 5.5 函数重载 5.6 函数模板 5.7 作用域与存储类,11:23:09,安徽理工大学软件教研室,5.1.1 引例 已知五边形的各条边的长度,计算其面积 计算多边形面积,可将多边形分解成若干个三角形,计算三角形面积的公式如下:,5.1 函数的定义、调用与说明,11:23:09,安徽理工大学软件教研室,用前面所学的知识实现:,#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=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; ,11:23:09,安徽理工大学软件教研室,用函数实现:,#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) * (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; ,11:23:09,安徽理工大学软件教研室,特点: 函数具有相对独立的功能 函数与函数之间通过参数(输入)和返回值(输出)来联系 使用函数有利于代码重用,提高开发效率,11:23:09,安徽理工大学软件教研室,5.1.2 函数的定义,函数类型 函数名(形式参数类型表) 函数体,将两个数的比较独立出来编一函数:,【例5.1】求三个整型数中最大的数。,int max(int x,int y) int z; if(xy) z=x; else z=y; return z; /将大的数返回 ,void main() int a,b,c,m; cinabc; m=max(a,b); m=max(c,m); coutmendl; ,11:23:09,安徽理工大学软件教研室,【例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行构成的三角形独立出来编一函数:,11:23:09,安徽理工大学软件教研室,说明: 函数类型指函数返回值的数据类型 函数体由语句和其它分程序组成。 形式参数可以为空,但圆括号不能省略。 函数体中不允许再嵌套定义函数 对没有返回值的函数,函数类型定为void型(无类型或空类型)。,11:23:09,安徽理工大学软件教研室,非void型函数 函数体中必须有return语句,形式为: return 表达式 ; 或 return (表达式) ; 用于返回函数值。表达式值的类型与函数类型最好一致。 void型函数 函数体中return语句可以不出现。若出现,则不能带表达式。,11:23:09,安徽理工大学软件教研室,5.1.3 函数调用,形式:,函数名(实在参数表),函数调用的过程:,11:23:09,安徽理工大学软件教研室,注意: 实参与形参的个数、位置与类型必须一致。它可以是同类型的常量、变量或表达式。 调用的形式可以是表达式,也可以是语句。 函数定义中的形参只有当发生函数调用时,才被分配内存单元。,11:23:09,安徽理工大学软件教研室,#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; ,11:23:09,安徽理工大学软件教研室,函数调用和返回的过程:,注意:数据的输入、输出一般放在主函数中,11:23:09,安徽理工大学软件教研室,函数嵌套调用的示意图:,11:23:09,安徽理工大学软件教研室,【例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; ,11:23:09,安徽理工大学软件教研室,5.1.4 函数说明(函数原型),形式: 函数类型 函数名(形式参数类型表);,#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】函数说明示例,省略参数名,11:23:09,安徽理工大学软件教研室,注意: 函数调用在前,定义在后,则必须对函数进行说明,函数说明可以放在函数调用之前所在的函数内,也可以放在源文件开头、函数的外部。 函数说明和函数定义在返回类型、函数名和参数表上必须要完全一致。 函数说明以分号结束。,11:23:09,安徽理工大学软件教研室,5.2 函数间参数传递,5.2.1 传值参数 特点:形参的改变不会影响实参的值 【例5.5】m是一个3位的正整数,将满足m、m2、m3均为回文数的正整数输出。所谓回文数是指顺读与倒读数字相同,如4、151、34543。 分析:将正整数的每位数取出,构造一个逆序的正整数,若该数与原来的相同,即为回文数。,实参:常量、变量和表达式。 形参:变量,11:23:09,安徽理工大学软件教研室,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; ,11:23:09,安徽理工大学软件教研室,#include “iostream.h“ void swap(int a,int b) int temp; temp=a;a=b;b=temp; void main() int x,y; cinxy; swap(x,y); cout“x=“x“ y=“yendl; ,【例5.6】分析下面程序,能否交换两个变量的值?,P128,11:23:09,安徽理工大学软件教研室,5.2.1 指针参数 1形参为指针变量 特点:形参的改变能影响实参值 【例5.7】交换两个变量的值,实参:变量的地址、指针变量或数组名形参:指针变量,#include “iostream.h“ void swap(int * ,int * ); void main() int a,b;cinab; swap(,11:23:09,安徽理工大学软件教研室,【例5.8】随机生成10个1100之间的数放在一维数组中,求其平均值及最大的元素值 。,程序:,#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, ,11:23:09,安徽理工大学软件教研室,【例5.9】字符串的复制,#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.“ char b=“You are a student.“; coutaendlbendl; copy_string(a,b); coutaendlbendl; ,程序:,11:23:09,安徽理工大学软件教研室,注意:若对应的实参是指针变量,则该指针应有确定的指向。,void main() char *a,*b; a=new char40; b=new char20; cinab; copy_string(a,b); couta bendl; delete a; delete b; ,若该二语句删除,程序运行时将异常终止。,P133,11:23:09,安徽理工大学软件教研室,2形参为常指针 防止被调函数对实参所指对象的修改,#include “iostream.h “ int f(const int * p) int a=100; a=*p+1; return a; void main() int x=5; coutf( ,错误,不能修改const对象,11:23:09,安徽理工大学软件教研室,注意:若实参是常对象的地址,则形参必须定义为常指针。,#include “iostream.h“ int f(const int *p) int a=100; a=*p; return a; void main() const int x=5; coutf( ,形参不能定义为int *p,11:23:09,安徽理工大学软件教研室,3函数返回值为指针 即函数的返回值可以是变量的地址、数组名或指针变量等。 如:,float *fun(float x,float y); char *strcat(char *strDest,const char *strSource);,在说明或定义返回值为指针的函数时,只须在函数名前加一指针类型说明符即可。,11:23:09,安徽理工大学软件教研室,【例5.10】拼接两个字符串s1和s2,将拼接后的字符串存于s1中返回。,char *strcat1(char *s1,const char *s2) char *p=s1; while(*p+); -p; while(*p+=*s2+) ; return(s1); ,思考:若不定义为返回指针值的函数,则程序应如何修改?,P135,11:23:09,安徽理工大学软件教研室,注意:不能返回一个局部变量(在函数内定义的变量)的地址,#include “iostream.h“ int *fun(int x) int y=x*x; return ,p指向的对象已经不存在,11:23:09,安徽理工大学软件教研室,5.2.2 引用参数,#include “iostream.h“ void swap(int ,&为引用声明符。 x是a的引用, y是b的引用。,特点:形参的改变可影响实参值。,形参是引用 实参只能是变量名,11:23:09,安徽理工大学软件教研室,引用是一种特殊类型的变量,可认为是另一个变量的别名,它不占用存储空间,对引用的操作就是对被引用者的操作,它们代表的是同一存储单元。,11:23:09,安徽理工大学软件教研室,【例5.11】编一函数,判别一个自然数N是否是降序数,同时,求出该数各位数和。并加以调用,若是降序数输出“yes”,否则输出“no”。例如:3、441、531是降序数;而412不是降序数。,bool drop(int x,int ,11:23:09,安徽理工大学软件教研室,5.2.3 数组名作参数,特点:在被调函数中对形参数组的任何改变均会影响实参所指地址里的内容 。,形参:数组名 实参:数组名或指针变量,11:23:09,安徽理工大学软件教研室,【例5.12】对含有n个元素的整型数组a,从大到小进行排序。,调用:sort(a,10);,void 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; ,数值型数组的元素个数一般须传给形参,11:23:09,安徽理工大学软件教研室,【例5.13】 求字符串长度,并调用之。,int len(char s) int i=0; while(si!=0)i+; return i; ,调用: coutlen(str);,字符型数组的元素个数一般不用传给形参,11:23:09,安徽理工大学软件教研室,编一函数,未二维数组mn中的最大值和最小值,void m(int x4,int m,int n, int ,不允许省略第维长度,11:23:09,安徽理工大学软件教研室,注意: 形参和实参的类型应保持一致。 函数头里的参数,要一个一个地分别说明或列出。 下面是几种函数头正确与错误的写法:,int m(int x4,int y),int m(int x,int y),11:23:09,安徽理工大学软件教研室,5.2.4 对象参数,实参为CString对象,则形参可以是: (1) CString 参数,对形参的改变不影响实参; (2) CString &参数, 对形参的改变将影响实参; (3) const CString &参数,不允许改变形参值。,11:23:09,安徽理工大学软件教研室,int count(CString str1,const CString sub) int i,count=0,k; i=str1.Find(sub); while(i=0) count+; k=str1.GetLength(); str1=str1.Mid(i+1,k-i); i=str1.Find(sub); return count; ,【例5.14】 统计字符串str1中出现子串sub的个数,11:23:09,安徽理工大学软件教研室,5.3 递归函数,用自身的结构来描述自身就称为递归。 最典型的例子是对阶乘运算:,特点: 原始问题可转化为解决方法相同的新问题; 新问题的规模比原始问题小; 新问题又可转化为解决方法相同的规模更小的新问题,直至终结条件为止。,11:23:09,安徽理工大学软件教研室,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(int n) if(n=1) return(1); return (n*fac(n-1); ,递推过程 每调用自身,当前参数压栈,直到达到递归结束条件。 回归过程 不断从栈中弹出当前的参数,直到栈空。,思考:若fac函数中没有语句 if(n=1) return(1);程序运行结果将如何?,11:23:09,安徽理工大学软件教研室,递推,回归,终止项,11:23:09,安徽理工大学软件教研室,【例5.16】用递归函数实现将一个十进制整数转换成二至十六任意进制的字符,void convert(int m,int r) char b17=“0123456789ABCDEF“; if(m!=0) convert(m/r,r);coutbm%r; ,任何有意义的递归必须具有: 递归结束条件及结束时的值; 能用递归形式表示,并且递归向终止条件发展。,递归算法设计简单,程序代码简洁易读,但它消耗的机时和占据的内存空间比非递归大。,11:23:09,安徽理工大学软件教研室,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】求下面级数的部分和。精度为:,11:23:09,安徽理工大学软件教研室,默认参数的说明必须出现在函数调用之前。若一个函数说明已给出参数的默认值,则在函数定义中不允许再设置。 要求赋予默认值的参数必须放在形参表列中的最右端。,说明:,分析下面各例: 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); /错误,只能从左至右匹配,11:23:09,安徽理工大学软件教研室,5.5 函数重载,引例:求不同类型数据的绝对值 #include #include void main() int x1=-1; double x2=2.5; long x3=3L; coutabs(x1)endl; coutfabs(x2)endl; coutlabs(x3)endl; ,不足:易出错、难记忆 函数重载:一组参数(个数或类型)不同的函数共用一个函数名。,不同名函数实现同一类的操作,11:23:09,安徽理工大学软件教研室,#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(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); int t2=min(c,d); return min(t1,t2); void main() coutmin(13,5,4,9)endl; coutmin(-2,8,0)endl; ,编译器根据调用语句中实参的个数来确定应该调用哪个函数,注意:不要同时使用重载函数和缺省参数函数。,11:23:09,安徽理工大学软件教研室,5.6 函数模板,使用函数重载需编写多个函数,而利用函数模板只需定义一个通用函数即可。 利用函数模板定义的函数称为模板函数,形式:,template 类型 函数名( 参数表) ,11:23:09,安徽理工大学软件教研室,#include template T min(T a,T b) return ab?a:b; void main() coutmin(3,5)endl; coutmin(8.5,5.6)endl; ,定义一个数据类型T 使用模板函数时,模板中的类型参数T用实参的类型替换,【例5.20】,11:23:09,安徽理工大学软件教研室,分析以下几种模板函数:,template T fun1(T a,int b) /可含有模板参数表中未给 出的数据类型,template /模板中可带有多个参数 void fun1(T1 a,T2 b,T3 c) ,11:23:09,安徽理工大学软件教研室,template void fun1(int a,int b) /必须至少有一个参数的类型或函数类型为模板的类型参数 ,template void fun1(int a,int b) T i,j; ,11:23:09,安徽理工大学软件教研室,【例5.21】定义一个通用的函数,对n个数按递增排序。,#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 b3=5.5,8.0,0; sort(a,6); sort(b,3); for(i=0;i6;i+) coutaiendl; for(i=0;i3;i+) coutbiendl; ,注意w变量的定义,5.7 作用域与存储类别,#include “iostream.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】,11:23:09,安徽理工大学软件教研室,5.7.1 自动变量,作用域:从定义点开始到所在的分程序结束 生存期:开始执行分程序就生成,分程序执行结束就消亡 初始化:可以初始化,缺省值为随机值。 作用域不可以扩展,#include “iostream.h“ int f(int x) x+; int k=5; /auto int k=5; k+; return x+k; void main() int k=2; coutf(k)endl; coutf(k+1)endl; ,缺省的存储类别:auto 注意:只有内部变量存储类别才能auto,【例5.23】,11:23:09,安徽理工大学软件教研室,5.7.2 静态局部变量,作用域:从定义点开始到所在的分程序结束。 生存期:程序的执行周期 初始化:可以初始化,缺省值为0或0 。 初始化一次 在编译时初始化,调用时不再初始化 作用域不可以扩展 一个函数可能被调用多次, 前一次调用的结果带到下一次去。,#include “iostream.h“ int fac(int n) static 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】,11:23:09,安徽理工大学软件教研室,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() 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 extern int i; /不能初始化 void fun() / extern int i; couti; int i=5; void main() int j=20; coutj; fun(); ,11:23:09,安徽理工大学软件教研室,(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 max,min; void maxmin(int x,int n) max=x0;min=x0; for(int i=0;imax)max=xi; if(ximin)min=xi; ,11:23:09,安徽理工大学软件教研室,总结:,11:23:09,安徽理工大学软件教研室,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也是质数,则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的组合 ,11:23:09,安徽理工大学软件教研室,【例5.28】写一函数itoc(),把数字转变成字符串。如数字-123,经过itoc(-123)后,变为-123。 分

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论