第08章--函数_第1页
第08章--函数_第2页
第08章--函数_第3页
第08章--函数_第4页
第08章--函数_第5页
已阅读5页,还剩104页未读 继续免费阅读

下载本文档

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

文档简介

1、C语言教学组语言教学组E-mail:Tel: 第第08章章 函数函数编写程序输出如编写程序输出如图所图所示的示的图形图形:模块化设计思路:模块化设计思路:合理合理的设计应该是将整个任务进行功能分的设计应该是将整个任务进行功能分解或过程抽象,将重复实现的功能用独立函数解或过程抽象,将重复实现的功能用独立函数实现,如用实现,如用DrawStar()函数输出星号,用函数输出星号,用DrawCircle()输出圆,用输出圆,用DrawTriangle ()输出三角输出三角形。这样,对于主函数而言,只需要通过调用形。这样,对于主函数而言,只需要通过调用多个功能独立且实现简单的函数,就可以实现多个功能独立

2、且实现简单的函数,就可以实现相对复杂的图形输出。相对复杂的图形输出。程序结构:程序结构:模块化程序设计的意义:模块化程序设计的意义:1. 由于由于具体的输出各个图形的功能代码从主函数中移到具体的输出各个图形的功能代码从主函数中移到了各自函数内部,因此主函数中只有对各个函数的调了各自函数内部,因此主函数中只有对各个函数的调用,没有具体实现的细节,可以保证其结构是清晰的。用,没有具体实现的细节,可以保证其结构是清晰的。2. 重复重复实现的功能,只需要编写一次代码。例如,虽然实现的功能,只需要编写一次代码。例如,虽然整个图形要求输出两个三角形,但只需要编写输出一整个图形要求输出两个三角形,但只需要编

3、写输出一个三角形的一段代码,只是对其重复调用即可,这就个三角形的一段代码,只是对其重复调用即可,这就是代码复用,可以有效降低程序的规模。是代码复用,可以有效降低程序的规模。3. 相比相比所有功能细节都实现在主函数中,这样的设计,所有功能细节都实现在主函数中,这样的设计,每个函数实现的复杂度都降低了很多,更易于实现。每个函数实现的复杂度都降低了很多,更易于实现。4. 如果如果某个图形有变化,如三角形有变化,只需要修改某个图形有变化,如三角形有变化,只需要修改输出三角形的函数输出三角形的函数DrawTriangle(),其他函数的代码,其他函数的代码都不受影响。都不受影响。分为:1.库函数2.用户

4、自定义函数分为:1.有返回值函数2.无返回值函数从函数的返回值来看分为:1.有参函数2.无参函数从调用者和被调用函数之间是否需要传送数据的角度来看定义格式:定义格式: 函数函数类型类型 函数名函数名(形式参数列表)(形式参数列表) 声明语句声明语句 执行执行语句语句 当当缺省缺省时,为时,为intint类型;类型;voidvoid可可限制函数无返回限制函数无返回值。值。可以省略可以省略例如:例如:1.2.1. 函数调用方法函数调用方法函数名函数名(实际参数列表实际参数列表)其中其中,实际参数列表的一般形式为:,实际参数列表的一般形式为:表达式表达式1,表达式,表达式2,表达式,表达式n2. 函

5、数调用过程函数调用过程3. 例如,求两数的较大值例如,求两数的较大值4. 求求两数的较大两数的较大值值的函数调用过程的函数调用过程1. 参数定义:参数定义:函数函数定义中用到的参数称为定义中用到的参数称为形式参数形式参数,简称,简称形参形参。而函数调用中使用的参数为而函数调用中使用的参数为实际参数实际参数,简称简称实参实参。顾名思义,实际参数是提供实际的顾名思义,实际参数是提供实际的值给形式参数,而对于形式参数而言,在其隶值给形式参数,而对于形式参数而言,在其隶属的函数未被调用前,形式参数并未在内存中属的函数未被调用前,形式参数并未在内存中实际存在,因此只是一种形式上存在的对象。实际存在,因此

