第6章函数与编译预处理

上传人:re****.1 文档编号:568288718 上传时间:2024-07-23 格式:PPT 页数:94 大小:1.27MB
返回 下载 相关 举报
第6章函数与编译预处理_第1页
第1页 / 共94页
第6章函数与编译预处理_第2页
第2页 / 共94页
第6章函数与编译预处理_第3页
第3页 / 共94页
第6章函数与编译预处理_第4页
第4页 / 共94页
第6章函数与编译预处理_第5页
第5页 / 共94页
点击查看更多>>
资源描述

《第6章函数与编译预处理》由会员分享,可在线阅读,更多相关《第6章函数与编译预处理(94页珍藏版)》请在金锄头文库上搜索。

1、第第6章章 函数与编译预处函数与编译预处理理C语言程序设计教程2024/7/232C语言程序设计教程第6章 函数与编译预处理教学目的和基本要求:教学目的和基本要求:要求学生了解模块化程序设计的思想,掌握函数的定义及调用,理解变量的作用域与存储方式的概念,理解编译预处理的概念。 教学重点:教学重点:函数的定义及调用、递归调用、变量的作用域。 2 2C语言程序设计教程2024/7/233C语言程序设计教程第6章 函数与编译预处理6.1 模块化程序设计与函数模块化程序设计与函数 在在在在解解解解决决决决较较较较复复复复杂杂杂杂的的的的问问问问题题题题时时时时,我我我我们们们们一一一一般般般般采采采采

2、用用用用的的的的方方方方法法法法是是是是:把把把把问问问问题题题题分分分分成成成成几几几几个个个个部部部部分分分分,每每每每部部部部分分分分又又又又可可可可分分分分成成成成更更更更细细细细的的的的若若若若干干干干小小小小部部部部分分分分,逐逐逐逐步步步步细细细细化化化化,直直直直至至至至把把把把复复复复杂杂杂杂的的的的问问问问题题题题分分分分解解解解成成成成为为为为很很很很容容容容易易易易求求求求解解解解的的的的一一一一些些些些小小小小问问问问题题题题。这这这这样样样样,原原原原来来来来问问问问题题题题的的的的解解解解就就就就可可可可以以以以由由由由这这这这些些些些小小小小问问问问题的解来表示

3、了。题的解来表示了。题的解来表示了。题的解来表示了。 求解较小问题的程序模块称为求解较小问题的程序模块称为“功能模块功能模块”。一个。一个较大的程序一般都应分为若干个功能模块,每个模块用较大的程序一般都应分为若干个功能模块,每个模块用来实现一个特定的功能,这也就是模块化程序设计的思来实现一个特定的功能,这也就是模块化程序设计的思想。想。3 3C语言程序设计教程2024/7/234C语言程序设计教程第6章 函数与编译预处理一、模块与函数 在在在在C C C C语语语语言言言言中中中中是是是是用用用用函函函函数数数数来来来来实实实实现现现现模模模模块块块块功功功功能能能能的的的的,故故故故一一一一

4、个个个个C C C C程程程程序序序序可可可可以以以以由由由由一一一一个个个个主主主主函函函函数数数数和和和和若若若若干干干干个个个个其其其其它它它它函函函函数数数数构构构构成成成成。由由由由主主主主函函函函数数数数调调调调用用用用其其其其它它它它函函函函数数数数,其其其其它它它它函函函函数数数数也也也也可可可可以以以以互互互互相相相相调调调调用用用用,同同同同一一一一个函数可以被一个或多个函数调用任意多次。个函数可以被一个或多个函数调用任意多次。个函数可以被一个或多个函数调用任意多次。个函数可以被一个或多个函数调用任意多次。 C C C C语语语语言言言言就就就就是是是是通通通通过过过过函函

5、函函数数数数的的的的调调调调用用用用来来来来实实实实现现现现完完完完成成成成较较较较大大大大程程程程序序序序的全部功能。的全部功能。的全部功能。的全部功能。 模模模模块块块块化化化化的的的的程程程程序序序序设设设设计计计计就就就就是是是是靠靠靠靠设设设设计计计计函函函函数数数数和和和和调调调调用用用用函函函函数数数数实实实实现的。现的。现的。现的。4 4C语言程序设计教程2024/7/235C语言程序设计教程第6章 函数与编译预处理任务模块模块模块函数函数函数函数函数函数任务、任务、模块与函数的关系模块与函数的关系:5 5C语言程序设计教程2024/7/236C语言程序设计教程第6章 函数与编

6、译预处理例例例例6_1:6_1:从键盘输入两个数,求这两个数的较大值从键盘输入两个数,求这两个数的较大值从键盘输入两个数,求这两个数的较大值从键盘输入两个数,求这两个数的较大值main()main()inta,b,maxv;inta,b,maxv;scanf(%d%d,&a,&b);scanf(%d%d,&a,&b);maxv=maxv=max(a,b)max(a,b); ; star();star();printf(“themax_value=%dn,maxv);printf(“themax_value=%dn,maxv);star()star(); intmax(intxintmax(in

7、tx,inty)inty) intz;intz;if(xy)z=x;if(xy)z=x;elsez=y;elsez=y;returnz;returnz; voidstar()voidstar() printf(“*n”);printf(“*n”); 6 6C语言程序设计教程2024/7/237C语言程序设计教程第6章 函数与编译预处理二、模块设计的原则二、模块设计的原则1 1、模块独立:、模块独立: 独立性原则表现在模块完成独立的功能独立性原则表现在模块完成独立的功能, , 模块间的模块间的关系尽量简单关系尽量简单, ,各模块可以单独调试。修改某一模块各模块可以单独调试。修改某一模块, ,不不

8、会造成整个程序的混乱。会造成整个程序的混乱。2 2、模块规模适当:、模块规模适当: 模块不能太大模块不能太大, ,但也不能太小。模块太大,功能复杂但也不能太小。模块太大,功能复杂, ,可读性就不好。但如果模块太小,各个模块间反复调用,可读性就不好。但如果模块太小,各个模块间反复调用,也会增加程序的复杂度,可读性也会降低。这点需要在也会增加程序的复杂度,可读性也会降低。这点需要在不断的实践中慢慢积累经验。不断的实践中慢慢积累经验。7 7C语言程序设计教程2024/7/238C语言程序设计教程第6章 函数与编译预处理6.2 函数的定义与调用函数的定义与调用 在在在在C C语语语语言言言言中中中中,

9、 ,函函函函数数数数是是是是一一一一个个个个处处处处理理理理过过过过程程程程,可可可可以以以以进进进进行行行行数数数数值值值值运运运运算算算算、信信信信息息息息处处处处理理理理、控控控控制制制制决决决决策策策策等等等等,即即即即一一一一段段段段完完完完成成成成某某某某个个个个功功功功能能能能的的的的程程程程序序序序放放放放在在在在函函函函数数数数中中中中进进进进行行行行,函函函函数数数数结结结结束束束束时时时时可可可可以以以以携携携携带带带带或或或或不不不不携携携携带带带带处理结果。处理结果。处理结果。处理结果。 C C语语语语言言言言程程程程序序序序全全全全部部部部是是是是以以以以函函函函数

10、数数数的的的的形形形形式式式式出出出出现现现现,最最最最简简简简单单单单的的的的C C程序也至少要有一个程序也至少要有一个程序也至少要有一个程序也至少要有一个mainmain函数。函数。函数。函数。 函数必须先定义和声明后才能调用函数必须先定义和声明后才能调用函数必须先定义和声明后才能调用函数必须先定义和声明后才能调用。 从用户使用函数的角度来看,函数有两种:从用户使用函数的角度来看,函数有两种: 库函数库函数( (标准函数标准函数) ):系统提供的:系统提供的 用户自定义函数用户自定义函数:用户自己编写的:用户自己编写的8 8C语言程序设计教程2024/7/239C语言程序设计教程第6章 函

11、数与编译预处理一、标准库函数一、标准库函数 C C C C语言有丰富的库函数,这些函数的说明在不语言有丰富的库函数,这些函数的说明在不语言有丰富的库函数,这些函数的说明在不语言有丰富的库函数,这些函数的说明在不同的头文件同的头文件同的头文件同的头文件(*.(*.(*.(*.h)h)h)h)中。中。中。中。 想要调用标准的库函数,就必须用编译预处理想要调用标准的库函数,就必须用编译预处理想要调用标准的库函数,就必须用编译预处理想要调用标准的库函数,就必须用编译预处理命令命令命令命令includeincludeincludeinclude把程序中所用到的头文件包含进来。把程序中所用到的头文件包含进

12、来。把程序中所用到的头文件包含进来。把程序中所用到的头文件包含进来。例如:例如:例如:例如:include“stdio.h”# #includemain()printf(“%f”,sqrt(2*3);调用调用sqrt函数函数(求根号求根号)时,时,必须有必须有include9 9C语言程序设计教程2024/7/2310C语言程序设计教程第6章 函数与编译预处理函数定义的一般形式:函数定义的一般形式:函数定义的一般形式:函数定义的一般形式:函数类型名函数类型名函数类型名函数类型名 函数名函数名函数名函数名( ( ( ( 形式参数类型说明列表形式参数类型说明列表形式参数类型说明列表形式参数类型说明

