程序设计语言(C) 第三章 函数_第1页
程序设计语言(C) 第三章 函数_第2页
程序设计语言(C) 第三章 函数_第3页
程序设计语言(C) 第三章 函数_第4页
程序设计语言(C) 第三章 函数_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

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

文档简介

1、程序设计语言(C),第三章函数,本章重点C中函数的定义、调用和参数传递;参数传递时的两种调用方式:传值调用和引用调用;函数的重载和递归调用;部分常见系统函数的用法。本章难点函数之间进行参数传递时两种调用方式;函数的递归调用;函数重载。,函数是源程序的基本模块,一个C控制台程序一般由一个主函数main()和若干个应用函数组成。主函数main()是整个应用程序的开始执行点,正常情况下,整个C控制台应用程序也是在main()函数中结束的。主函数可以调用应用函数,而应用函数之间也可以根据其逻辑关系相互调用。调用其他函数的函数称为主调函数,而被调用的应用函数称被调函数。我们把实现某种功能的算法编成一个个

2、相对独立的函数模块,然后用调用的方法来使用这些函数。,函数的分类,C语言系统自身提供了丰富的应用函数,这些函数被称为系统函数。系统函数无需用户定义,只需在源程序前连接包含有该函数原型的头文件,即可在程序中直接调用(在稍后的章节里介绍)。此外,还可以根据需求,把算法编成独立的函数模块,在源程序的适当位置进行定义和调用,这类应用函数叫做用户自定义函数。在C语言源程序中,用户自定义函数应用遵循先定义后使用的原则。,函数定义,类型标识符函数名(形式参数表)语句类型标识符和函数名称为函数头,类型标识符指明了本函数的类型,函数的类型实际上是函数返回值的数据类型,该类型标识符与前面介绍的各种数据类型说明符相

3、同,一些情况下函数也可以没有返回值,此时函数类型标识符应为void。,求两个整型数据中较大的整数,intmax(intx,inty)if(xy)returnx;elsereturny;,将华氏温度转换为摄氏温度,floatftoc(floatf)floatc;c=5*(f-32)/9;returnc;,函数原型声明,在程序中,一个函数的定义可以放在任意位置,既可放在主调函数之前,也可放在主调函数之后,为了避免由于函数定义位置的不确定性而引起的编译错误,要求应在应用函数调用之前为其构造原型,即在源程序中首先声明函数原型。类型标识符函数名(形式参数表);其中:类型标识符、函数名、形式参数表的规定与

4、函数的定义相同。该语句最后的分号不能缺少。,上节2个例题中的函数原型声明分别为:floatftoc(floatf);intmax(intx,inty);注意:1)同一个函数的原型声明与函数定义,在类型标识、函数名称以及形式参数表上必须完全一致。2)函数原型声明必须出现在函数调用之前。3)函数原型声明时,形式参数表中可以不包含参数的名字,只包含参数的类型。因此,函数ftoc原型声明也可写为:floatftoc(floatf);,函数的调用,函数被定义以后,只有在主调函数的适当位置对它进行调用,才能发挥其作用。函数调用实际上就是转去执行这段用函数名命名的程序代码,它包括参数传递、执行代码、返回函数

5、值等操作。调用形式:函数名(实际参数表)其中:函数调用中的函数名称应与函数定义中的函数名称相一致;实际参数表中给出的实际参数(简称实参),是主调函数转去执行被调函数了时,希望参与被调函数运算的实际值,它们可以是常量、变量或表达式。,对函数ftoc的调用,floatftoc(floatf);voidmain()floatx,y;coutx;y=ftoc(x);cout华氏温度x度=摄氏温度y度endl;,函数的返回值,要将被调函数的计算结果,有效的传递到主调函数中去(即返回函数值),采用return语句实现。return语句的一般格式为:return表达式;该语句的功能是终止函数的执行,并向主调