6、只是一种形式上存在的对象。2. 示例:示例: 关于形参与实参的说明关于形参与实参的说明1.1. 在定义函数时,新标准要求必须在定义函数时,新标准要求必须分别指定分别指定每个形参每个形参的类型的类型, ,通常直接写在小括号内。旧标准是将类型说通常直接写在小括号内。旧标准是将类型说明写在小括号外。明写在小括号外。int max(int x,int y);int max(x,y) int x, y ; ;2.2. 实参实参与形参的与形参的类型类型、个数个数、顺序顺序通常一致。通常一致。3.3. 形参和实参的形参和实参的存储空间完全独立存储空间完全独立!#include#includeint main

7、(void)int main(void) int a,b; int a,b; scanf(%d%d,&a,&b); scanf(%d%d,&a,&b); printf printf(%(%d %dn,a,b);d %dn,a,b); swap(a,b);swap(a,b); printfprintf(%(%d %dn,a,b);d %dn,a,b); return 0; return 0; void swap(int x,int y) int temp; temp=x; x=y; y=temp; 如果输入为:如果输入为:2 3 2 3 ;请问输出结果?;请问输出

8、结果?main main 空间空间2 23 3a ab bswap swap 空间空间3 32 2x xy y 2 3 2 3 2 3 2 3 输出结果输出结果: :3 32 2形参的值形参的值在函数中被改变在函数中被改变并不影响并不影响实参实参的值!的值!阅读如下程序:阅读如下程序:函数类型和返回值类型不一致时以函数类型为准!函数类型和返回值类型不一致时以函数类型为准!运行情况运行情况10.23,25.68a,ba,b的较大值是:的较大值是:25.00 函数和变量一样函数和变量一样,通常在,通常在其主调函数中也要其主调函数中也要“先声先声明,后使用明,后使用”。注意关系注意关系: 函数函数定

9、义定义 创造函数创造函数 函数函数声明声明 准备使用准备使用 函数函数调用调用 使用函数使用函数函数声明格式:函数声明格式:数据类型数据类型 函数名函数名( (参数类型表参数类型表) );/ /* *函数原型函数原型* */ / 或或 数据类型数据类型 函数名函数名( )( ); / /* *旧版旧版* */ / 以下以下两两种种情况可以在主调函数中省略声明:情况可以在主调函数中省略声明: 1 1、被被调函数的定义出现在主调函数之前时;调函数的定义出现在主调函数之前时; 2 2、文件一开头,在所有函数之前,对所用函数作了文件一开头,在所有函数之前,对所用函数作了声声明明。 例如:例如:函数原型

10、的作用函数原型的作用: :1.1. 帮助编译器在编译阶段检查主调函数中的函数调帮助编译器在编译阶段检查主调函数中的函数调用语句和原型是否吻合,包括函数名和参数个数用语句和原型是否吻合,包括函数名和参数个数是否一致,如果不一致,系统将提醒用户有关函是否一致,如果不一致,系统将提醒用户有关函数调用的语句可能有错,这样可以尽可能使错误数调用的语句可能有错,这样可以尽可能使错误在开发阶段排除掉。在开发阶段排除掉。2.2. 函数原型的另一个作用就是指导编译器把实参隐函数原型的另一个作用就是指导编译器把实参隐式地转换为形参的类型。编译器要求实参和形参式地转换为形参的类型。编译器要求实参和形参的类型赋值兼容

11、即可。也就是说,如果实参与形的类型赋值兼容即可。也就是说,如果实参与形参类型不匹配,但是符合类型转换规则,则编译参类型不匹配,但是符合类型转换规则,则编译器将把实参的值转换为形参的类型,并为形参赋器将把实参的值转换为形参的类型,并为形参赋值。否则,拒绝编译。这样,函数原型可以强迫值。否则,拒绝编译。这样,函数原型可以强迫你使用正确的参数类型来调用函数,以避免运行你使用正确的参数类型来调用函数,以避免运行时可能出现的错误。时可能出现的错误。 数组元素数组元素和和整个数组整个数组均可以作为函数参数均可以作为函数参数数组元素只能做实参,不可以做形参数组元素只能做实参,不可以做形参【例例】: :假设假