13、列表) 局部变量说明部分局部变量说明部分局部变量说明部分局部变量说明部分 可执行语句序列可执行语句序列可执行语句序列可执行语句序列 二、函数的定义二、函数的定义例如:求两个数中的较大者的函数例如:求两个数中的较大者的函数例如:求两个数中的较大者的函数例如:求两个数中的较大者的函数intmax(intxintmax(intx,inty)/*inty)/*有两个整型的形式参数有两个整型的形式参数有两个整型的形式参数有两个整型的形式参数* */ /intz;/*intz;/*局部变量局部变量局部变量局部变量 z z定义定义定义定义* */ /if(xy)z=x;if(xy)z=x;elsez=y;e

14、lsez=y;returnz;/*returnz;/*返回语句,函数携带整型返回值返回语句,函数携带整型返回值返回语句,函数携带整型返回值返回语句,函数携带整型返回值* */ / 1010C语言程序设计教程2024/7/2311C语言程序设计教程第6章 函数与编译预处理函数定义分为两大部分:函数定义分为两大部分:函数定义分为两大部分:函数定义分为两大部分:函数的说明函数的说明函数的说明函数的说明部分和部分和部分和部分和函数体函数体函数体函数体部分。部分。部分。部分。1.1.1.1.函数说明部分(函数首部)函数说明部分(函数首部)函数说明部分(函数首部)函数说明部分(函数首部) (1 1 1 1

15、)函数类型)函数类型)函数类型)函数类型:即函数返回值的类型。:即函数返回值的类型。:即函数返回值的类型。:即函数返回值的类型。 如如如如上上上上例例例例中中中中函函函函数数数数的的的的类类类类型型型型是是是是intintintint,即即即即函函函函数数数数的的的的返返返返回回回回值值值值z z z z是是是是intintintint类类类类型型型型。如如如如果果果果函函函函数数数数有有有有返返返返回回回回值值值值,要要要要用用用用返返返返回回回回语语语语句句句句returnreturnreturnreturn。returnreturnreturnreturn语句的一般形式是:语句的一般形式

16、是:语句的一般形式是:语句的一般形式是: returnreturnreturnreturn(表达式);(表达式);(表达式);(表达式); 或或或或 return return return return 表达式;表达式;表达式;表达式;(2 2)函数名)函数名 函数名是用户定义函数时自己命名的,其命名遵循函数名是用户定义函数时自己命名的,其命名遵循函数名是用户定义函数时自己命名的,其命名遵循函数名是用户定义函数时自己命名的,其命名遵循C C C C 语言标识符命名规则。语言标识符命名规则。语言标识符命名规则。语言标识符命名规则。 如果函数不需要提供返回值,可定义函数类型为空如果函数不需要提供

17、返回值,可定义函数类型为空如果函数不需要提供返回值,可定义函数类型为空如果函数不需要提供返回值,可定义函数类型为空类型。类型。类型。类型。空类型空类型的标识符为的标识符为的标识符为的标识符为voidvoidvoidvoid,例如:,例如:,例如:,例如: void starvoid starvoid starvoid star()()()() printf(“*n”); printf(“*n”); printf(“*n”); printf(“*n”); 1111C语言程序设计教程2024/7/2312C语言程序设计教程第6章 函数与编译预处理(3 3 3 3)参数列表)参数列表)参数列表)参数