6、函数返回函数值,返回的函数值就是return语句中表达式的值。该语句的表达式可以省略,若省略表达式,return语句仅表示终止函数的执行,并将系统控制权交给主调用函数。,使用return语句应注意以下几点,1)有返回值函数的函数体中至少应有一个return语句。2)C允许函数体中存在多个return语句,当程序流程执行到其中的某个return语句时,终止函数的执行。3)关键字return后面的表达式可有可无,当return语句不带表达式,又位于函数体的最后时,return语句可以省略。4)关键字return后面的表达式可以用()括起来,也可以省略括号。5)函数默认的返回值数据类型为整型。,形式

7、参数和实际参数,在调用函数时,大多数情况下,主调函数和被调用函数之间有数据传递关系。这就是前面提到的有参函数。在定义函数时函数名后面括弧中的变量名称为“形式参数”(简称“形参”),在主调函数中调用一个函数时,函数名后面括弧中的参数(可以是一个表达式)称为“实际参数”(简称“实参”)。,形式参数在函数定义时说明,在整个函数体内都可以使用,离开该函数则不能使用,它约定了主调函数在调用该函数时,所要传递给该函数的数据个数和每个要传递数据的类型等。实际参数出现在主调函数中,进入被调函数后,实参变量也不能使用。实际参数就是在调用函数时,主调函数传递给被调函数符合形参约定的实际数据。也就是说,发生函数调用

8、时,主调函数把实参传送给被调函数的形参,从而实现主调函数向被调函数的数据传送。,函数形参和实参的特点,实参可以是常量、变量、表达式、函数等,无论实参是何种类型,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值、输入、计算等办法使实参获得确定值。实参和形参在数量、类型和顺序上应严格一致,否则会发生“类型不匹配”的错误。一般情况下,形参变量只有在被调用时才分配内存单元,调用结束即刻释放所分配的内存单元。所以,形参只在函数内部有效,函数调用结束返回主调函数后,则不能再使用形参变量。因此,这种情况下函数调用中发生的数据传送是单向的,即只能把实参的值传送给形参,而不能把

9、形参的值反向地传送给实参。,传值调用,voidswap(inta,intb);voidmain()intx=3,y=5;cout交换前:x=xy=yendl;swap(x,y);cout交换后:x=xy=yendl;,voidswap(inta,intb)cout交换前:a=ab=bendl;inttemp;temp=a;a=b;b=temp;cout交换后:a=ab=bendl;,程序的运行结果是:交换前:x=3y=5交换前:a=3b=5交换后:a=5b=3交换后:x=3y=5swap()函数用于交换两个参数的值,从运行结果可以看出,主函数中变量x、y的值在调用swap()函数时作为实际参数

10、传递给了swap()函数的形式参数a、b,执行swap()函数的结果,确实将函数体内变量a、b里的值进行了交换。但是,由于函数调用采用的是传值调用,形式参数值的改变并不影响实际参数的值,所以,当函数返回时主函数中变量x、y的值没有发生变化。,函数的引用调用,与传值调用不同,函数的引用调用将在主调函数的实参变量与被调函数的形参变量之间建立某种联系,使得形参变量的变化将影响实参变量的值。在使用引用调用时,要在函数定义时将函数的形式参数类型用引用运算符“intfact(intn);voidmain()inta=3,b=5,s;s=pow2(a,b);couts=sendl;,intpow2(intx

11、,inty)intf1,f2;f1=fact(x);f2=fact(y);returnf1*f1+f2*f2;intfact(intn)inti,f=1;for(i=1;i=n;i+)f*=i;returnf;,程序运行结果:s=14436上述程序中,主函数在执行s=pow2(a,b)语句时遇到函数调用,转去执行函数pow2并将a、b的值3和5传递给pow2函数的形参变量x和y,执行函数pow2的过程中,又有f1=fact(x)和f2=fact(y)两语句要调用fact函数,转去执行fact函数分别得到x!和y!,之后从fact返回pow2函数,pow2函数计算出x!的平方、y!的平方之和,返

12、回这个和到主函数。,函数的递归调用,函数不仅可以调用其他函数,也可以自己调用自己,这种函数自己调用自己的过程叫做函数的递归调用。函数的递归调用包括直接的自身调用和间接的自身调用。递归的过程可分为两个阶段,即“递推”和“回归”。所谓递推是函数自身逐级调用的过程,反映在内存中就是调用函数的信息(包括运行环境和返回地址等)入栈过程。所谓回归就是函数的逐级返回(结束运行)的过程,这一过程反映到内存中,就是调用函数信息的出栈过程。,栈的的概念,所谓的栈区是程序用来存放局部数据的一块内存空间。每调用一个函数就会为该函数内的局部数据在栈区分配存储空间,且调用函数与被调用函数的栈区互相独立,被调用函数会在自己

