安徽工程科技学院

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

安徽工程科技学院6.1概述6.2函数的定义6.3函数的调用6.4函数的嵌套及递归调用6.5数组作为函数参数6.6局部变量和全局变量6.7变量的存储类别6.8内部函数和外部函数6.9编译预处理6.10程序举例第6章函数6.1概述6.1.1模块化程序设计思想面对一项复杂任务,通常采取模块化的解决方法。首先,分解该复杂任务成几个大的功能模块,根据需要还可以继续细分,直到分解成一个个功能独立的模块为止。分解的结果可以描述为一棵倒立的大树,如图6.1所示。图6.1模块化程序设计大任务小任务小任务小任务小任务小任务小任务小任务小任务小任务小任务小任务小任务•在程序设计中,常将一些常用的功能模块编写成函数,放在函数库中供公共选用。要善于利用函数库中的函数,以减少重复编写程序段的工作量。•先举一个简单的函数调用的例子。【例6.1】main(){printstar();/*调用printstar函数*/print_message();/*调用print_message*/printstar();/*调用printstar函数*/}printstar()/*printstar函数*{printf(******************\n);}print_message()/*print_message函数*/{printf(“Howdoyoudo!\n”);}运行结果如下:******************Howdoyoudo!******************printstart()和print_message()都是用户定义的函数,分别用来输出一排“*”号和一行信息。说明:(1)一个源程序文件由一个或多个函数组成。一个源程序文件是一编译单位,即以源程序为单位进行编译,而不以函数为单位进行编译。(2)一个C程序由一个或多个源程序文件组成。对较大的程序,一般不希望全放在一个文件中,而将函数和其他内容(如预处理)分别放在若干个源文件中,再由若干源文件组成一个C程序。这样可以分别编写、分别编译,提高调度效率。一个源文件可以为多个C程序公用。•(3)C程序的执行从main函数开始,调用其他函数后流程返回到main函数,在main函数中结束整个程序的运行,main函数是系统定义的。•(4)所有函数都是平行的,即在定义函数时是互相独立的,一个函数并不从属于另一个函数,即函数不能嵌套定义(这和其他的高级语言可能不同)。函数间可以互相调用,但不能调用main函数。•(5)从用户使用的角度看,函数有两种;•①标准函数,即库函数。这是由系统提供的,用户不必自己定义这些函数,可以直接使用它们。应该说明,不同的C系统提供的库函数的数量和功能不同,当然有一些基本的函数是相同的。•②用户自己定义的函数,用户自己编写的用以解决特定问题。•(6)从函数的形式看,函数分两类:•①无参函数。如例6.1中printstar()和print_message()就是无参函数。在调用无参函数时,主调函数并不将数据传送给被调用函数,一般用来执行指定的一组操作,printstar()函数的作用是输出18个星号。无参函数可以带回或不带回函数值。•②有参函数。在调用函数时,在主调函数和被调用函数之间有数据传递。也就是说,主调函数可以将数据传给被调用函数使用,被调用函数中的数据也可以带回来供主调函数使用。6.1.2C语言程序结构函数是构成C语言程序的基本功能模块,它完成一项相对独立的任务。一个C语言程序是若干函数构成的,在构成C程序的诸多函数中有而且只有一个主函数。函数是程序的最小组成单位。所有函数之间的关系是平行的,没有从属的概念。函数的平行关系使得函数的编写相对独立,便于模块化程序设计的实现。C程序的执行总是从主函数开始,又从主函数结束,其他函数只有通过调用关系发生作用。6.1.4函数的分类1.从用户角度分从用户角度,函数可分为以下两类。(1)库函数(2)自定义函数①定义函数;②声明函数;③调用函数。具体使用方法将在本章中详细介绍。2.从函数形式分从函数形式角度,函数可分为以下两类。(1)无参函数,函数不带参数。(2)有参函数,函数带有至少一个参数。3.从函数的返回值分从函数是否有返回值,函数可分为以下两类。(1)有值函数,调用该函数后可以得到返回值。(2)无值函数,调用该函数后没有返回值。无值函数类似于其他高级语言中的过程。6.2函数的定义函数由两部分构成:函数头和函数体。函数头给出函数相关信息(类似“黑盒子”中的入口和出口),而函数体具体实现函数的功能。6.2.1函数的定义形式函数定义的一般形式是:[类型标识符]函数名(形式参数表列)形式参数类型说明{数据描述部分算法实现部分}前两行是函数头。形式参数(又简称形参)表列和形式参数类型说明部分体现的是一个函数的入口参数的个数及其类型。类型标识符说明了函数返回值的类型,也简称函数类型。函数体用一对花括号{}括起来。函数体中不仅可以使用数据描述部分描述的变量,而且还可以使用形式参数。例6.1函数定义示例。floatmax(x,y)floatx,y;{floattemp;if(xy)temp=x;elsetemp=y;return(temp);}6.2.2函数的返回值在函数定义时需要描述函数类型,但没有给出函数如何得到返回值。调用有值函数时,要求被调函数返回数据给主调函数,返回的数据称为函数返回值,简称函数值。得到函数返回值的方法是使用return语句。return语句的功能有3个。(1)返回一个值给主调函数。(2)释放在函数的执行过程中分配的所有内存空间。(3)结束被调函数的运行,将流程控制权交给主调函数。return语句使用的一般形式为:return(表达式)return语句应书写在函数体的算法实现部分,圆括号可以省略。6.2.3形参和返回值的设定编写函数时,应分析该函数中哪些量是函数的已知量,那些是函数需要得到的结果。设计时将已知数据作为函数的形参,已知数据有几个,形参就有几个。未知数据正是函数需要得到的结果。除需要分析已知和未知外,还需要确定已知和未知的数据类型,从而完成对函数头的设计。6.3函数的调用当函数被调用时,函数对应的程序代码才开始执行,才能实现相应的函数功能。6.3.1对被调用函数的声明对被调用函数的声明有两种方式:外部声明和内部声明。在主调函数内对被调函数所作的声明称为内部声明,也称为局部声明;在函数外进行的函数声明称为外部声明,如果声明在程序最前端,外部声明又称为全局声明。内部声明过的函数只能在声明它的主调函数内调用。外部声明过的函数,从声明处到本程序文件结束都可以被调用。内部声明应放在主调函数的数据描述部分,外部声明可以出现在程序中任何函数外。对被调用函数的声明具体形式为:函数类型函数名();例6.5函数声明示例。main(){intm;floatc;floatsum();/*在主函数main()内对被调函数sum()作局部声明,*/scanf(%d,&m);/*只能在主函数内调用声明过的函数max()*/c=sum(m);printf(c=%f\n,c);}floatsum(intn)/*功能是计算数列1/2,2/3,3/5,5/8……的前n项之和*/{floata,b,t,s;intk;a=1,b=2;s=0.5;for(k=2;k=n;k++){t=a,a=b,b=a+t;s=s+a/b;}return(s);}6.3.2函数调用的一般形式1.函数调用的一般形式函数名(实际参数表列)实际参数表列是函数入口参数的实际值。如例6.5中的csum(m)中的m就是有确定值的实际参数,sum(m)是对函数的调用,调用结束后得到返回值赋值给变量c。2.形式参数和实际参数有参函数在调用时,主调函数和被调函数之间有数据传递,主调函数传递数据给被调函数。主调函数传递来的数据称为实际参数,简称实参。函数定义时形式参数仅仅是数据的抽象代表,没有具体值,称为形参。(1)形式参数定义函数时,函数名后的参数称作形式参数,简称形参。在定义函数时,系统并不给形参分配存储单元,当然形参也没有具体的数值,所以称它是形参,也叫作虚参。形参在函数调用时,系统暂时给它分配存储单元,以便存储调用函数时传来的实参。一旦函数结束运行,系统马上释放相应的存储单元。(2)实际参数在调用函数时,函数名后的参数称作实际参数,简称实参。调用函数时,实参有确定的值,所以称它是实际参数。它可以是变量、常量、表达式等任意“确定的值”。(3)实参和形参之间的关系实参的个数、类型应该和形参的个数、类型一致。调用函数时,系统给形参分配存储单元,并且把实参的数值传递给形参。实参和形参分别属于主调函数和被调函数,具有不同的内存单元。所以,在函数调用时形参发生改变,不会影响到实参。3.实参和形参的结合方式C语言中实参和形参的结合采取的是“单向值传递”方式,只有实参传递参数给形参,形参不回传参数给实参。下面用例6.7讲述实参和形参的具体结合方式。例6.7实参和形参的结合方式示例。main(){floata,b,sum;floatadd();scanf(%f,%f,&a,&b);sum=add(a,b);printf(sum=%f\n,sum);}floatadd(x,y)floatx,y;{floatz;z=x+y;return(z);}程序从主函数开始执行,首先输入a,b的数值(假如输入3,5),接下来调用函数add(a,b)。具体调用过程如下。(1)给形参x,y分配内存空间。(2)将实参b的值传递给形参y,a的值传递给形参x,于是y的值为5,x的值为3。(3)执行函数体。①给函数体内的变量分配存储空间。即给z分配存储空间。②执行算法实现部分,得到z的值为8。③执行return语句,完成以下功能。将返回值返回主调函数,即将z的值返回给main()。释放函数调用过程中分配的所有内存空间,即释放x,y,z的内存空间。结束函数调用,将流程控制权交给主调函数。调用结束后继续执行main()函数直至结束。函数调用前后实参、形参的变化情况如图6.4所示。y主abab调函数被调x,y不存在函数504550455045x调用时调用结束后图6.4例6.7实参和形参变化示意图6.3.3函数调用的具体形式有些函数有返回值,有些没有返回值,这两种函数的调用形式不同。1.有值函数的调用形式(1)函数调用作为表达式的一部分。即函数返回值参与表达式的运算。(2)作为函数参数。即函数返回值又作为另一个函数的实参。2.无值函数的调用形式无值函数调用是作为独立的函数调用语句出现的语句,其功能类似于一个过程。(1)实参的类型应和形参的类型匹配。(2)实参和形参的结合方向是自右向左的。(3)实参的个数和形参应该一致。(4)实参可以是任意能够代表“确定的值”的内容。(5)有值函数才可以参于表达式的运算。6.4函数的嵌套及递归调用6.4.1函数的嵌套调用嵌套调用指的是在函数的调用过程中又出现了另外一种函数调用,称为函数的嵌套调用。例6.8函数嵌套示例。以下程序的功能是计算x2sinx在区间[0,5]的定积分。程序由3个函数构成,分别是主函数main()、函数f1()、函数f2()。main()调用函数f2(),在函数f2()的执行过程中又调用了函数f1(),main()嵌套调用了函数f1()。sin(x){…⑦}main()①{…②s+=f2(x,h);…(13)(12)}f2(x,h)③{…④f1(x)…(11)(10)}f1(x)⑤{…⑥sin(x)…⑨⑧}图6.5例6.10函数嵌套调用过程#includemath.hmain(){floatf2();floats=0,h=0.00005,x;for(x=0;x5;x+=h)s+=f2(x,h);printf(%f\n,s);}floatf2(x,h)floatx,h;{floatf1();return((f1(x)+f1(x+h))*h/2);}floatf1(x)floatx;{return(x*x+sin(x));}6.4.2函数的递归调

1 / 122
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功