18、列表 函数名后的()内是参数列表,由一个或多个函数名后的()内是参数列表,由一个或多个函数名后的()内是参数列表,由一个或多个函数名后的()内是参数列表,由一个或多个类型标识类型标识类型标识类型标识符符符符 变量名变量名变量名变量名组成。参数列表中的变量称为组成。参数列表中的变量称为组成。参数列表中的变量称为组成。参数列表中的变量称为形式参数形式参数形式参数形式参数,简称形,简称形,简称形,简称形参。如参。如参。如参。如int max(int xint max(int xint max(int xint max(int x,int yint yint yint y) 根据函数是否需要参数,可将

19、函数分为根据函数是否需要参数,可将函数分为根据函数是否需要参数,可将函数分为根据函数是否需要参数,可将函数分为无参函数无参函数无参函数无参函数和和和和有参有参有参有参函数函数函数函数两种。(注意:无参函数的函数名后的两种。(注意:无参函数的函数名后的两种。(注意:无参函数的函数名后的两种。(注意:无参函数的函数名后的( )( )( )( )也不能省也不能省也不能省也不能省!)!)!)!) 例如:打印一排例如:打印一排例如:打印一排例如:打印一排 * * * * 的函数的函数的函数的函数 void star( ) void star( ) /* /* 函数无形式参数,无返回值函数无形式参数,无返

20、回值函数无形式参数,无返回值函数无形式参数,无返回值* */ / printf(“n*n”); printf(“n*n”); 2. 2. 2. 2.函数体函数体函数体函数体 内内内内的的的的部部部部分分分分是是是是函函函函数数数数体体体体,包包包包含含含含局局局局部部部部变变变变量量量量定定定定义义义义部部部部分分分分和和和和执执执执行语句序列。行语句序列。行语句序列。行语句序列。1212C语言程序设计教程2024/7/2313C语言程序设计教程第6章 函数与编译预处理 说明:说明:函数定义不允许嵌套函数定义不允许嵌套。 在语言中,所有函数(包括主函数在语言中,所有函数(包括主函数main()

21、main())都是平级的。一个函数的定义,可以放)都是平级的。一个函数的定义,可以放在程序中的任意位置,主函数在程序中的任意位置,主函数main() main() 之前或之之前或之后。后。 但在任意一个函数(包括主函数)的函数体内但在任意一个函数(包括主函数)的函数体内( (即即 内),不能再定义另一个函数,即函数不内),不能再定义另一个函数,即函数不能嵌套定义。能嵌套定义。1313C语言程序设计教程2024/7/2314C语言程序设计教程第6章 函数与编译预处理函数定义举例函数定义举例1.编写求编写求x的的n次方的函数,要求返回计算结果。次方的函数,要求返回计算结果。intpower(int

22、x,intn)intj;inty=1;for(j=1;j=n;j+)y=y*x;returny;main()intm,n;m=power(2,3);n=power(3,2);1414C语言程序设计教程2024/7/2315C语言程序设计教程第6章 函数与编译预处理2. 2. 求求求求200,1000200,1000的双胞胎数的对数。双胞胎数:两素数差为的双胞胎数的对数。双胞胎数:两素数差为的双胞胎数的对数。双胞胎数:两素数差为的双胞胎数的对数。双胞胎数:两素数差为2 2称称称称为双胞胎数。下面是我们用现在所学的知识编的程序。为双胞胎数。下面是我们用现在所学的知识编的程序。为双胞胎数。下面是我们

23、用现在所学的知识编的程序。为双胞胎数。下面是我们用现在所学的知识编的程序。main()inta,b,n=0,I;for(a=200;a=998;a+)for(I=2;Ia;I+)if(a%I=0)break;if(a=i)b=a+2;for(I=2;Ib;I+)if(b%I=0)break;if(b=i)n+;printf(“n%d”,n);我们注意到,程序中我们注意到,程序中用用筐住的部分是筐住的部分是完成了相同的功能,完成了相同的功能,即判断一个数即判断一个数(a或或b)是否是素数。是否是素数。我们可以考虑用一个我们可以考虑用一个独立的函数来完成判独立的函数来完成判断素数的功能,在主断素数

24、的功能,在主函数中调用此函数即函数中调用此函数即可。如下:可。如下:1515C语言程序设计教程2024/7/2316C语言程序设计教程第6章 函数与编译预处理main()inta,b,n=0;intf(intx);for(a=200;a=998;a+)if(f(a)=1)b=a+2;if(f(b)=1)n+;printf(“n%d”,n); intf(intx)intI;for(I=2;Ix;I+)if(x%I=0)break;if(x=I)return1;elsereturn0;下面我们详细介绍函数调用的格式和语法规定。下面我们详细介绍函数调用的格式和语法规定。1616C语言程序设计教程20

25、24/7/2317C语言程序设计教程第6章 函数与编译预处理1 1、函数调用的一般形式:函数调用的一般形式: 调用有参函数调用有参函数:函数名(实参列表);:函数名(实参列表); 调用无参函数调用无参函数:函数名(:函数名( );); 如如果果实实参参表表列列包包括括多多个个实实参参,则则实实参参间间用用逗逗号号隔隔开开(注注意意:实实参参与与形形参参的的个个数数必必须须相相等等,类类型型应应一一致致或或赋赋值值兼兼容容),实参与形参是按照对应位置一一传递数据的。如:实参与形参是按照对应位置一一传递数据的。如:三、函数的调用三、函数的调用intpower(intx,intn)intj;inty

26、=1;for(j=1;jb)?a:b;y=(ab)?a:b;returny;returny; 调用时调用时:m=max(3,6);m=max(a,b);括号里是形式参数括号里是形式参数括号里是形式参数括号里是形式参数返回值返回值返回值返回值括号里是实参括号里是实参括号里是实参括号里是实参在这一句调用时,在这一句调用时,在这一句调用时,在这一句调用时,形参的值是形参的值是形参的值是形参的值是3 3和和和和6 6其返回值其返回值其返回值其返回值y y将被赋给将被赋给将被赋给将被赋给调用语句中的调用语句中的调用语句中的调用语句中的mm1818C语言程序设计教程2024/7/2319C语言程序设计教程

27、第6章 函数与编译预处理2 2、函数调用的方式函数调用的方式(1)(1)函数语句调用:函数语句调用:printf(“%d”,3); printf(“%d”,3); (2)(2)函数表达式函数表达式 y=power(2,3)y=power(2,3)1;1;(3)(3)函数参数函数参数 函数调用作为一个函数的实参如:函数调用作为一个函数的实参如: maxval=max(power(2,3),power(3,2); maxval=max(power(2,3),power(3,2);3 3、对被调用函数的声明和函数原型对被调用函数的声明和函数原型在一个函数中调用另一函数需要具备的条件:在一个函数中调用

28、另一函数需要具备的条件:a.a.调用的函数必须是已经存在的函数(是库函数或自己调用的函数必须是已经存在的函数(是库函数或自己定义的函数)定义的函数)1919C语言程序设计教程2024/7/2320C语言程序设计教程第6章 函数与编译预处理 b. b.对被调用函数进行如下说明:对被调用函数进行如下说明: 如如果果是是自自己己定定义义的的函函数数(下下面面标标号号为为的的情情况况除除外外)则则应应在在主主调调函函数数中中进进行行声声明明,其其声声明明的的一一般般形形式式为为: 函数的首部;函数的首部; /* /* ;分号一定不可少;分号一定不可少 * */ / 如:如: intpower(intx

29、,intn); 在在C C语言中,以上的语言中,以上的函数声明函数声明称为称为函数原型函数原型。下面几种情况,函数声明可以省略:下面几种情况,函数声明可以省略: a.a.被被调调函函数数的的定定义义在在主主调调函函数数之之前前,即即先先定定义义后后使使用。用。 b. b.当函数的类型为当函数的类型为intint型、型、charchar型或型或voidvoid型时。型时。2020C语言程序设计教程2024/7/2321C语言程序设计教程第6章 函数与编译预处理例如例如例如例如: : 计算计算计算计算1!+2!+3!+10! 1!+2!+3!+10! 的值的值的值的值voidmain()voidm

30、ain() longmm(intn);longmm(intn); inti;inti;longs=0;longs=0;printf(“n%ld”,s);printf(“n%ld”,s); longmm(intn)/*求求n!*/longt=1;inti;for(i=1;i=n;i+)t*=i;returnt;函数调用举例函数调用举例for(i=1;i=10;i+)s+=mm(i);2121C语言程序设计教程2024/7/2322C语言程序设计教程第6章 函数与编译预处理4.函数的嵌套调用函数的嵌套调用C语语言言不不允允许许嵌嵌套套定定义义函函数数,但但可可以以嵌嵌套套调调用用函函数数,也也就就

31、是说,在执行被调用函数时,被调用函数又调用了其它函数。是说,在执行被调用函数时,被调用函数又调用了其它函数。main()f1();f1()f2();f2()2222C语言程序设计教程2024/7/2323C语言程序设计教程第6章 函数与编译预处理例如例如例如例如: : 计算计算计算计算1!+2!+3!+10! 1!+2!+3!+10! 的值的值的值的值voidmain()voidmain()longsum();longsum();printf(“n%ld”,sum();printf(“n%ld”,sum(); longmm(intn)/*求求n!*/longt=1;inti;for(i=1;i

32、=n;i+)t*=i;returnt;函数嵌套调用举例函数嵌套调用举例longsum()/*求求n!之和!之和*/longmm(intn);intI;longs=0;for(i=1;iy)z=x;if(xy)z=x;elsez=y;elsez=y;returnz;returnz; main()main() Inta,b,m;Inta,b,m;scanf(“%d%d”,&a,&b);scanf(“%d%d”,&a,&b);m=m=max(a,b)max(a,b); ;printf(“%d,%d”,a,b);printf(“%d,%d”,a,b); 2525C语言程序设计教程2024/7/2326

33、C语言程序设计教程第6章 函数与编译预处理6.3函数的递归调用函数的递归调用一、递归的定义一、递归的定义函数调用它本身,称为函数调用它本身,称为递归递归。直接在函数内调用自己为。直接在函数内调用自己为直接递归直接递归,通过别的函数调用自己为,通过别的函数调用自己为间接递归间接递归。voida().a();.voida().b();.voidb().a();.注意:注意:为了防止递归调用无终止地为了防止递归调用无终止地进行,在函数体内必须有使递归调进行,在函数体内必须有使递归调用终止的条件。用终止的条件。常用的办法是常用的办法是: 加条件判断,满足加条件判断,满足某种条件后就不再作递归调用,然某

34、种条件后就不再作递归调用,然后逐层返回。后逐层返回。2626C语言程序设计教程2024/7/2327C语言程序设计教程第6章 函数与编译预处理 例例6_56_5:有:有5 5个人坐在一起,问第个人坐在一起,问第5 5个人多少岁?他说个人多少岁?他说比第比第4 4个人大个人大2 2岁。问第岁。问第4 4个人岁数,他说比第个人岁数,他说比第3 3个人大个人大2 2岁。问岁。问第第3 3个人,又说比第个人,又说比第2 2个人大个人大2 2岁。问第岁。问第2 2个人,说比第个人,说比第1 1个人大个人大2 2岁。最后问第岁。最后问第1 1个人,他说是个人,他说是1010岁。请问第岁。请问第5 5个人多

35、大?个人多大? 显然,根据题意我们可以得出以下等式:显然,根据题意我们可以得出以下等式: age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10 二、简单的递归程序举例二、简单的递归程序举例 可可以以看看到到,当当nlnl时时,求求第第n n个个人人的的年年龄龄的的公公式式是是相相同同的,因此可以用一个函数表示上述关系。的,因此可以用一个函数表示上述关系。 age(1)=l0 ( (递归调用结束条件)递归调用结束条件) age(n)=age(n-1)十十2(n1)(递归操作)递归操作)2727C语言程序设计教程

36、2024/7/2328C语言程序设计教程第6章 函数与编译预处理根据上述分析,可得求第根据上述分析,可得求第n n个人的年龄的程序如下:个人的年龄的程序如下:intage(intn)/*求第求第n个人年龄的函数个人年龄的函数*/intc;if(n=1)c=10;elsec=age(n-1)+2;return(c);main()printf(%d,age(5);2828C语言程序设计教程2024/7/2329C语言程序设计教程第6章 函数与编译预处理下图表示求第下图表示求第下图表示求第下图表示求第5 5 5 5个人年龄的递归调用过程。个人年龄的递归调用过程。个人年龄的递归调用过程。个人年龄的递归

37、调用过程。2929C语言程序设计教程2024/7/2330C语言程序设计教程第6章 函数与编译预处理例例例例6_66_6递归方法求递归方法求递归方法求递归方法求n!n! 由于由于n!=n*(n-1)!是递归定义,所以也可以用函数递是递归定义,所以也可以用函数递归调用来实现。归调用来实现。若要求若要求n!只要求出只要求出(n-1)!)!即可即可(n-1)!(n-2)!)!(n2)!(n-3)!)!1!而已知而已知0!=1,1!=1。再反过来就可以依次求出再反过来就可以依次求出2!直到最后求出直到最后求出n!。!。3030C语言程序设计教程2024/7/2331C语言程序设计教程第6章 函数与编译

38、预处理#include“stdlib.h”longf(intn)longy;if(nC,AB,CB, AC,BA,BC, AC 共经历7步,由此可以推出:移动n个盘子要经历2n 1步。步。3636C语言程序设计教程2024/7/2337C语言程序设计教程第6章 函数与编译预处理1 1、将、将A A上上n-1n-1个盘借助个盘借助C C座先移到座先移到B B座上。座上。 2 2、把、把A A座上剩下的一个盘移到座上剩下的一个盘移到C C座上。座上。3、将将n-1个盘从个盘从B座借助于座借助于A座移到座移到C座上。座上。 将将n n个盘子从个盘子从A A座移到座移到C C座可以分解为以下座可以分解

39、为以下3 3个步骤:个步骤:3737C语言程序设计教程2024/7/2338C语言程序设计教程第6章 函数与编译预处理递归方法解汉诺塔递归方法解汉诺塔voidhanoi(intn,charA,charB,charC)if(n=1)printf(“n“n%c-%c”,A,C);elsehanoi(n-1,A,C,B);printf(“n“n%c-%c”,A,C);hanoi(n-1,B,A,C);n=1时时,直接将盘子直接将盘子从从A座移动到座移动到C座座将将n-1个盘子从个盘子从A座经座经过过C座移动到座移动到B座座将第将第n个盘子个盘子从从A座移动到座移动到C座座再将再将n-1个盘子从个盘子

40、从B座经过座经过A座移动到座移动到C座座main()intn;printf(“n“ninputn:”);scanf(“%d”,&n);hanoi(n,A,B,C);将将n个盘子从个盘子从A座经座经过过B座移动到座移动到C座座3838C语言程序设计教程2024/7/2339C语言程序设计教程第6章 函数与编译预处理1.1.局部变量局部变量 在在一一个个函函数数内内部部定定义义的的变变量量是是内内部部变变量量,它它只只在在本本函函数数范范围围内内有有效效,也也就就是是说说只只有有在在本本函函数数内内才才能能使使用用它它们们,在在此此函函数数以以外外是是不不能能使使用用这这些些变变量量的的。这这样样

41、的的变变量量我们称之为我们称之为局部变量。局部变量。6.6.4 4 变量的作用域与存储方式变量的作用域与存储方式 一一. .变量的作用域变量的作用域: :即变量的有效范围即变量的有效范围 变量按作用域分为变量按作用域分为局部变量局部变量和和全局变量全局变量3939C语言程序设计教程2024/7/2340C语言程序设计教程第6章 函数与编译预处理intf1(intx)inta,b;main()intm,n;m=f1();a,b,x的有效范围的有效范围m,n的有效范围的有效范围4040C语言程序设计教程2024/7/2341C语言程序设计教程第6章 函数与编译预处理 (1) (1)主函数主函数ma

42、inmain中定义的变量中定义的变量( (m,n)m,n)也只在主函数中有效也只在主函数中有效, ,而不因为在主函数中定义而在整个文件或程序中有效而不因为在主函数中定义而在整个文件或程序中有效, ,主函主函数也不能使用其他函数中定义的变量。数也不能使用其他函数中定义的变量。 (2) (2)不同函数中可以定义相同名字的变量不同函数中可以定义相同名字的变量, ,它们代表不同它们代表不同的对象的对象, ,在内存中占不同的单元在内存中占不同的单元, ,互不混淆互不混淆, ,互不干扰。互不干扰。 (3) (3)形式参数也是局部变量形式参数也是局部变量, ,只在本函数中有效只在本函数中有效, ,其他函数其

43、他函数不能使用。不能使用。 (4)4)在函数体内的复合语句中也可以定义局部变量,它们在函数体内的复合语句中也可以定义局部变量,它们的作用范围只在复合语句内。的作用范围只在复合语句内。 2 2、局部变量的说明、局部变量的说明4141C语言程序设计教程2024/7/2342C语言程序设计教程第6章 函数与编译预处理main()intm,n;.intc;c=m*n; m m、n n在此范围内有效在此范围内有效 . . . . c c在此范围内有效在此范围内有效 . . . . . . 4242C语言程序设计教程2024/7/2343C语言程序设计教程第6章 函数与编译预处理 在在函函数数之之外外定定

44、义义的的变变量量叫叫作作全全局局变变量量,其其有有效效范范围围为为从定义变量的位置开始到本源文件结束。如:从定义变量的位置开始到本源文件结束。如:3 3. .全局变量全局变量intp=1,q=5;floatf1(inta)charc1,c2;charf2(intx,chary)main()全局变量全局变量p、q的作用范围的作用范围全局变量全局变量c1、c2的作用范围的作用范围4343C语言程序设计教程2024/7/2344C语言程序设计教程第6章 函数与编译预处理(1)在在一一个个函函数数中中既既可可以以使使用用本本函函数数中中的的局局部部变变量量,又可以使用有效的全局变量。又可以使用有效的全

45、局变量。 (2) (2)如果在同一个文件中,外部变量与局部变量同名,如果在同一个文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量被则在局部变量的作用范围内,外部变量被“屏蔽屏蔽”,即,即它不起作用。它不起作用。注:注:建议不在必要时不要使用全局变量,因为全局变量建议不在必要时不要使用全局变量,因为全局变量过多,会降低程序的清晰性,往往难以清楚地判断出每过多,会降低程序的清晰性,往往难以清楚地判断出每个瞬时各个外部变量的值。个瞬时各个外部变量的值。4 4. .全局变量的说明全局变量的说明4444C语言程序设计教程2024/7/2345C语言程序设计教程第6章 函数与编译预处理#

46、 # # #include include include include int a,b; /*aint a,b; /*aint a,b; /*aint a,b; /*a,b b b b为全局变量为全局变量为全局变量为全局变量*/*/*/*/ void f1(int x void f1(int x void f1(int x void f1(int x,int y ) int y ) int y ) int y ) int a,b; /*int a,b; /*int a,b; /*int a,b; /*此此此此a,ba,ba,ba,b是局部变量是局部变量是局部变量是局部变量*/*/*/*/

47、a=x*y; a=x*y; a=x*y; a=x*y; b=10 b=10 b=10 b=10; printf(“f1:a=%d,b=%dn”,a,b); printf(“f1:a=%d,b=%dn”,a,b); printf(“f1:a=%d,b=%dn”,a,b); printf(“f1:a=%d,b=%dn”,a,b); main( ) main( ) main( ) main( ) a=2; b=4; /* a=2; b=4; /* a=2; b=4; /* a=2; b=4; /* 此此此此a,ba,ba,ba,b是全局变量,赋值是全局变量,赋值是全局变量,赋值是全局变量,赋值 */

48、 */ */ */ f1(af1(af1(af1(a,b); /* b); /* b); /* b); /* 调用函数调用函数调用函数调用函数f1( ) */ f1( ) */ f1( ) */ f1( ) */ printf (“main: a=%d,b=%d”, a, b); printf (“main: a=%d,b=%d”, a, b); printf (“main: a=%d,b=%d”, a, b); printf (“main: a=%d,b=%d”, a, b); 程序输出结果为程序输出结果为程序输出结果为程序输出结果为: : : : f1:a=8,b=10f1:a=8,b=1

49、0main:a=2,b=10main:a=2,b=10全局变量全局变量a,b的作用范围的作用范围局部变量局部变量a,b的作用范围的作用范围4545C语言程序设计教程2024/7/2346C语言程序设计教程第6章 函数与编译预处理二二. .变量的存储特性变量的存储特性 静态存储静态存储类型的变量的类型的变量的生存期为程序运行的整个过程生存期为程序运行的整个过程,在该过程中它们一直占有固定的存储空间,通常称它们为在该过程中它们一直占有固定的存储空间,通常称它们为永久永久存储存储的变量。如:的变量。如:全局变量、静态的局部变量全局变量、静态的局部变量;动态存储动态存储类型变量类型变量只存在某一段时间

50、内只存在某一段时间内。例如,。例如,函数的函数的形参和函数体内定义的局部变量形参和函数体内定义的局部变量,它们只有当程序调用该函它们只有当程序调用该函数时才能得到存储空间,当该函数执行完后,数时才能得到存储空间,当该函数执行完后,变量的存储空变量的存储空间又被撤销了。间又被撤销了。1.1.1.1.变量按存在时间可分为变量按存在时间可分为变量按存在时间可分为变量按存在时间可分为 静态存储类型的变量静态存储类型的变量静态存储类型的变量静态存储类型的变量 动态存储类型的变量动态存储类型的变量动态存储类型的变量动态存储类型的变量4646C语言程序设计教程2024/7/2347C语言程序设计教程第6章

51、函数与编译预处理 存存存存储储特特特特性性性性是是是是指指指指数数数数据据据据在在在在内内内内存存存存中中中中存存存存储储的的的的方方方方式式式式,存存存存储储方方方方式式式式分分分分为为静静静静态态存存存存储储类类和和和和动动态态存存存存储储类类,具具具具体体体体包包包包含含含含四四四四种种种种:autoautoautoauto(自自自自动动动动型型型型)、staticstaticstaticstatic(静静静静态态态态型型型型)、externexternexternextern(外外外外部部部部型型型型)、 registerregisterregisterregister(寄寄寄寄存存存

52、存器型)器型)器型)器型)。 (1 1)自动变量()自动变量(autoauto):):(autoauto)变量类型)变量类型 变量名;变量名; C C语言规定,凡未加存储类型说明的变量均被视为自语言规定,凡未加存储类型说明的变量均被视为自动变量,即动变量,即自动变量可以省略自动变量可以省略autoauto存储类型说明符存储类型说明符。如。如前面各章中所定义的变量前面各章中所定义的变量凡未加存储类型说明符的均是凡未加存储类型说明符的均是autoauto变量变量。 例如:例如:int aint a,b b; 等价于等价于 auto int a,bauto int a,b;2. 2. 变量的存储特性

53、变量的存储特性 c c语言中每一个变量有两个属性语言中每一个变量有两个属性: :数据类型数据类型, , 存储类型。存储类型。完整的变量定义完整的变量定义: : 存储类型存储类型 数据类型数据类型 变量名变量名; ;4747C语言程序设计教程2024/7/2348C语言程序设计教程第6章 函数与编译预处理自动变量的特点:自动变量的特点: 自自动动变变量量是是动动态态分分配配存存储储方方式式,只只有有当当定定义义该该变变量量的的函函数数被被调调用用时时才才会会给给它它分分配配存存储储单单元元,函函数数调调用用结结束束,存存储储单单元释放。元释放。 自自动动变变量量的的作作用用域域和和生生存存期期都

54、都在在定定义义它它的的函函数数或或复复合合语语句句内内,因因此此不不同同函函数数内内允允许许使使用用相相同同的的变变量量名名,而而不不会会引引起起混淆。例如:混淆。例如:main()autointa=1,b=2;/*auto可省略:可省略:inta=1,b=2;*/if(a0)autointb;/*auto可省略:可省略:intb*/b=a;printf(“%d,%d”,a,b);printf(“%d,%d”,a,b);4848C语言程序设计教程2024/7/2349C语言程序设计教程第6章 函数与编译预处理静态局部变量静态局部变量 (2)(2)静态变量(静态变量(staticstatic):

55、):static static 变量类型变量类型 变量名;变量名; 在在局局部部变变量量类类型型定定义义前前加加上上staticstatic,就就构构成成了了静静态态局局部部变变量。量。 例如:例如:f1f1()() static int astatic int a2 2,b b; 静静态态局局部部变变量量的的值值在在函函数数调调用用结结束束后后不不会会消消失失而而会会保保留留原值,直到整个程序运行结束原值,直到整个程序运行结束。 在编译时在编译时,系统就为静态变量分配存储空间,并自动为,系统就为静态变量分配存储空间,并自动为它们它们赋初值赋初值0(0(对数值型变量对数值型变量) )或空字符或

56、空字符( (对字符变量对字符变量) );4949C语言程序设计教程2024/7/2350C语言程序设计教程第6章 函数与编译预处理例例例例: :分析下面程序的执行结果分析下面程序的执行结果分析下面程序的执行结果分析下面程序的执行结果f(inta)f(inta)intb=0;staticintc=3;intb=0;staticintc=3;b+;c+;b+;c+;printf(“%dprintf(“%d,%d%d,%d”,a,b,c);%d”,a,b,c);return(a+b+c);return(a+b+c); main()main()inta=2,k;inta=2,k;for(k=0;k3;

57、k+)for(k=0;k3;k+)printf(“%5dn”,f(a);printf(“%5dn”,f(a); 静态变量静态变量c无论函数调用无论函数调用其多少次,它都只被初其多少次,它都只被初始化赋值一次始化赋值一次运行结果:运行结果:214(a,b,c)7(f(a)215821695050C语言程序设计教程2024/7/2351C语言程序设计教程第6章 函数与编译预处理(3)extern型型:extern 变量类型变量类型 变量名变量名; ; 如果某个模块文件中要用到另一个模块文件中的如果某个模块文件中要用到另一个模块文件中的非静非静态全局变量态全局变量,就要用,就要用externexte

58、rn说明。说明。静态全局变量静态全局变量 用用staticstatic声明的全局变量叫作静态全局变量。静态全局声明的全局变量叫作静态全局变量。静态全局变量只限于被变量只限于被本文件本文件引用,而不能被其它模块文件引用。引用,而不能被其它模块文件引用。5151C语言程序设计教程2024/7/2352C语言程序设计教程第6章 函数与编译预处理例如例如: :程序模块程序模块file1.cfile1.c中定义了全局变量中定义了全局变量 int s ;/* int s ;/* 定义全局变量定义全局变量s */s */ main main()() 如果在另一个程序如果在另一个程序file2.cfile2.

59、c中的函数中的函数fun1( )fun1( )中需要使中需要使用这个变量用这个变量s s,可以在,可以在file2.cfile2.c的函数的函数fun1( )fun1( )中加上如下中加上如下所示的外部变量说明语句所示的外部变量说明语句: : fun1( ) fun1( ) extern int s;extern int s; /* /*表明变量表明变量s s是在其他文件定义是在其他文件定义的的*/*/ . . 在定义时给在定义时给s s分配内存分配内存, ,其他文件引用时不再分配内存其他文件引用时不再分配内存. .5252C语言程序设计教程2024/7/2353C语言程序设计教程第6章 函数

60、与编译预处理( (4)register4)register型:型:型:型: register register 变量类型变量类型变量类型变量类型 变量名变量名变量名变量名; ; 将使用频率高的变量定义为将使用频率高的变量定义为将使用频率高的变量定义为将使用频率高的变量定义为registerregisterregisterregister型型型型, , , ,可以提高运行可以提高运行可以提高运行可以提高运行速度速度速度速度. . . . 寄存器变量只限于寄存器变量只限于寄存器变量只限于寄存器变量只限于整型整型整型整型、字符型字符型字符型字符型、指针型指针型指针型指针型的局部变量。的局部变量。的局

61、部变量。的局部变量。寄存器变量是动态变量,而且数目有限寄存器变量是动态变量,而且数目有限寄存器变量是动态变量,而且数目有限寄存器变量是动态变量,而且数目有限, , 一般仅允许说明两一般仅允许说明两一般仅允许说明两一般仅允许说明两个寄存器变量。个寄存器变量。个寄存器变量。个寄存器变量。例如例如例如例如: : register int d;register int d; register char c; register char c;5353C语言程序设计教程2024/7/2354C语言程序设计教程第6章 函数与编译预处理6.5 编译预处理l l “ “编编编编译译译译预预预预处处处处理理理理”

62、 ”是是是是C C语语语语言言言言编编编编译译译译系系系系统统统统的的的的一一一一个个个个重重重重要要要要功功功功能能能能。当当当当对对对对一一一一个个个个源源源源文文文文件件件件进进进进行行行行编编编编译译译译时时时时,系系系系统统统统将将将将自自自自动动动动引引引引用用用用预预预预处处处处理理理理程程程程序序序序对对对对源源源源程程程程序中的预处理命令进行处理。序中的预处理命令进行处理。序中的预处理命令进行处理。序中的预处理命令进行处理。源源程程序序中中的的预预处处理理命命令令均均以以“#”开开头头(注注意意:结结尾尾不不加加分分号号),它它们们可可以以写写在在程程序序中中的的任任意意位位

63、置置,但但一一般般写写在在程程序中的开头,序中的开头,它的作用域它的作用域是从它所在的位置到源程序的末尾。是从它所在的位置到源程序的末尾。预预处处理理命命令令包包括括#include(文文件件包包含含)、define(宏宏定定义义)和和条件编译条件编译。5454C语言程序设计教程2024/7/2355C语言程序设计教程第6章 函数与编译预处理二二二二. .文件包含文件包含文件包含文件包含 # #includeinclude1. 1.文文文文件件件件包包包包含含含含是是是是指指指指一一一一个个个个源源源源文文文文件件件件可可可可以以以以将将将将另另另另一一一一个个个个源源源源文文文文件件件件的的

64、的的全部内容包含进来。全部内容包含进来。全部内容包含进来。全部内容包含进来。2. 2.它它它它的的的的功功功功能能能能是是是是把把把把指指指指定定定定包包包包含含含含的的的的文文文文件件件件插插插插入入入入该该该该命命命命令令令令行行行行位位位位置置置置取取取取代代代代该该该该命命命命令令令令行行行行,从从从从而而而而把把把把指指指指定定定定包包包包含含含含的的的的文文文文件件件件和和和和当当当当前前前前的的的的源程序文件连成一个源文件。源程序文件连成一个源文件。源程序文件连成一个源文件。源程序文件连成一个源文件。3. 3.#include#include命令有两种格式(两者区别见命令有两种格

65、式(两者区别见命令有两种格式(两者区别见命令有两种格式(两者区别见p96p96)(1)#(1)#includeinclude(2)#(2)#include“include“文件名文件名文件名文件名” ”5555C语言程序设计教程2024/7/2356C语言程序设计教程第6章 函数与编译预处理#includeadd.c”#include“stdio.h”main()inta=54,b=13;printf(a+b=%d,add(a,b);注意:注意:若不在上述两个目录若不在上述两个目录中,则应包含该文件的绝对中,则应包含该文件的绝对路径。路径。如:若如:若add.c存储在存储在d盘的盘的cheng

66、目录中,则应这样使用目录中,则应这样使用#include“d:chengadd.c”intadd(inta,intb)returna+b;将这个函数单独作为一个文件保将这个函数单独作为一个文件保存到:存到:c:tcincludeadd.c5656C语言程序设计教程2024/7/2357C语言程序设计教程第6章 函数与编译预处理一一一一. . . .宏定义宏定义宏定义宏定义l l宏定义宏定义宏定义宏定义 宏定义的功能是:宏定义的功能是:宏定义的功能是:宏定义的功能是:用一个标识符来表示一个字符串,标用一个标识符来表示一个字符串,标用一个标识符来表示一个字符串,标用一个标识符来表示一个字符串,标识

67、符称为识符称为识符称为识符称为宏名。宏名。宏名。宏名。 在编译预处理时,对程序中所有出现的宏名,都用宏定在编译预处理时,对程序中所有出现的宏名,都用宏定在编译预处理时,对程序中所有出现的宏名,都用宏定在编译预处理时,对程序中所有出现的宏名,都用宏定义中的字符串去替换(这个步骤叫作义中的字符串去替换(这个步骤叫作义中的字符串去替换(这个步骤叫作义中的字符串去替换(这个步骤叫作宏展开宏展开宏展开宏展开)。)。)。)。 在在在在C C C C语言中,宏分为语言中,宏分为语言中,宏分为语言中,宏分为有参数有参数有参数有参数和和和和无参数无参数无参数无参数两种。下面分别讨论两种。下面分别讨论两种。下面分

68、别讨论两种。下面分别讨论1.1.1.1.无参宏定义无参宏定义无参宏定义无参宏定义 一般形式为一般形式为一般形式为一般形式为: : : : # # # #define define define define 标识符标识符标识符标识符 字符串字符串字符串字符串 表示这是一条预处理命令,表示这是一条预处理命令,表示这是一条预处理命令,表示这是一条预处理命令,definedefinedefinedefine为宏定义命令,为宏定义命令,为宏定义命令,为宏定义命令,“标标标标识符识符识符识符”为所定义的宏名,字符串可以是常数、表达式,格式为所定义的宏名,字符串可以是常数、表达式,格式为所定义的宏名,字符

69、串可以是常数、表达式,格式为所定义的宏名,字符串可以是常数、表达式,格式串等。串等。串等。串等。 5757C语言程序设计教程2024/7/2358C语言程序设计教程第6章 函数与编译预处理如如如如: #: #: #: #define PI 3.14159 define PI 3.14159 define PI 3.14159 define PI 3.14159 /* /* /* /*定义后定义后定义后定义后, , , ,程序中所有的字符串程序中所有的字符串程序中所有的字符串程序中所有的字符串3.141593.141593.141593.14159可以用可以用可以用可以用PIPIPIPI来代替来

70、代替来代替来代替 */ */ */ */2.2.2.2.宏定义的作用宏定义的作用宏定义的作用宏定义的作用 对程序中反复使用的表达式进行宏定义,将给程序的书对程序中反复使用的表达式进行宏定义,将给程序的书对程序中反复使用的表达式进行宏定义,将给程序的书对程序中反复使用的表达式进行宏定义,将给程序的书写带来很大的方便。写带来很大的方便。写带来很大的方便。写带来很大的方便。 例如:例如:例如:例如:#define P printf(“*”);#define P printf(“*”);#define P printf(“*”);#define P printf(“*”); 5858C语言程序设计教程

71、2024/7/2359C语言程序设计教程第6章 函数与编译预处理3.3.3.3.说明说明说明说明 (1)(1)(1)(1)宏定义必须写在函数外,宏定义必须写在函数外,宏定义必须写在函数外,宏定义必须写在函数外,它的作用域它的作用域它的作用域它的作用域为从宏定义为从宏定义为从宏定义为从宏定义命令起到源程序结束,但可以用命令起到源程序结束,但可以用命令起到源程序结束,但可以用命令起到源程序结束,但可以用 # # # #undefundefundefundef命令终止宏定义命令终止宏定义命令终止宏定义命令终止宏定义的作用域。例如:的作用域。例如:的作用域。例如:的作用域。例如: #define PI

72、 3.14159#define PI 3.14159#define PI 3.14159#define PI 3.14159 # # # #undef PI undef PI undef PI undef PI /*/*/*/*从该位置开始以后的从该位置开始以后的从该位置开始以后的从该位置开始以后的PIPIPIPI就不代表就不代表就不代表就不代表3.141593.141593.141593.14159 * * * */ / / / (2) (2) (2) (2)宏定义是用宏名来表示一个字符串,在宏展开时宏定义是用宏名来表示一个字符串,在宏展开时宏定义是用宏名来表示一个字符串,在宏展开时宏定义是

73、用宏名来表示一个字符串,在宏展开时只是以该字符串取代宏名,只是一种简单的替换,不进只是以该字符串取代宏名,只是一种简单的替换,不进只是以该字符串取代宏名,只是一种简单的替换,不进只是以该字符串取代宏名,只是一种简单的替换,不进行语法检查。行语法检查。行语法检查。行语法检查。 (3) (3) (3) (3)宏定义不是语句,行末不加分号。宏定义不是语句,行末不加分号。宏定义不是语句,行末不加分号。宏定义不是语句,行末不加分号。5959C语言程序设计教程2024/7/2360C语言程序设计教程第6章 函数与编译预处理(4 4 4 4)用括号括起来的宏名,预处理程序不对其进行宏替)用括号括起来的宏名,

74、预处理程序不对其进行宏替)用括号括起来的宏名,预处理程序不对其进行宏替)用括号括起来的宏名,预处理程序不对其进行宏替换。换。换。换。(5 5 5 5)宏定义的嵌套使用)宏定义的嵌套使用)宏定义的嵌套使用)宏定义的嵌套使用 # # # # define R 3.0define R 3.0define R 3.0define R 3.0 # define PI 3.1415926 # define PI 3.1415926 # define PI 3.1415926 # define PI 3.1415926 # define L 2*PI*R /* # define L 2*PI*R /* #