12、设某学期某专业共某学期某专业共10门课,编写程序比门课,编写程序比较较A同学和同学和B同学各科成绩情况。分别统计并输同学各科成绩情况。分别统计并输出出A同学成绩高于同学成绩高于B同学的科目数、成绩相等的同学的科目数、成绩相等的科目数和成绩低于科目数和成绩低于B同学的科目数同学的科目数。任务分析:任务分析: 为了为了说明数组元素作函数参数,本任务用两个函数说明数组元素作函数参数,本任务用两个函数实现:实现:mainmain()()函数完成数据的输入和输出,函数完成数据的输入和输出,Judge()Judge()函函数完成具体两数的比较。数完成具体两数的比较。mainmain()()函数中主要包括如

13、下三步:函数中主要包括如下三步:1.1. 分别分别输入两个学生的输入两个学生的1010门课的成绩;门课的成绩;2.2. 调用调用Judge()Judge()函数完成对应科目成绩的比较;函数完成对应科目成绩的比较;3.3. 输出输出比较结果。比较结果。关于关于学生成绩的输入和对应成绩的比较,都需要学生成绩的输入和对应成绩的比较,都需要从头到尾遍历每个数组元素。从头到尾遍历每个数组元素。Judge()Judge()函数的功能是比较两数的大小情况,比较的函数的功能是比较两数的大小情况,比较的结果用变量结果用变量flagflag返回。如果前者大于后者,返回返回。如果前者大于后者,返回1 1;如;如果两

14、者相等,返回果两者相等,返回0 0;如果前者小于后者,返回;如果前者小于后者,返回-1-1。程序实现:程序实现:程序运行结果如下:程序运行结果如下:数组名做函数参数数组名做函数参数 数组名既可以做实参也可以做形参,数组名代数组名既可以做实参也可以做形参,数组名代表数组的表数组的首地址首地址,因此主调函数和被调函数是对,因此主调函数和被调函数是对同一个内存同一个内存区域进行操作区域进行操作, ,形参的操作会导致实形参的操作会导致实参的改变参的改变! a0a1a2a3a4a5a6a7a8a9a0a1a2a3a4a5a6a7a8a9 b0b1b2b3b4b5b6b7b8b9 b0b1b2b3b4b5

15、b6b7b8b9 【例例】编写程序实现两变量值的交换,其中值交换编写程序实现两变量值的交换,其中值交换的功能由自定义函数实现的功能由自定义函数实现。实现如下:实现如下:数组做数组做形参形参时,时,长度可省长度可省!也可以是!也可以是任意正整数任意正整数!1.2.【例例】编写程序实现编写程序实现33方阵的方阵的转置转置。任务分析:任务分析:在在C语言中处理数学上的矩阵,用二维数组很合适,语言中处理数学上的矩阵,用二维数组很合适,都是逻辑上若干行若干列的数据组织形式。本例中,用都是逻辑上若干行若干列的数据组织形式。本例中,用两个函数完成整个任务。其中两个函数完成整个任务。其中main()函数主要完

16、成数据函数主要完成数据的输入和输出,转置的功能用一个独立函数的输入和输出,转置的功能用一个独立函数Invert()完完成。关于转置算法,只需要一条双重循环语句就可完成。成。关于转置算法,只需要一条双重循环语句就可完成。外层循环遍历所有的行,内层循环遍历行内对角线下方外层循环遍历所有的行,内层循环遍历行内对角线下方的元素,然后将其和对角线上方的对称元素做互换,即的元素,然后将其和对角线上方的对称元素做互换,即可实现转置。可实现转置。程序实现:程序实现:函数中调用其它函数叫函数中调用其它函数叫函数的嵌套调用函数的嵌套调用。C C中函数的定义是平等的中函数的定义是平等的。除了除了mainmain以外

