ImageVerifierCode 换一换
格式:DOCX , 页数:25 ,大小:448.83KB ,
资源ID:4448349      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4448349.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(信息学奥赛DEV C++基础教程之函数.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

信息学奥赛DEV C++基础教程之函数.docx

1、信息学奥赛信息学奥赛 DEV C+基础教程之函数基础教程之函数 DEV 教程 第六章 函数 第 22课:函数 前面我们曾经学习了程序设计中的三种基本控制结构(顺序、分支、循环)。用它们可以组成任何程序。但在应用中,还经常用到子程序结构。通常,在程序设计中,我们会发现一些程序段在程序的不同地方反复出现,此时可以将这些程序段作为相对独立的整体,用一个标识符给它起一个名字,凡是程序中出现该程序段的地方,只要简单地写上其标识符即可。这样的程序段,我们称之为子程序。子程序的使用不仅缩短了程序,节省了内存空间及减少了程序的编译时间,而且有利于结构化程序设计。因为一个复杂的问题总可将其分解成若干个子问题来解

2、决,如果子问题依然很复杂,还可以将它继续分解,直到每个子问题都是一个具有独立任务的模块。这样编制的程序结构清晰,逻辑关系明确,无论是编写、阅读、调试还是修改,都会带来极大的好处。在一个程序中可以只有主程序而没有子程序(本章以前都是如此),但不能没有主程序,也就是说不能单独执行子程序。在此之前,我们曾经介绍并使用了 C+提供的各种标准函数,如 abs(),sqrt()等等,这些系统提供的函数为我们编写程序提供了很大的方便。比如:求 sin(1)+sin(2)+sin(100)的值。但这些函数只是常用的基本函数,编程时经常需要自定义一些函数。一、函数的概念 函数是一种对应关系的描述,即确定了函数自

3、变量到函数值之间的对应关系。与函数相关的概念如下。自变量:函数计算时使用的数据,自变量的取值范围称为函数的定义域。在程序设计中,函数的自变量称为参数,定义域由参数的类型决定。函数值:函数的计算结果,它的取值范围称为值域。在程序设计中函数值称为函数返回值,返回值的类型称为函数类型。表达式:数学中函数的计算过程由表达式来说明,在程序设计中,一个函数的处理过程往往比一个表达式所描述的内容要复杂得多,需要一段程序来描述所有的操作,这就是 C+语言一个函数的函数体。二、函数的分类 分为系统函数和用户定义函数(也叫自定义函数)1、系统函数 系统函数取出由 C+语言系统提供的函数(也称库函数)。这些函数可以

4、从语言系统的手册上查阅其功能和使用方法,用户不需自己再进行定义说明,就直接调用。例如我们已经学过的标准函数 abs、sqrt、max、min等。例 1:编写求 n!的函数。参考程序:#include using namespace std;int fact(int n)/fact 为函数名;括号里面的为形式参数,简称为形参。int i,t=1;if(n0)coutError!endl;return 0;for(i=2;i=n;i+)t=t*i;return t;int main()int m,x;coutm;x=fact(m);/函数调用,返回值赋给变量 x。coutm!=xendl;retu

5、rn 0;三、函数的定义 1.函数定义的语法形式 数据类型 函数名(形式参数表)/函数的首部 /函数体;说明部分;语句部分;关于函数的定义有如下说明:1、函数的数据类型是函数的返回值类型(若数据类型为 void,则无返回值)。2、函数名是标识符,一个程序中除了主函数名必须为 main 外,其余函数的名字按照标识符的取名规则可以任意选取,最好取有助于记忆的名字。3、形式参数(简称形参)表可以是空的(即无参函数);也可以有多个形参,形参间用逗号隔开,不管有无参数,函数名后的圆括号都必须有。形参必须有类型说明,形参可以是变量名、数组名或指针名,它的作用是实现主调函数与被调函数之间的关系,通常将函数所

6、处理的数据、影响函数功能的因素或者函数处理的结果作为形参。在被调用函数中的参数被称为形参。4、函数中最外层一对花括号“”括起来的若干个说明语句和执行语句组成了一个函数的函数体。由函数体内的语句决定该函数功能。函数体实际上是一个复合语句,它可以没有任何类型说明,而只有语句,也可以两者都没有,即空函数。5、函数不允许嵌套定义。在一个函数内定义另一个函数是非法的。但是允许嵌套使用。6、函数在没有被调用的时候是静止的,此时的形参只是一个符号,它标志着在形参出现的位置应该有一个什么类型的数据。函数在被调用时才执行,也就是在被调用时才由主调函数将实际参数(简称实参)值赋予形参。这与数学中的函数概念相似,如

7、数学函数:f(x)=x 2+x+1 这样的函数只有当自变量被赋值以后,才能计算出函数的值。三、函数的调用 函数的一般调用形式为:函数名(实在参数 1,实在参数 2,)若实在参数的个数多于一个时,各实在参数之间用逗号隔开。若函数无形参,调用形式为:函数名()函数名后的一对圆括号不可少。例 2:任意输入 10 组三角形的三边,求其面积。【问题分析】:已知三角形的三条边求其面积,用海伦公式:P=(a+b+c)/2 S=【算法设计】:我们可以定义一个已知三角形三条边分别为 a,b,c,求其面积的函数,设为 area(a,b,c)。程序如下:#include#include using namespac

8、e std;double area(double x,double y,double z)double s1,p;p=(x+y+z)/2;s1=sqrt(p*(p-x)*(p-y)*(p-z);return s1;int main()double a,b,c;int i;for(i=1;i=10;+i)coutinput a,b,cabc;if(a+b=c)|(a+c=b)|(b+c=a)coutdata error!endl;/判断三角形是否合法;else couts=area(a,b,c)endl;return 0;注意:在函数说明中,如果形参的个数不止一个,那么在程序中调用函数的实参个数

9、一定要与形参的个数一致;第一个实参对应第一个形参,第二个实参对应第二个实参,次序不能对调。例 3:无参函数 编程序打印如下图:、-|-|-|-【问题分析】:共有四个横行,每行 10个“-”;共有四个竖行,每行 4个“|”【算法设计】:设计一个专门的函数只输出横线。另外一个函数专门输出竖线。参考程序:#include#include using namespace std;void hx()int i;for(i=1;i=10;i+)cout-;coutendl;void sx()int j;cout|;for(j=1;j4;j+)coutsetw(3)|;coutendl;int main()

10、int k;for(k=1;k4;k+)hx();sx();hx();return 0;练习:求:1!+2!+3!+10!第 23课:函数 例 1:使用标识符 sum_double求两个浮点数之和。【问题分析】:在 C+的库函数中,很多由常用程序组成的函数可以直接调用,它们用的就是标识符。【算法设计】:函数 sum_double(double x,double y)有两个参数,参数的类型为双精度实数。调用函数时要传递两个双精度实数。参考程序:#include using namespace std;double sum_double(double x,double y)return x+y;i

11、nt main()double a,b,sum;coutab;sum=sum_double(a,b);coutsum=sumendl;return 0;四、函数调用的传递方式 函数的调用分为传值调用和传地址调用两种,这两种调用的区别在于参数的传递机制不同。1、传值调用 在被调用的函数中形参的改变不会影响到实在参数的值,换句话说,实参的值是被复制给了形参名字所标识的一个对象中,函数内部对形参的改变并不能影响到实在参数。2、传地址调用 传地址调用时,实参用的是地址值,而形参则是我们之后要学到的指针变量。在这章我们先掌握它的调用形式和作用。在 C+语言中,数据只能从实际参数单向传递给形式参数,称为“

12、按值”传递。例 2:以下两个程序,哪一个能交换两个数的值。参考程序一:#include using namespace std;void swap(int a,int b)int tmp=a;a=b;b=tmp;int main()int c=1,d=2;swap(c,d);coutc dendl;return 0;参考程序二:#include using namespace std;void swap(int&a,int&b)int tmp=a;a=b;b=tmp;int main()int c=1,d=2;swap(c,d);coutc dendl;return 0;在参考程序一中,虽然在

13、 swap函数中交换了 a,b 两数的值,但是在 main中却没有交换。因为 swap函数只是交换 c,d 两变量的值,主程序传递给函数 c、d的是变量的值 在参考程序二中,因为 swap 函数的参数为传地址调用,所以,在函数 swap中修改 a,b的值相当于在主函数 main中修改 c,d的值。所以参考程序一运行完成后结果为:1 2;参考程序二运行完成后结果为:2 1。除了用地址表示符“&”表示传的是地址之外,也可以用指针表示。参考程序三:#include using namespace std;void swap(int*a,int*b)int tmp=*a;*a=*b;*b=tmp;in

14、t main()int c=1,d=2;swap(c,d);coutc dendl;return 0;五、函数的全程变量、局部变量及它们的作用域 在函数外部定义的变量称为外部变量或全局变量,在函数内部定义的变量称为内部变量或局部变量。1、全局变量 全局变量的作用域是从变量定义的位置起直至本源文件结束止,即从定义位置之后的所有函数都可以访问该全局变量。下面通过例子来说明这一点。例 3:全局变量的应用。#include#include using namespace std;int x,y;/定义全局变量 x,y int fun1(int s)/访问全局变量 x,y x=10;y=x*s;retu

15、rn x+y;float a,b;/定义全局变量 a,b void fun2(int c)coutx=x y=ymn;coutfun1(m)endl;fun2(n);couta=a b=bendl;/访问全局变量 a,b return 0;当在键盘上输入 6 9 后程序的执行结果是:70 x=10 y=60 a=0 b=0 程序中主函数先调用 fun1(),实参是 6,将实参值传给形参 s(即 s=6),函数 fun1中x 值为 10,y值为 60,return语句将 xy的和返回,fun1()结束。主函数输出返回值之后,调用 fun2(),在 fun2()中输出全局变量 x 和 y 的值,之

16、后返回主函数。在主函数中输出全局变量 a和 b 值。由于 a、b 在声明时未赋初值,系统的默认值为 0。使用全局变量的说明:在一个函数内部,既可以使用本函数定义的局部变量,也可以使用在此函数前定义的全局变量。全局变量的作用是使得函数间多了一种传递信息的方式。如果在一个程序中多个函数都要对同一个变量进行处理,即共享,就可以将这个变量定义成全局变量,使用非常方便,但副作用也不可低估。过多地使用全局变量,会增加调试难度。因为多个函数都能改变全局变量的值,不易判断某个时刻全局变量的值。过多地使用全局变量,会降低程序的通用性。如果将一个函数移植到另一个程序中,需要将全局变量一起移植过去,同时还有可能出现

17、重名问题。全局变量在程序执行的全过程中一直占用内存单元。全局变量在定义时若没有赋初值,其默认值为 0。2、局部变量 局部变量的作用域是在定义该变量的函数内部。换句话说,局部变量只在定义它的函数内有效。在一个子程序内定义的变量也是局部变量,其作用域是该子程序。函数的形参也是局部变量。由于局部变量的作用域仅局限于本函数内部,所以,在不同的函数中变量名可以相同,它们分别代表不同的对象,在内存中占据不同的内存单元,互不干扰。一个局部变量和一个全局变量是可以重名的,在相同的作用域内局部变量有效时全局变量无效。即局部变量可以屏蔽全局变量。练习一:编程求 5!+7!+9!+11!的值。练习二:求正整数 2和

18、 100 之间的完全数。完全数:因子之和等于它本身的自然数,如 6=1+2+3 练习三:如果一个自然数是素数,且它的数字位置经过对换后仍为素数,则称为绝对素数,例如 13。试求出所有二位绝对素数。第 24课:函数的综合运用 例 1:计算如图多边形的面积。【问题分析】:从图中可以看出,五边形的 面积是三个三角形面积之和。【算法设计】:五边形的 5条边分别设为 b1、b2、b3、b4、b5,两条对角线分别为 b6、b7,然后利用海伦公式分别求出三个 三角形的面积,三个三角形的面积之和即为 五边形的面积。参考程序:#include#include#include using namespace st

19、d;double area(double a,double b,double c);int main()double b1,b2,b3,b4,b5,b6,b7,s;coutplease input b1,b2,b3,b4,b5,b6,b7:b1b2b3b4b5b6b7;s=area(b1,b5,b6)+area(b2,b6,b7)+area(b3,b4,b7);printf(s=%10.3lfn,s);return 0;double area(double a,double b,double c)double p=(a+b+c)/2;return sqrt(p*(p-a)*(p-b)*(p-c

20、);此程序中的函数位置与前面的函数不同,放在了主程序的后面。只在主程序前面放了一个函数的声明。如果不做声明就放在了主程序后,是会出错的。六、函数的声明 调用函数之前先要声明函数原型。在主调函数中,或所有函数定义之前,按如下形式声明:类型说明符 被调函数名(含类型说明的形参表);如果是在所有函数定义之前声明了函数原型,那么该函数原型在本程序文件中任何地方都有效,也就是说在本程序文件中任何地方都可以依照该原型调用相应的函数。如果是在某个主调函数内部声明了被调用函数原型,那么该原型就只能在这个函数内部有效。函数原型和函数定义在返回值类型、函数名和参数个数与类型必须完全一致,否则,就会发生编译错误。下

21、面对 max()函数原型声明是合法的。int max(int x,int y);也可以:int max(int,int);可以看到函数原型声明与函数定义时的第一行类似,只多了一个分号,成为了一个声明语句而已。2、函数的返回值 在组成函数体的各类语句中,值得注意的是返回语句 return。它的一般形式是:return(表达式);其功能是把程序流程从被调函数转向主调函数并把表达式的值带回主调函数,实现函数的返回。所以,在圆括号表达式的值实际上就是该函数的返回值。其返回值的类型即为它所在函数的函数类型。当一个函数没有返回值时,函数中可以没有 return语句(在 TC+和 VC+,函数类型定义为 v

22、oid,可以没有 return语句;函数类型定义为 int,必须有返回值),直接利用函数体的右花括号“”,作为没有返回值的函数的返回。也可以有 return语句,但 return后没有表达式。返回语句的另一种形式是:return;这时函数没有返回值,而只把流程转向主调函数。例 2:定义一个函数 check(n,d),让它返回一个布尔值。如果数字 d 在正整数 n 的某位中出现则送回 true,否则送回 false。例如:check(325719,3)=true;check(77829,1)=false;【问题分析】:本题是利用函数求位数是否相同的题目,函数的返回值为布尔(boolean)变量。

23、【算法设计】:利用 While循环语句,一位一位的取出给定数字 n 各位上的数,与给的数 d比较,如果相等则函数返回 true,否则则返回 false。参考程序:#include using namespace std;bool check(int,int);int main()int a,b;coutinputa,bab;if(check(a,b)=true)couttrueendl;else coutfalseendl;return 0;bool check(int n,int d)while(n)int e=n%10;n/=10;if(e=d)return true;return fal

24、se;例 3:求正整数 2和 100 之间的完全数。完全数:因子之和等于它本身的自然数,如 6=1+2+3【问题分析】:首先判断 2-100中的任何一个数是否为完全数,然后在主程序中输出该数。【算法设计】:由于 2-100 之间的任何一个数大于一半就不能被本数整数,所以在函数中判断是否为完全数时只须到一半(即 i/2)即可。参考程序:#include using namespace std;bool wqx(int n);int main()int i;for(i=2;i=100;i+)if(wqx(i)printf(%d,i);return 0;bool wqx(int n)int x,s=

25、0;for(x=1;x=n/2;x+)if(n%x=0)s=s+x;if(s=n)return true;return false;练习一:求出 1-n 之间有所有素数之和。练习二:编写函数 gcd,功能是利用辗转相除法求两个正整数 m 和 n的最大公约数,并由函数值返回。练习三:编写一个求两个数约分,求互质数的程序。第 24课:函数的嵌套和递归 一、函数的嵌套 函数的嵌套调用指的是一个函数调用另一个函数,而被调用函数又可调用其它函数。例如,在调用 A函数的过程中,可以调用 B函数,在调用 B 函数的过程中,还可以调用 C 函数当 C 函数调用结束后,返回到 B函数,当 B函数调用结束后,再返

26、回到 A函数。这就是函数的嵌套调用过程。例 1:函数的嵌套应用举例【问题分析】:主程序中调用函数 1,函数 1 调用函数 2,函数 2调用函数 3。【算法设计】:主程序调用无参数的函数 p1(),在 p1()中函数调用 f(i),而函数 f(i)中调用函数 p2(i),函数逐级返回。p2(i)返回 f(i),f(i)返回到p1(),p1()返回到主函数。参考程序:#include using namespace std;int i=10;void p2(int i1)i1*=2;couti1=i1endl;int f(int i)p2(i);return(3*i);void p1()i=f(i

27、);int main()couti=iendl;p1();couti=i0 时,x!=x*(x-1)!。假设用函数 Fac(x)表示 x 的阶乘,当 x=3 时,Fac(3)的求解方法可表示为:Fac(3)=3*fac(2)=3*2*Fac(1)=3*2*1*Fac(0)=3*2*1*1=6 定义函数:int fac(int n)如果 n=0,则 fac=1;如果 n0,则继续调用函数 fac=n*fac(n-1);返回主程序,打印 fac(x)的结果。参考程序:#include using namespace std;int fac(int n);int main()int x;cinx;c

28、outx!=fac(x)endl;return 0;int fac(int n)if(n=0)return 1;else return(n*fac(n-1);/或 return n=0?1:n*fac(n-1);/调用函数 fac(n-1)递归求(n-1)!【说明】:这里出现了一个小东西,三元运算符“?:”。a?b:c的含义是:如果 a为真,则表达式的值是 b,否则是 c。所以 n=0?1:n*fac(n-1)很好地表达了刚才的递归定义。参考程序二(利用全局变量编程如下):#include using namespace std;int t;int fac(int x)if(x=0)t=1;e

29、lse fac(x-1);t*=x;int main()int x;cinx;fac(x);coutt0,n0)【问题分析】:求两个数的最大公约数,可以用枚举因子的方法,从两者中较小的数枚举到能被两个数同时整除且是最大的约数的方法;也可以用辗转相除法或辗转相减法。【算法设计】:这里采用递归实现辗转相除算法:求 m 除以 n 的余数;如果余数不为 0,则让 m=n,n=余数,重复步骤,即调用子程序;如果余数为 0,则终止调用子程序;输出此时的 n值。参考程序一(有参函数):#include using namespace std;int gcd(int,int);int main()int m,

30、n;cinmn;coutm=m n=n gcd=gcd(m,n)endl;return 0;int gcd(int m,int n)return m%n=0?n:gcd(n,m%n);参考程序二(采用全局变量):#include using namespace std;int d;void gcd(int,int);int main()int a,b;cinab;gcd(a,b);coutm=a n=b gcd=dendl;return 0;void gcd(int x,int y)if(x%y=0)d=y;else gcd(y,x%y);练习一:用递归的方法求 1+2+3+N的值。练习二:用

31、递归函数输出斐波那契数列第 n 项(n=30)。0,1,1,2,3,5,8,13 练习三:植树节那天,有五位同学参加了植树活动,他们完成植树的棵数都不相同。问第一位同学植了多少棵时,他指着旁边的第二位同学说比他多植了两棵;追问第二位同学,他又说比第三位同学多植了两棵;如此追问,都说比另一位同学多植两棵,最后问到第五位同学时,他说自己植了 10 棵。问第一位同学到底植了多少棵树?第 24课:函数的递归 例 1:输入一串以“!”结束的字符,按逆序输出。【问题分析】:可以用循环倒序输出即可,用递归则更简单。【算法设计】:递归的本质就是先进再出,且为后进的先计算,所以很简单的就能做到逆序输出。参考程序

32、:#include using namespace std;void rever()char ch;scanf(%c,&ch);if(ch!=!)rever();printf(%c,ch);int main()rever();return 0;注意:通过本题,同学们要再次好好理解递归的本质和运行的顺序。例 2:用递归函数输出斐波那契数列第 n项(n=30)。0,1,1,2,3,5,8,13【问题分析】:斐波那契数列是一个古老的数学问题,从数字排列的规律来看,后一项等于前两项之和。第一个数字 0可以看做第零项,也可以看做第一项。【算法设计】:设要求的项用 x1变量来表示,要求得后一项,前两项必须

33、已知。参考程序:#include using namespace std;int facci(int n);int main()int x1;printf(Input x1:);scanf(%d,&x1);printf(%d,facci(x1);return 0;int facci(int n)if(n=0)return 0;else if(n=1)return 1;else return(facci(n-1)+facci(n-2);例 3:Hanoi(汉诺塔)问题 问题的提出:Hanoi 塔由 n 个大小不同的圆盘和 3根木柱 1,2,3组成。开始时,这 n 个圆盘由大到小依次套在 1柱上,如图所示。现在要求用最少的移动次数把 1柱上 n个圆盘按下述规则移到 3柱上:(1)一次只能移一个圆盘;(2)圆盘只能在 3个柱上存放;(3)在移动过程中,不允许大盘压小盘。请编程描述移动的过程。【问

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1