75、define L 2*PI*R /* # define L 2*PI*R /*宏体是表达式宏体是表达式宏体是表达式宏体是表达式*/*/*/*/ # # # # define S PI*R*Rdefine S PI*R*Rdefine S PI*R*Rdefine S PI*R*R(6 6 6 6)宏名一般用大写字母表示。)宏名一般用大写字母表示。)宏名一般用大写字母表示。)宏名一般用大写字母表示。6060C语言程序设计教程2024/7/2361C语言程序设计教程第6章 函数与编译预处理2. 2. 带参数的宏定义带参数的宏定义带参数的宏定义带参数的宏定义 (1)(1)带参数的宏定义的一般形式为带

76、参数的宏定义的一般形式为带参数的宏定义的一般形式为带参数的宏定义的一般形式为 # # define define 宏名宏名宏名宏名( (参数表)参数表)参数表)参数表) 字符串字符串字符串字符串 如如如如 # #define S (a,b) a*b define S (a,b) a*b #define PR (x) printf( #define PR (x) printf(s=%fn”, x)s=%fn”, x)(2)(2)带实参的宏名被展开带实参的宏名被展开带实参的宏名被展开带实参的宏名被展开 宏宏宏宏名名名名被被被被所所所所定定定定义义义义的的的的宏宏宏宏体体体体替替替替换换换换, ,