17、以外,都,都可以互相调用。可以互相调用。函数可以嵌套调用但不可以嵌套定义。函数可以嵌套调用但不可以嵌套定义。main().a 函数函数b函数函数【例例】删除某个字符串中的指定字符,比如将字符串“I love computer.”中的“o”删除,结果字符串就变成了“I Ive cmputer.”。任务分析:任务分析:如果将本任务只用main()函数实现,main()函数将会因为代码较多而显得结构不清楚。因此,可将整个任务按功能进行分解,然后用多个函数实现,这样,整个程序的结构将会很清晰,并且更易于实现。【例例】删除某个字符串中的指定字符,比如将字符串“I love computer.”中的“o”

18、删除,结果字符串就变成了“I Ive cmputer.”。任务分析:任务分析:如果将本任务只用main()函数实现,main()函数将会因为代码较多而显得结构不清楚。因此,可将整个任务按功能进行分解,然后用多个函数实现,这样,整个程序的结构将会很清晰,并且更易于实现。可用三个函数实现整个程序,功能分解如下:1. main()函数:实现数据的输入和输出。查找指定字符并将其删除的功能分解到SearchCharacter()函数中完成。2. SearchCharacter()函数:实现从头到尾遍历每个字符,如果当前字符等于要删除的字符,则调用DeleteCharacter()函数删除该字符。3. D

19、eleteCharacter()函数:实现具体的删除指定字符的功能。程序实现:执行流程:执行流程:递归调用的概念递归调用的概念: : 在在调用一个函数的过程中又出现调用一个函数的过程中又出现直接直接或或间接间接地地调用该函数本身,称为调用该函数本身,称为递归调用递归调用。1 1、直接递归调用:、直接递归调用:调用函数的过程中又调用该函数本身调用函数的过程中又调用该函数本身2 2、间接递归、间接递归调用:调用:Fun1Fun1函数中调用函数中调用Fun2Fun2函数函数,而,而FunFun2 2中又中又需要需要调用调用Fun1Fun1 递归法递归法 从结果出发,归纳出从结果出发,归纳出后一结果后

20、一结果与与前一结果前一结果直到初直到初值为止存在的关系。值为止存在的关系。 要求通过分析得到:要求通过分析得到: 初值初值+ +递归函数递归函数编程编程:设计一个函数(设计一个函数(递归函数递归函数),这个函数不断使),这个函数不断使用下一级值调用自身,直到结果已知处用下一级值调用自身,直到结果已知处选择选择结构结构。【例例】: :某猴子摘桃子,第一天摘了一些,吃了一半,忍不住又多吃一个;第二天将前一天剩下的桃子又吃了一半多一个。以此类推,到第十天早上桃子只剩一个了,请问猴子第一天摘了多少个桃子?数学模型:n+1n2(x1)1n9x1n=10程序实现:程序实现:调用过程:调用过程:P183 总

21、结总结: :递归调用的一般形式:递归调用的一般形式: 在主调函数中用终值在主调函数中用终值n n调用递归函数,而在递归函数中:调用递归函数,而在递归函数中: funfun(参数参数n n) 定义定义结果变量结果变量; if (if (n n=初值初值) ) 结果结果变量变量= =已知条件;已知条件; else else 结果结果变量变量= =含含fun(fun(n-1n-1) )或或fun(fun(n+1n+1) )的的表达式表达式; returnreturn(结果结果变量变量);); 作用域:指在源程序中定义变量的位置及其能被作用域:指在源程序中定义变量的位置及其能被读写访问的范围(读写访问

22、的范围(空间空间)。)。分类分类: : 局部变量局部变量(Local Variable) (Local Variable) 全局变量全局变量(Global Variable)(Global Variable) 局部变量局部变量:在函数内部或在函数内部或复合语句复合语句中定义的变量叫中定义的变量叫局部变量,局部变量,它在本函数(或复合语句)内有效它在本函数(或复合语句)内有效。例如:例如: 全局变量全局变量:在函数之外定义的变量叫全局变量在函数之外定义的变量叫全局变量, ,又名外部又名外部变量。变量。全局变量的全局变量的有效有效范围:范围:从定义的位置开始到文件结束从定义的位置开始到文件结束。i

