资源预览内容
第1页 / 共109页
第2页 / 共109页
第3页 / 共109页
第4页 / 共109页
第5页 / 共109页
第6页 / 共109页
第7页 / 共109页
第8页 / 共109页
第9页 / 共109页
第10页 / 共109页
亲,该文档总共109页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第8章 模块化程序设计,学习内容指南,8.1 函数和模块的基本概念,8.2 函数的定义,8.3 函数的调用,8.4 函数的嵌套调用,8.5 函数的递归调用,8.6 指针与数组作为函数参数,8.7 局部变量与全局变量,学习内容指南,8.8 变量的存储方式、存储类别和生存期,8.9 内部函数和外部函数,8.10 指向函数的指针,8.11 返回指针值的函数,8.12 main函数可以带两个形参,8.13 结构化、模块化程序设计举例,8.14 运行一个多文件的C程序的方法,前言,模块化设计是结构化程序设计的重要步骤。 一个大型程序,可以采用“自顶向下、逐步细化”的方法逐层分解为多个功能模块,其中每个模块都完成一个特定的功能,模块之间彼此相对独立,同时也具有一定的联系 。,C语言中的模块则用“函数”来实现,8.1 函数和模块的基本概念,整个C程序是由一个主函数(即main函数)和若干个其他函数构成。执行时首先执行主函数,主函数调用其它函数,其它函数也可以互相调用,通常最后在主函数中结束整个程序的运行,从而完成了整个程序的任务。,例:编程输出以下3行信息: * Good morning world! *,方法一:只用一个主函数实现。程序如下: #include void main ( ) printf ( “*n“ ) ; printf ( “ Good morning world!n“ ) ; printf ( “*n“ ) ; ,方法二:使用一个主函数和2个自定义函数实现,程序如下: #include int main ( ) void prtstar ( ) ; void prtinfo ( ) ; prtstar ( ) ; prtinfo ( ) ; prtstar ( ) ; return 0 ; void prtstar( ) printf ( “*n“ ) ; void prtinfo( ) printf ( “Good morning world!n“ ) ; ,主控模块,输出一行 “Good morning world”,输出一行星号,该程序的执行过程是:首先执行main函数,执行其函数体的第一个可执行语句(程序中的第5行)“prtstar ( ) ;”,它是对prtstar函数的调用,则转去执行prtstar函数的函数体,调用printf标准函数输出一行星号,之后到达该函数体的尾部,则控制返回到主函数;接着执行程序中的第6行“prtinfo ( ) ;”,它是对prtinfo函数的调用,则转去执行prtinfo函数的函数体,输出一行“世界您早!”的信息,之后到达该函数体的尾部,则控制返回到主函数;然后执行程序中的第7行 “prtstar ( ) ;”,它又是对prtstar函数的调用,则又转去执行prtstar函数的函数体,又输出一行星号,之后到达该函数体的尾部,则控制返回到主函数;最后执行主函数体中的语句“return 0 ;”,在主函数中结束整个程序的运行。,函数和模块的基本概念,函数之间调用关系的相关的概念给出几点说明 : 一个C程序可以由一个或多个源程序文件(即以“.C”为后缀的文件)组成。当程序规模较大时,一般可以按照程序的模块结构划分成若干个功能模块群,每个功能模块群的程序存放在一个源程序文件中。 一个C程序只能有一个main函数,主函数名“main”是系统定义的,不允许更改,而其函数体中的语句是用户根据自己的需要编写的。不论main函数放在该程序其他函数的前面、中间还是最后,程序执行时总是先从main函数开始。如果在main函数中调用了其他函数,被调函数执行后将返回到主调函数main中,一般在main函数中结束整个程序的运行。 除main函数外,其他所有函数的地位都是平行的。C语言规定,函数不能嵌套定义,即在一个函数的函数体中不能定义另一个函数。但函数间可以互相调用,还可以嵌套调用 ,但不能调用main函数,main函数是由操作系统或集成开发环境调用的。 从用户使用的角度,函数可分为库函数和用户自定义函数两类。 从形式上,函数可分为有参函数和无参函数两类。,8.2 函数的定义,C规定,在程序中用到的所有函数,必须先定义、后使用。要定义一个函数,需要给出函数名、函数参数、函数体、函数值的类型、函数的属性等。,无参函数的定义格式: 类型说明符 函数名 ( void ) 声明部分 可执行部分 ,函数首部,指定了函数值(即返回值)的类型,函数名是用户为函数起的名字,函数名后必为一对圆括号,表示定义一个函数,函数体,它包括声明部分和可执行部分,声明部分可包括对变量等数据的声明或定义、对本函数将要调用的函数的声明等 可执行部分由若干个可执行语句组成,由它们实现本函数的功能。,如果所定义的函数的函数体为空则定义一个“空函数”例如:void input ( ) ,空函数在模块化程序设计中是有用的。,函数的定义,有参函数的定义格式: 类型说明符 函数名 ( 形参表列 ) 声明部分 可执行部分 ,例:要求定义一个求2个整数的和的函数,可定义如下: int add ( int x , int y ) int z ; z = x + y ; return ( z ) ; ,函数的定义,有参函数定义的几点说明: 有参函数的定义除了在圆括号中增加了“形式参数表列”,其他的与“无参函数”的定义都相同。 在形参表列中可以分别定义一个或多个“形式参数”,如果为多个,则各形参定义之间应以“,”分隔。每个形参变量必须分别指定数据类型。 形参表列中定义的各个参数之所以称为形参,是由于这些参数在没调用该函数时并没有分配实际的存储单元,只有在该函数被调用时,才在“栈”(stack)中临时分配单元,以便接收相应的实际参数传递来的数据。因此,形参又称为“哑元”。形参表列中的参数又称为“入口参数”。而add函数被调用执行后,将把和值z带回主调函数作为函数值,则称该返回值为该函数的“出口参数”。一个函数的“入口参数”和“出口参数”就构成了该函数与主调函数之间的“接口”。,函数调用的格式为: 函数名 ( 实参表列 ),8.3 函数的调用,例如: prtstar ( ) ; sum = add ( a , b ) ;,几点说明: 在函数调用的格式中,如果圆括号中的实际参数表列(简称实参表列)缺省,就是对无参函数的调用。 调用有参函数时,如果实参表列含有多个实参,则各实参间应以逗号隔开。 需要指出,在调用一个有参函数时,实参表列中的每个实参一般都可以是一个可求值的表达式,而常量、变量只是表达式的特例。,例如:sum = add ( a*a , b-1 ),两个实参都是表达式,函数的调用,按照函数调用出现的位置和语法地位来划分,可以有3种调用方式。 函数调用语句。它是由一次函数调用加一个分号构成的语句。此时不要求“被调函数”带回函数值,只要求其完成一定的功能。 函数表达式。如果一个函数调用带回一个值,那么它就可以作为表达式出现在程序中表达式允许出现的任何地方。 函数参数。即用一个函数调用做为另一个函数调用的实参。,例如:prtstar ( ) ;,例如:sum = add ( a , b ) ;,例如:printf ( “sum=%d“ , add ( a , b ) ) ;,注意: 实参与形参 个数相等,类型一致,按顺序一一对应,形参和实参之间的数据传递,形式参数:定义函数时函数名后面括号中的变量名 实际参数:调用函数时函数名后面括号中的参数,常量 变量 表达式,例:比较两个数,并输出较大值,#include “stdio.h“ void main() int max(int x, int y); int a,b,c; scanf(“%d,%d“, ,形参和实参之间的数据传递,实参和形参间的数据传递: 对有参函数,在未调用该函数时,并没有给其形参分配单元。在主调函数调用有参函数时,才在堆栈中根据形参的类型依次给各形参分配单元。 在调用函数的过程中,系统会把实参表达式的值依次传递给被调函数对应的形参变量。C语言的这种参数传递方式称为“按值传递”或“按值调用”。这是由实参向形参的单向传递。所以在被调函数中如果改变了形参的值,实参将不受影响。 实参一般应是一个可求值的表达式。作为表达式的特例,也可以是一个常量或变量。 实参与形参的类型应一致。所谓一致是指“类型相同”或“赋值兼容”。 形参从实参表达式接收值以后,就可以在本函数体中和其他局部变量一样引用,既可以使用其值,又可以重新被赋值。,例如:如果和int型的形参对应的实参为double型数据,比如max ( 3.4 , 6.9 ) ,则会将double型数据转换为int型数据后再赋给形参,使x=3、y=6,因此实参和形参的类型属于赋值兼容,也是一致的。,函数的返回值,在许多情况下,希望通过函数调用使主调函数得到一个确定的值,该值称为函数值或函数的返回值。 当然,在许多情况下调用函数只是为了让它实现某一功能,此时不需要“被调函数”有返回值,这就是没有返回值的函数。,函数返回值是通过return语句获得的。 可以带回返回值的return语句的格式如下: return ( 表达式 ) ; 或 return 表达式 ;,return语句的功能主要是计算表达式的值作为返回值,把它带回到主调函数的调用位置,作为本次调用的函数值。,函数的返回值,对有返回值的函数的定义,应指定函数的类型(即函数值的类型)。,例如: char f ( char ch , int n ) float min ( float x , float y ) ,返回值为char型,返回值为float型,如果在定义函数时未指定函数值的类型,则默认为int型。但最好不缺省,以便提高可读性和可移植性。,return语句中表达式的值的类型和函数值的类型必须一致(即相同或赋值兼容)。若不一致,则系统自动将return语句中表达式的值转换为函数值的类型后作为返回值。即函数的类型决定了函数返回值的类型。,例如: int add ( double x , double y ) return x + y ; 假设在主调函数中用语句 c = add ( 4.7 , 5.2 ) ; 来调用add函数,则表达式x+y的值为double型数值9.9,系统会自动将其转换为int型数据9作为函数返回值。,函数的返回值,调用有函数值的函数,其返回值也可以不用。例如,printf函数的返回值是它输出字符的个数。语句:printf ( “nn“ ) ;是向屏幕输出2个换行符,函数返回值为2,但这个2没有被使用,被自动丢弃了,这是允许的。 在定义有函数值的函数时,如果漏写了return语句,或者return语句中无表达式(有的编译系统如TurboC+3.0不允许),则将带回一个不确定的值。 要定义一个没有返回值的函数,应将函数值的类型明确定义为void(空)类型,以便告诉编译系统该函数不带回任何返回值。此时可以没有返回语句或使用不带表达式的返回语句:return ;。 一个函数体中可以有多个return语句。,例如: 如下的求2个整数最大值的max函数中就含有2个return语句。注意,该函数的末尾是该函数的唯一出口,即单出口。 int max ( int x , int y ) if ( x y ) return x ; else return y ; ,函数的返回值,调用有函数值的函数,其返回值也可以不用。例如,printf函数的返回值是它输出字符
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号