77、宏宏宏宏体体体体中中中中的的的的形形形形参参参参按按按按从从从从左左左左到到到到右右右右的的的的顺序顺序顺序顺序被实参替换。被实参替换。被实参替换。被实参替换。 例如例如例如例如: : area = S (3,2);area = S (3,2); PR(area) ; PR(area) ; 展开为展开为展开为展开为: : area=3*2area=3*2; printf( printf(s=%fn”, area) ;s=%fn”, area) ;6161C语言程序设计教程2024/7/2362C语言程序设计教程第6章 函数与编译预处理宏定义与函数的区别(1)(1)引用宏只占编译时间,不占运行时

78、间。引用宏只占编译时间,不占运行时间。(2)(2)引用宏没有返回值。如引用宏没有返回值。如: #: #define define squ(nsqu(n) n*n) n*nvoid main (void)void main (void) printfprintf ( (%fn%fn,27.0/squ(3.0); ,27.0/squ(3.0); 程序输出结果为:程序输出结果为: 27.000000 27.000000注意,展开为27.0/3.0*3.0 不是27.0/(3.0*3.0) 6262C语言程序设计教程2024/7/2363C语言程序设计教程第6章 函数与编译预处理long f1(int

79、 n,int k) long f1(int n,int k) long power=n;long power=n; int i; int i; for(i=1;ik;i+) for(i=1;ik;i+) power *= n; power *= n; return power; return power; long f2(int n,int k) long sum=0; int i; for(i=1;i=n;i+) sum += f1(i, k); return sum; main()例例: 计算计算s=1k+2k+3k+N k printf(%dn,f2(5,4);6.6 函数设计举例函数设

80、计举例6363C语言程序设计教程2024/7/2364C语言程序设计教程第6章 函数与编译预处理1 1 以下程序求以下程序求10001000以内的所有的完全数之和,请将程序补充以内的所有的完全数之和,请将程序补充完整,并给出正确结果,填入相应窗口。完整,并给出正确结果,填入相应窗口。” ”完全数完全数” ”是指:是指:一个数如果刚好与它所有的真因子(不包括该数本身)之一个数如果刚好与它所有的真因子(不包括该数本身)之和相等,如:和相等,如:6=1+2+36=1+2+3,则,则6 6就是一个完全数。就是一个完全数。 # #include include #include #include #in

81、clude #include main()main() int sum,n,m,s,k; int sum,n,m,s,k; sum=0; sum=0;6464C语言程序设计教程2024/7/2365C语言程序设计教程第6章 函数与编译预处理for (n=3;n=1000;n+)for (n=3;n=1000;n+) s=0; s=0; k=n/2+1; k=n/2+1; for (m=1;mk;m+) for (m=1;mk;m+) if (n%m=0) if (n%m=0) _; _; if (s=n) if (s=n) _ _ printf(nThe sum=%d,sum); printf

82、(nThe sum=%d,sum); 6565C语言程序设计教程2024/7/2366C语言程序设计教程第6章 函数与编译预处理2 2。以下程序求。以下程序求10,100010,1000之间能被之间能被3 3或或5 5或或8 8整除的数之和。请将程序补整除的数之和。请将程序补充完整,给出正确程序运行结果,填入相应窗口。充完整,给出正确程序运行结果,填入相应窗口。 # #include include #include #include #include #include main()main() _long sum;long sum;sum=0;sum=0;for ( i=10;i=1000;

83、i+)for ( i=10;i=1000;i+) if ( _ ) if ( _ ) sum+=i; sum+=i; clrscr();clrscr();printf(%ldn,sum);printf(%ldn,sum); 6666C语言程序设计教程2024/7/2367C语言程序设计教程第6章 函数与编译预处理3 3下下面面程程序序求求3,7503,750之之间间同同构构数数之之和和, 请请将将程程序序补补充充完完整整, 并并给给出出正正确确结结果果,填填入入相相应应窗窗口口。同同构构数数是是:一一自自然然数数平平方方的的末末几几位位与与该该数数相相同时,称此数为自构数,例如:同时,称此数为