23、nt p=1,q=5; int p=1,q=5; / /* *全局变量全局变量* */ / float f1(int a)float f1(int a) int b,c; int b,c; ; ; char c1,c2; char c1,c2; / /* *全局变量全局变量* */ /char f2(int x, int y); char f2(int x, int y); int i,j; int i,j; ; ; int main(void)int main(void) int m,n; int m,n; ; ; p,q的作用范围的作用范围c1,c2的作用范围的作用范围externexte

24、rn可以扩展全局变量的作用域可以扩展全局变量的作用域int p=1,q=5; /*全局变量全局变量*/ float f1(int a) int b,c; extern char c1,c2; ; char c1,c2; /*全局变量全局变量*/char f2(int x, int y); int i,j; ; int main(void) int m,n; ;c1,c2的作用范围的作用范围【例例】编写程序求得编写程序求得10个数的最大值、最小值和平均个数的最大值、最小值和平均值值。1. 分析分析问题。我们可以将全部功能分解在两个函数中问题。我们可以将全部功能分解在两个函数中实现:一个是实现:一

25、个是main()函数,另外一个称为函数,另外一个称为Calculate()函数。函数。main()函数只提供要计算的值和输出结果,函数只提供要计算的值和输出结果,而具体的计算最大值、最小值和平均值的功能由而具体的计算最大值、最小值和平均值的功能由Calculate()函数实现。这样就涉及一个问题:函数实现。这样就涉及一个问题:Calculate()函数需要给函数需要给main()函数返回三个值。大家函数返回三个值。大家知道知道return语句只能返回一个值,如何从被调函数语句只能返回一个值,如何从被调函数返回多个值呢?返回多个值呢?8.4.2节中介绍了数组名作函数参数节中介绍了数组名作函数参数

26、可以可以“返回返回”多个值,除此之外,我们可以采用另多个值,除此之外,我们可以采用另外一种方法外一种方法“返回返回”多个值,那就是全局变量。多个值,那就是全局变量。【例例】编写程序求得编写程序求得10个数的最大值、最小值和平均个数的最大值、最小值和平均值值。2. 程序设计程序设计 主要主要数据描述数据描述float max;/全局变量,存放最大值全局变量,存放最大值float min;/全局变量,存放最小值全局变量,存放最小值float average;/局部变量(局部变量(Calculate函数中定义),函数中定义),存放平均值存放平均值 算法设计算法设计l main()函数。函数。步骤步骤

27、1:输入:输入10个原始的数。个原始的数。步骤步骤2:调用:调用Calculate()函数计算最大值、最小值和平均()函数计算最大值、最小值和平均值。值。步骤步骤3:输出最大值、最小值和平均值。:输出最大值、最小值和平均值。l Calculate()函数。函数。步骤步骤1:用第一个数为:用第一个数为max、min、求和变量、求和变量(sum)赋初值。赋初值。步骤步骤2:在循环内遍历第二个数到最后一个数:在循环内遍历第二个数到最后一个数:如果该数大于如果该数大于max,则用该数更新,则用该数更新max;否则如果该数小于否则如果该数小于min,则用该数更新,则用该数更新min;将该数加到累加和变量

28、将该数加到累加和变量(sum)中。中。步骤步骤3:累加和变量:累加和变量(sum)除以除以n(值为值为10)赋给赋给average 变量。变量。步骤步骤4:返回:返回average。3. 程序实现程序实现当全局变量与局部变量同名时,局部变量优先当全局变量与局部变量同名时,局部变量优先。【例例】#include #include intint a a=3,=3,b b=5;=5;int max(int int max(int a a,int,int b b) ) int c; int c; c=ab ? a:b; c=ab ? a:b; return(c); return(c); int mai