13、的栈空间内保存调用它的函数的运行状态和返回地址,以便调用结束后恢复调用函数的状态并继续运行。,main函数的栈区中保存了操作系统的运行状态、返回地址以及操作系统传给它的参数。被调用函数运行结束后,释放它所占的栈区空间,这些空间对应的变量名、形参名都被丢弃。分配栈区并往其中存入相应的数据的过程称为入栈,读出栈区的内容并释放相应栈区的过程称为出栈。,用递归调用求n!,intfact(intnum);voidmain()intn;coutn;coutn!=fact(n)endl;intfact(intnum)if(num!=1)returnnum*fact(num-1);elsereturn1;,递

14、归过程的两个阶段:递推:4!=43!3!=32!2!=21!1!=1未知已知回归:4!=43!=243!=32!=62!=21!=21!=1未知,对于递归的使用必须要注意,在递归调用的函数体内应有结束递归调用的语句,即不能无限制地调用自己,而结束递归调用的往往是一个判断语句;函数体内需有直接或间接调用自身的语句,且这种递归调用语句应在判断是否结束递归的语句之后才出现,即先判断是否结束自身调用,如果条件成立则返回,否则再次调用自身。,用递归调用求Fibonacci数列第n项值,intfib(intn);voidmain()intf,n;coutn;f=fib(n);coutFibonacci数列

15、的第n项值为:fendl;,intfib(intn)if(n=1)return1;elseif(n=2)return1;elsereturnfib(n-1)+fib(n-2);,有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他说是10岁。请问第5个人多大。显然,这是一个递归问题。要求第5个人的年龄,就必须先知道第4个人的年龄,而第4个人的年龄也不知道,要求第4个人的年龄必须先知道第3个人的年龄,而第3个人的年龄又取决于第2个人的年龄,第2个人的年龄取决于第1个人的

16、年龄。而且每一个人的年龄都比其前1个人的年龄大2。,即age(5)age(4)2age(4)age(3)2age(3)age(2)2age(2)age(1)2age(1)10可以用式子表述如下:age(n)10(n1)age(n1)2(n1)可以看到,当n1时,求第n个人的年龄的公式是相同的。因此可以用一个函数表示上述关系。,intage(intn)/*求年龄的递归函数*/intc;/*c用作存放函数的返回值的变量*/if(n=1)c=10;elsec=age(n-1)+2;returnc;voidmain()coutage(5);,例:汉诺塔问题:将a柱子上盘移到c柱,用b柱放临时盘,要求:

17、一次只能移动一个盘,大盘不可放于小盘上。,a,b,c,hanoi塔问题,可以按照下面3个步骤来操作:(1)将n1个盘从一个座移到另一个座上(n1)。(2)将1个盘子从一个座上移到另一座上。这是大和尚自己做的工作。(3)将n1个盘从一个座移到另一个座上(n1)。,voidhanoi(intn,charone,chartwo,charthree);voidmove(intno,charfrom,charto)coutnono:fromfromtotoendl;intmain(intargc,char*argv)hanoi(3,a,b,c);,voidhanoi(intn,charone,chart

18、wo,charthree)if(n=1)move(n,one,three);elsehanoi(n-1,one,three,two);move(n,one,three);hanoi(n-1,two,one,three);,C系统函数,为了方便程序员编程,C语言软件包提供了大量已预先编制好的函数,即系统函数(又称库函数或标准函数),对于系统函数,用户可以不用定义和声明而直接调用它们。C软件包将不同功能的系统函数的函数原型分别写在不同的头文件中,这些头文件是以“.h”为文件名后缀的文件,在使用某一系统函数前,必须用include预处理指令给出该函数的原型所在头文件的文件名。,本章小结,本章首先介绍了函数的基本定义方

温馨提示

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

评论

0/150

提交评论