84、自构数,例如:5 55=255=25,则称,则称5 5为自同构数。为自同构数。# #include include #include #include #include #include main()main() long sum,n,m,s,k; long sum,n,m,s,k; sum=0; sum=0; for (n=3;n=750;n+) for (n=3;n=750;n+) if (n10) k=10; if (n10) k=10; else else if (n100) k=100; if (n100) k=100; else k=1000; else k=1000; s=n*n

85、; s=n*n; _; _; 6767C语言程序设计教程2024/7/2368C语言程序设计教程第6章 函数与编译预处理if (s%k=0)if (s%k=0) _ _ printf(n The sum = %d,sum); printf(n The sum = %d,sum); 6868C语言程序设计教程2024/7/2369C语言程序设计教程第6章 函数与编译预处理4 4下面程序是求下面程序是求5,755,75之间的所有奇数的立方和。请将程序补充完整,之间的所有奇数的立方和。请将程序补充完整,并给出正确结果,填入相应窗口。并给出正确结果,填入相应窗口。 # #include include

86、 #include #include #include #include main()main() long sum; long sum; _ _ sum=0; sum=0; for (i=5;i=75;i+) for (i=5;i=75;i+) if (fmod(i,2)!=0) if (fmod(i,2)!=0) _ _ clrscr(); clrscr(); printf(%ldn,sum); printf(%ldn,sum); 6969C语言程序设计教程2024/7/2370C语言程序设计教程第6章 函数与编译预处理5 5下面程序是求下面程序是求1,4501,450之间同时满足除之间同