29、n(void) int main(void) int int a a=8;=8; int max(int int max(int a a,int,int b b);); printf(“%d”,max(printf(“%d”,max(a a, ,b b);); return 0;return 0; 运行结果为 8 【例例】#includeint main(void) int x=1; int x=2; int x=3; printf(“x=%dn”, x ); printf(“x=%dn”, x ); printf(“x=%dn”, x ); return 0; 运行结果:运行结果:x=3 x

30、=2 x=1 对于同名变量,内层对于同名变量,内层变量的作变量的作用域内,外层的变量不起作用。用域内,外层的变量不起作用。使函数之间的数据交换更容易,也更高效使函数之间的数据交换更容易,也更高效 但是并但是并不推荐不推荐使用使用 因为多个函数都可以改写全局变量,其值容因为多个函数都可以改写全局变量,其值容易变得不确定易变得不确定尽量尽量少用少用全局变量。不得不用时,要严格全局变量。不得不用时,要严格控制对它的改写。控制对它的改写。1.1.模块化设计要求研究不同模块(函数、源文件)间模块化设计要求研究不同模块(函数、源文件)间变量的关系变量的关系2.2.变量两大属性:变量两大属性:数据类型数据类

31、型: 存储存储类别:类别:3.3.变量变量的完整定义格式应该为:的完整定义格式应该为: 存储类型存储类型 变量变量名名静态存储形式静态存储形式动态存储形式动态存储形式预留存储空间预留存储空间标准标准C C语言为变量定义了语言为变量定义了4 4种存储种存储类型类型:即即autoauto、staticstatic、registerregister和和externextern。这这4 4种存储类型可以分为两种生存期:永久的和临时的种存储类型可以分为两种生存期:永久的和临时的。永久永久生存的变量由于被存储在生存的变量由于被存储在静态存储区静态存储区而在整个程而在整个程序执行期间都存在,而临时生存的变量

32、由于被存储在序执行期间都存在,而临时生存的变量由于被存储在动态动态存储区或寄存器中存储区或寄存器中,在对应的函数执行结束后,所在存储,在对应的函数执行结束后,所在存储区就被释放,即变量不再存在区就被释放,即变量不再存在。autoauto和和registerregister变量的生存期均属于变量的生存期均属于“临时的临时的”,staticstatic和和externextern变量的生存期属于变量的生存期属于“永久的永久的”。C程序的内存映像图:程序的内存映像图:1. register型:可用型:可用于于局部变量局部变量、形式参数。形式参数。变量变量值存值存放在运算器的放在运算器的寄存器寄存器中

33、中存取速度快,一般只允存取速度快,一般只允许许23个,通常用于循环个,通常用于循环变量。(变量。(在微机的在微机的Turbo C中实际上自动转为中实际上自动转为auto型型)。由于编译器的自动)。由于编译器的自动优化越来越强大,现在很少用该存储类型了。优化越来越强大,现在很少用该存储类型了。2. auto型型变量变量值存放在主存储器的值存放在主存储器的动态存储区动态存储区 优点优点同一内存区可被不同变量反复使用同一内存区可被不同变量反复使用以上两种均属于以上两种均属于“动态存储动态存储”性质,即调用函数时才性质,即调用函数时才为这些变量分配单元,函数调用结束其值自动消失。为这些变量分配单元,函

34、数调用结束其值自动消失。l externextern型(外部变量型)型(外部变量型)函数函数外定义的变量被称为外部变量或全局变量,外外定义的变量被称为外部变量或全局变量,外部变量的默认存储类型是部变量的默认存储类型是externextern。关键字。关键字 extern extern 既可以用来定义外部变量的存储类型,又可以用来既可以用来定义外部变量的存储类型,又可以用来扩展外部变量的作用域,关于这一点扩展外部变量的作用域,关于这一点,务必,务必注意。注意。externextern变量存放变量存放在主存储器的在主存储器的静态存储区静态存储区。从从程序程序执行开始至结束,始终占用该存储空间。其值

35、可供执行开始至结束,始终占用该存储空间。其值可供其他源文件使用。其他源文件使用。未说明存储类别时,未说明存储类别时,函数内定义函数内定义的变量为的变量为auto型型,函数外定义函数外定义的变量为的变量为extern型型。例如:例如:例如:例如:为了区分定义和声明,经常将用于定义的为了区分定义和声明,经常将用于定义的externextern省略,且将定义的变量初始化,而声明是不可以赋值省略,且将定义的变量初始化,而声明是不可以赋值的。此外,的。此外,externextern也可以将全局变量的作用域扩展到也可以将全局变量的作用域扩展到定义它的源文件定义它的源文件之外之外。l staticstati

36、c型型系统系统将关键字将关键字staticstatic定义的变量存储在静态存储区定义的变量存储在静态存储区中,它既可以用来定义局部变量,又可以用来定义中,它既可以用来定义局部变量,又可以用来定义全局变量。如果用来定义局部变量,被称为全局变量。如果用来定义局部变量,被称为静态局静态局部变量部变量,反之称为,反之称为静态全局变量静态全局变量。e externxtern和和staticstatic变量均变量均属于属于“静态存储静态存储”性质性质,即,即从从变量变量定义处定义处开始,在整个程序执行期间其值都存在。开始,在整个程序执行期间其值都存在。例如:静态局部变量例如:静态局部变量例如:静态全局变量

37、(例如:静态全局变量(作用域仅限于定义的文件作用域仅限于定义的文件)内部函数和外部函数的定义内部函数和外部函数的定义内部函数:表示内部函数:表示 仅供本文件里调用的函数,在函数仅供本文件里调用的函数,在函数返回值前冠返回值前冠 static。允许。允许不同文件里出现不同文件里出现同名内部函数同名内部函数。 外部函数:可外部函数:可供其它文件里调用的函数,在函数返供其它文件里调用的函数,在函数返回值前冠回值前冠 extern 或或缺省缺省。函数函数默认是全局的(外部的默认是全局的(外部的)。)。例如:外部函数的使用例如:外部函数的使用预处理命令包括:预处理命令包括:1. 宏定义宏定义2. Inc

38、lude命令命令3. 条件编译条件编译1. 宏定义宏定义 不带参数的宏定义不带参数的宏定义格式:格式:#define 宏宏名名 宏体宏体 带参数的宏定义带参数的宏定义格式:格式:#define 宏宏名名(参数列表参数列表) 宏宏体体2. Include命令命令格式:格式: #include #include文件名文件名“由尖括号包括文件名的这种形式,预处理程序直接到开由尖括号包括文件名的这种形式,预处理程序直接到开发环境中设置的系统目录(子目录名通常为发环境中设置的系统目录(子目录名通常为 include)中)中查找查找所所包含的包含的文件文件。由双引号包括文件名的这种形式,。由双引号包括文件

39、名的这种形式,预处理程序先在源文件所在的用户目录中查找预处理程序先在源文件所在的用户目录中查找所所包含包含文文件件,如果找不到,再在设定的系统目录中查找。因此,如果找不到,再在设定的系统目录中查找。因此,在包含系统文件(如标准库文件)时应该用尖括号包括在包含系统文件(如标准库文件)时应该用尖括号包括文件名的形式;如果要包含用户自己定义的文件,该文文件名的形式;如果要包含用户自己定义的文件,该文件通常存放在与被处理源程序的同一个目录下,显然应件通常存放在与被处理源程序的同一个目录下,显然应该用双引号包括文件名的这种形式。此外,后一种形式该用双引号包括文件名的这种形式。此外,后一种形式允许在文件名

40、前允许在文件名前前缀路径前缀路径。2. Include命令命令格式:格式: #include #include文件名文件名“由尖括号包括文件名的这种形式,预处理程序直接到开由尖括号包括文件名的这种形式,预处理程序直接到开发环境中设置的系统目录(子目录名通常为发环境中设置的系统目录(子目录名通常为 include)中)中查找查找所所包含的包含的文件文件。由双引号包括文件名的这种形式,。由双引号包括文件名的这种形式,预处理程序先在源文件所在的用户目录中查找预处理程序先在源文件所在的用户目录中查找所所包含包含文文件件,如果找不到,再在设定的系统目录中查找。因此,如果找不到,再在设定的系统目录中查找。

41、因此,在包含系统文件(如标准库文件)时应该用尖括号包括在包含系统文件(如标准库文件)时应该用尖括号包括文件名的形式;如果要包含用户自己定义的文件,该文文件名的形式;如果要包含用户自己定义的文件,该文件通常存放在与被处理源程序的同一个目录下,显然应件通常存放在与被处理源程序的同一个目录下,显然应该用双引号包括文件名的这种形式。此外,后一种形式该用双引号包括文件名的这种形式。此外,后一种形式允许在文件名前允许在文件名前前缀路径前缀路径。l 处理文件包含命令的过程是处理文件包含命令的过程是:首先首先查找被包含文件,找到后就用该文件的内容查找被包含文件,找到后就用该文件的内容替换当前文件里对应的预处理

42、命令行。如果替换进来替换当前文件里对应的预处理命令行。如果替换进来的文件里仍有预处理命令,则它们也将被处理,直到的文件里仍有预处理命令,则它们也将被处理,直到没有预处理命令存在,预处理过程才结束。没有预处理命令存在,预处理过程才结束。l 文件包含命令允许嵌套,如文件包含命令允许嵌套,如file1.c文件中包含文件中包含file1.h,而而file1.h中包含中包含file2.h,示例如,示例如图图:l 预处理程序处理后:预处理程序处理后:3.条件编译条件编译 形式一 形式二3.条件编译条件编译 形式三3.条件编译条件编译C标准中还提供了一个词标准中还提供了一个词defined,常用于构成条件,

43、常用于构成条件编译的条件表达式,其使用形式为编译的条件表达式,其使用形式为:#defined 标识符 或 #defined(标识符)例如,为了保证例如,为了保证mymath.h文件的内容只被包含一次,文件的内容只被包含一次,可以将该文件的内容包含在下列形式的条件语句中:可以将该文件的内容包含在下列形式的条件语句中:为了方便使用:为了方便使用:因此,可用如下形式避免头文件的重复包含因此,可用如下形式避免头文件的重复包含:1. 分层分层和模块化程序设计和模块化程序设计为了便于开发,复杂的为了便于开发,复杂的软件项目软件项目通常通常采用采用层次化结构和模块化设计的方法开发层次化结构和模块化设计的方法

44、开发。分层分层设计的模式是把整个系统组织成设计的模式是把整个系统组织成一个相对独立的多层结构,每层由一个或一个相对独立的多层结构,每层由一个或多个模块构成。每个模块由一个或多个多个模块构成。每个模块由一个或多个C程程序构成。序构成。分层结构分层结构和模块化程序设计的具体方法是:自顶和模块化程序设计的具体方法是:自顶向下,先做整体的框架设计,根据功能将整个系统划向下,先做整体的框架设计,根据功能将整个系统划分为多层结构,每层可以是由一个模块或多个模块分为多层结构,每层可以是由一个模块或多个模块组组成,成,设计好层次和模块之间的接口,然后做模块内部设计好层次和模块之间的接口,然后做模块内部的设计的设计。框架框架设计的主要原则是各模块尽可能高内聚而低设计的主要原则是各模块尽可能高内聚而低耦合。高内聚是指一个模块(通常是一个耦合。高内聚是指一个模块(通常是一个.c文件和其接文件和其接口声明所在的口声明所在的.h文件)里面的函数,只有相互之间的调文件)里面的函数,只有相互之间的调用,而没有调用其他模块里面的函数,即尽可能减少用,而没有调用其他模块里面的函数,即尽可能减少不同模块里函数的交叉引用。低耦合是指一个完整的不同模块里函数的交叉引用。低耦合是指一个完整的系统中,模块与模块之间尽可能使其独立存在。也就系统中,模块与模块之间尽可能使其独立存在。也就是说,每个模块尽可能独立完

温馨提示

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

最新文档

评论

0/150

提交评论