87、时满足除3 3余余2 2和除和除5 5余余3 3条件的数的个数。条件的数的个数。请将程序补充完整,并给出正确结果,填入相应窗口。请将程序补充完整,并给出正确结果,填入相应窗口。 # #include include #include #include #include #include main()main() int count; int count; int i; int i; _ _ for (i=1;i=450;i+) for (i=1;i=450;i+) if (fmod(i,3)=2 & fmod(i,5)=3) if (fmod(i,3)=2 & fmod(i,5)=3) _ _

88、 clrscr(); clrscr(); printf(%dn,count); printf(%dn,count); 7070C语言程序设计教程2024/7/2371C语言程序设计教程第6章 函数与编译预处理6 6下面程序是求下面程序是求50,45050,450之间的能被之间的能被3 3和和5 5整除的数的平方和。请将程整除的数的平方和。请将程序补充完整,并给出正确结果,填入相应窗口。序补充完整,并给出正确结果,填入相应窗口。 # #include include #include #include #include #include main()main() long sum; long s

89、um; _; _; sum=0; sum=0; for (i=50;i=450;i+) for (i=50;i=450;i+) if (fmod(i,3)=0 & fmod(i,5)=0) if (fmod(i,3)=0 & fmod(i,5)=0) _ _ clrscr(); clrscr(); printf(%ldn,sum); printf(%ldn,sum); 7171C语言程序设计教程2024/7/2372C语言程序设计教程第6章 函数与编译预处理7 7下面的程序是求下面的程序是求22,500500之间的所有的素数的个数。之间的所有的素数的个数。 请请将程序补充完整,并给出正确结果,

90、填入相应窗口。将程序补充完整,并给出正确结果,填入相应窗口。 # #include include #include #include #include #include int prime(int n)int prime(int n) int yes, i; int yes, i; if(n=1) return 1; if(n=1) return 1; yes=1; yes=1; for(i=2; i=sqrt(n); i+) for(i=2; i=sqrt(n); i+) if(n%i=0) yes=0; break; if(n%i=0) yes=0; break; _ _ 7272C语言

91、程序设计教程2024/7/2373C语言程序设计教程第6章 函数与编译预处理main()main() int count=0, i; int count=0, i; clrscr(); clrscr(); for(i=2;i=500; i+) for(i=2;i=500; i+) if(prime(i) _ if(prime(i) _ printf(%dn, count); printf(%dn, count); 7373C语言程序设计教程2024/7/2374C语言程序设计教程第6章 函数与编译预处理8 8下面的程序是求表达式的值:下面的程序是求表达式的值:s=1+1/3+(1*2)/(3*

92、5)+(1*2*3)/(3*5*7)+.+(1*2*3*.*n)/(3*5*7*.(2*n+s=1+1/3+(1*2)/(3*5)+(1*2*3)/(3*5*7)+.+(1*2*3*.*n)/(3*5*7*.(2*n+1)1)请请将将程程序序补补充充完完整整,并并给给出出当当n=20n=20时时,程程序序的的运运行行结结果果( (按按四四舍舍五五入保留入保留1010位小数位小数) )。# #include include #include #include #include #include double fun(int n)double fun(int n) double s, t; int

93、 i; double s, t; int i; _ _ t=1.0; t=1.0; for(i=1;i=n; i+) for(i=1;i=n; i+) t=t*i/(2*i+1); t=t*i/(2*i+1); _ _ return s; return s; 7474C语言程序设计教程2024/7/2375C语言程序设计教程第6章 函数与编译预处理main()main()printf(n %12.10lf, fun(20);printf(n %12.10lf, fun(20); 7575C语言程序设计教程2024/7/2376C语言程序设计教程第6章 函数与编译预处理9 9下面的程序是求如下表

94、达式的值。下面的程序是求如下表达式的值。S=sqrt(ln(1)+ln(2)+ln(3)+ln(n)S=sqrt(ln(1)+ln(2)+ln(3)+ln(n)将将程程序序补补充充完完整整, 当当n=60n=60时,给出程序运行结果(按四舍五入保留时,给出程序运行结果(按四舍五入保留6 6位小数)。位小数)。# #include include #include #include #include #include double fun(int n)double fun(int n) _ _ int i; int i; for(i=1;i=n;i+) for(i=1;i=n;i+) s+=lo

95、g(1.0*i); s+=log(1.0*i); s=sqrt(s); s=sqrt(s); return s; return s; 7676C语言程序设计教程2024/7/2377C语言程序设计教程第6章 函数与编译预处理main()main() clrscr(); clrscr(); printf(_); printf(_); 7777C语言程序设计教程2024/7/2378C语言程序设计教程第6章 函数与编译预处理改错题:改错题:1 1下下面面的的程程序序是是求求500500以以内内的的所所有有的的素素数数之之和和。请请修修改改程程序序中中的的错错误误,使它能得出正确的结果,并给出正确结

96、果。使它能得出正确的结果,并给出正确结果。# #include include #include #include #include #include int prime(int n)int prime(int n) int yes, i; int yes, i; if(n=1) return 1; if(n=1) return 1; yes=1; yes=1; for(i=2; i=sqrt(n); i+) for(i=2; i=sqrt(n); i+) if(n%i=0) yes=0; break; if(n%i=0) yes=0; break; return 1; return 1; 7

97、878C语言程序设计教程2024/7/2379C语言程序设计教程第6章 函数与编译预处理main()main() int sum=0, i; int sum=0, i; clrscr(); clrscr(); for(i=2;i=500; i+) for(i=2;i=500; i+) if(prime(i) sum+=i; if(prime(i) sum+=i; printf(%dn, sum); printf(%dn, sum); 7979C语言程序设计教程2024/7/2380C语言程序设计教程第6章 函数与编译预处理2 2下下面面的的程程序序中中,函函数数funfun的的功功能能是是:根

98、根据据形形参参mm,计计算算下下面公式的值。面公式的值。 T=1+1/(2*3)+1/(3*4)+1/(m*(m+1) T=1+1/(2*3)+1/(3*4)+1/(m*(m+1) 请请改改正正程程序序中中的的错错误误,并并运运行行改改正正后后的的程程序序。当当从从键键盘盘输输入入7070时时,给给出出程程序序运运行行的的正正确确结结果果(按按四四舍舍五五入入保保留留6 6位位小小数)。数)。# #include include #include #include double fun(int m)double fun(int m) double t=1.0; double t=1.0;int

99、 i=2;int i=2;for(i=2; i=m; i+)for(i=2; i=m; i+) t+=1.0/i*(i+1); t+=1.0/i*(i+1);return ;return ; 8080C语言程序设计教程2024/7/2381C语言程序设计教程第6章 函数与编译预处理main()main() int m; int m;clrscr();clrscr();printf(n printf(n 请输入一个整数请输入一个整数: );: );scanf(%d,&m);scanf(%d,&m);printf(n printf(n 结果是结果是: %: %lf n, fun(m);lf n,

100、fun(m); 8181C语言程序设计教程2024/7/2382C语言程序设计教程第6章 函数与编译预处理3 3下下面面的的程程序序中中,函函数数funfun的的功功能能是是:根根据据形形参参mm,计计算算下下面面公公式式的的值值。T=1/1!+1/2!+1/3!+1/m! T=1/1!+1/2!+1/3!+1/m! 请请改改正正程程序序中中的的错错误误,并并运运行行改改正正后后的的程程序序。当当从从键键盘盘输输入入1010时时,给给出出程程序序运运行行的的正正确确结结果果(按按四四舍舍五五入入保保留留1010位小数)。位小数)。# #include include #include #inc

101、lude double fun(int m)double fun(int m) double fac, t=0.0; double fac, t=0.0;int i=1, j;int i=1, j;for(i=1;i=m;i+)for(i=1;i=m;i+) fac=1.0; fac=1.0; for(j=1; j=m; j+) fac=fac*i ; for(j=1; j=m; j+) fac=fac*i ; t+=1.0/fac; t+=1.0/fac; return t;return t; 8282C语言程序设计教程2024/7/2383C语言程序设计教程第6章 函数与编译预处理main

102、()main() int m; int m;clrscr();clrscr();printf(n printf(n 请输入整数请输入整数: );: );scanf(%d, &m);scanf(%d, &m);printf(n printf(n 结果是结果是: %12.10: %12.10lf n,fun(m);lf n,fun(m); 8383C语言程序设计教程2024/7/2384C语言程序设计教程第6章 函数与编译预处理4 4下下面面的的程程序序中中,函函数数funfun的的功功能能是是:根根据据形形参参mm,计计算算下下面公式的值。面公式的值。T=1+1/(1*2)+1/(2*3)+1/

103、(m-1)*mT=1+1/(1*2)+1/(2*3)+1/(m-1)*m请改正程序中的错误,并运行改正后的程序。当从键盘输入请改正程序中的错误,并运行改正后的程序。当从键盘输入7070时,给出程序运行的正确结果(按四舍五入保留时,给出程序运行的正确结果(按四舍五入保留6 6位小位小数)。数)。 # #include include #include #include double fun(int m)double fun(int m) double t=1.0; double t=1.0;int i=2;int i=2;for(i=2;i=m; i+)for(i=2;i=m; i+) t+=1

104、.0/(i*(i+1); t+=1.0/(i*(i+1);return ;return ; 8484C语言程序设计教程2024/7/2385C语言程序设计教程第6章 函数与编译预处理main()main() int m; int m;clrscr();clrscr();printf(n printf(n 输入整数输入整数: );: );scanf(%d, &m);scanf(%d, &m);printf(n printf(n 结果是结果是: %: %lf n,fun(m);lf n,fun(m); 8585C语言程序设计教程2024/7/2386C语言程序设计教程第6章 函数与编译预处理5 5

105、下面程序中,函数下面程序中,函数funfun的功能是:计算并输出的功能是:计算并输出k k以内的最大的以内的最大的1010个能被个能被1313或或1717整除的自然数之和。请改正程序中的错误,并运行正确的程序。整除的自然数之和。请改正程序中的错误,并运行正确的程序。当从键盘输入当从键盘输入500500时,给出程序运行的正确结果。时,给出程序运行的正确结果。 # #include include #include #include int fun(int k)int fun(int k) int m=0, mc=0, j; int m=0, mc=0, j;while(k=2) | mc=2)

106、| mc10) if (k%13=0) & (k%17=0) if (k%13=0) & (k%17=0) m=m+k; mc+; m=m+k; mc+; k-; k-; return m; return m; 8686C语言程序设计教程2024/7/2387C语言程序设计教程第6章 函数与编译预处理main()main() int k; int k; clrscr(); clrscr(); printf(n printf(n 请输入整数请输入整数:);:); scanf(%d, &k);scanf(%d, &k); printf(n printf(n 结果是结果是: %: %dn,fun(k

107、);dn,fun(k); 8787C语言程序设计教程2024/7/2388C语言程序设计教程第6章 函数与编译预处理6 6下列程序的功能是:求出以下分数序列的前下列程序的功能是:求出以下分数序列的前3030项之和,项之和,2/1,3/2,5/3,8/5,13/8,21/13,2/1,3/2,5/3,8/5,13/8,21/13,请请改改正正程程序序中中的的错错误误,并并运运行行修修改改后后程程序,给出程序结果(按四舍五入保留序,给出程序结果(按四舍五入保留6 6位小数)。位小数)。# #include include #include #include main()main() long a,

108、b,c,k; long a,b,c,k; double s; double s; clrscr(); clrscr(); s=0.0; a=2; b=1; s=0.0; a=2; b=1; for(k=1;k=30;k+) for(k=1;k=30;k+) s=s+a/b; s=s+a/b; c=a; a=a+b; b=c; c=a; a=a+b; b=c; printf(n printf(n 结果结果: %: %lfn, s);lfn, s); 8888C语言程序设计教程2024/7/2389C语言程序设计教程第6章 函数与编译预处理7 7下面的程序是求下面的程序是求400400以内的所有的

109、素数之和。请修改程序以内的所有的素数之和。请修改程序中的错误,使它能得出正确的结果,给出正确结果。中的错误,使它能得出正确的结果,给出正确结果。 # #include include #include #include #include #include int prime(int n)int prime(int n) int yes, i; int yes, i; if(n=1) return 0; if(n=1) return 0; yes=0; yes=0; for(i=2; i=sqrt(n); i+) for(i=2; i=sqrt(n); i+) if(n%i=0) yes=1;

110、if(n%i=0) yes=1; break;break; return yes; return yes; 8989C语言程序设计教程2024/7/2390C语言程序设计教程第6章 函数与编译预处理main()main() int sum=0, i; int sum=0, i; clrscr(); clrscr(); for(i=2;i=400; i+) for(i=2;i=1x=1;f(x)=0 f(x)=0 if if x=0 x=0 or or x=2x=2;f(x)=(x-1)/(x-2) f(x)=(x-1)/(x-2) if if x0x0。请请改改正正程程序序中中的的错错误误,并

111、并给给出出正正确确程程序序的的运运行行结结果果( (按按四四舍舍五五入入保保留留6 6位小数位小数) )。# #include include #include #include #include #include double f(double x)double f(double x) if(x=0 & x=2) if(x=0 & x=2) return 0.0 ; return 0.0 ; else if(x0.0) else if(x0.0) return (x-1)/(x-2); return (x-1)/(x-2); else else return (x+1)/(x-2); ret

112、urn (x+1)/(x-2); 9191C语言程序设计教程2024/7/2392C语言程序设计教程第6章 函数与编译预处理double fsum(int n)double fsum(int n) int i; double s=0.0, y; int i; double s=0.0, y; for(i=-n; i=n;i+) for(i=-n; i=n;i+) y=f(1.0*i); s+=y; y=f(1.0*i); s+=y; return y; return y; main()main() clrscr(); clrscr(); printf(%lfn, fsum(30); print

113、f(%lfn, fsum(30); 9292C语言程序设计教程2024/7/2393C语言程序设计教程第6章 函数与编译预处理9.9.下下 面面 的的 程程 序序 是是 计计 算算 如如 下下 公公 式式 的的 A15A15值值 。 A1=1, A1=1, A2=1/(1+A1), A2=1/(1+A1), A3=1/(1+A2), A3=1/(1+A2), A4=1/(1+A3), A4=1/(1+A3), .请请改改正正程程序序中中的的错错误误,并并给给出出程程序序运运行的正确结果(按四舍五入保留行的正确结果(按四舍五入保留1010位小数)位小数) # #include include #

114、include #include double fun(int n)double fun(int n) int A=1.0;int i; int A=1.0;int i; for(i=2; i=n; i+) for(i=2; i=n; i+) A+=1.0/(1+A); A+=1.0/(1+A); return A; return A; main()main() clrscr(); clrscr(); printf(%12.10lfn, fun(15); printf(%12.10lfn, fun(15); 9393C语言程序设计教程2024/7/2394C语言程序设计教程第6章 函数与编译预处理再见!再见!同学们:同学们:9494

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号