C语言程序设计函数与宏定义ppt课件.pptx

上传人:牧羊曲112 文档编号:2052469 上传时间:2023-01-04 格式:PPTX 页数:50 大小:455.49KB
返回 下载 相关 举报
C语言程序设计函数与宏定义ppt课件.pptx_第1页
第1页 / 共50页
C语言程序设计函数与宏定义ppt课件.pptx_第2页
第2页 / 共50页
C语言程序设计函数与宏定义ppt课件.pptx_第3页
第3页 / 共50页
C语言程序设计函数与宏定义ppt课件.pptx_第4页
第4页 / 共50页
C语言程序设计函数与宏定义ppt课件.pptx_第5页
第5页 / 共50页
点击查看更多>>
资源描述

《C语言程序设计函数与宏定义ppt课件.pptx》由会员分享,可在线阅读,更多相关《C语言程序设计函数与宏定义ppt课件.pptx(50页珍藏版)》请在三一办公上搜索。

1、第6章 函数与宏定义,第6章 函数与宏定义,本章主要内容1.函数的概念 函数的声明和调用 函数的传值方式2.变量的作用域和存储类型3.内部函数与外部函数4.递归函数的设计和调用5.预处理6.综合范例,6.1 函数的概念,模块化程序设计的核心:函数设计。重要概念:把解决问题的方案设计成一个个独立的模块;程序通过调用模块功能来解决问题。这些模块通过函数来实现,又称为函数模块。每一个函数具有独立的功能,程序通过各模块之间的协调工作完成复杂的程序功能。,6.1 函数的概念,C语言的函数分为两类:系统定义的标准函数,又称为库函数。函数声明一般是放在系统的include目录下以.h为后缀的头文件中,如在程

2、序中要用到某个库函数,必须在调用该函数之前用#include命令将库函数信息包含到本程序中。常用的库函数请查阅附录C。自定义函数。按要求设计的。C语言程序设计的核心之一:自定义函数。,6.1 函数的概念,6.1.1 函数的定义自定义函数的形式:存储类型符 返回值类型符 函数名(形参说明表)几点说明:1.存储类型符指的是函数的作用范围,只有两种形式:static和extern。static说明的函数称为内部函数,只能作用于其所在的源文件,extern说明的函数称为外部函数,可被其他源文件中的函数调用。缺省情况为extern。,6.1 函数的概念,存储类型符 返回值类型符 函数名(形参说明表),2

3、.返回值类型符指的是函数体语句执行完成后,函数返回值的类型。如int,float,char等。若函数无返回值,则用空类型void来定义函数的返回值。默认情况为int型(有些编译器不支持默认情况)。3.函数名由任何合法的标识符构成。建议将函数名的命名与函数内容有一定关系。,说明,6.1 函数的概念,4.形参说明表是一系列用逗号分开的形参变量说明。如:int x,int y,int z 表示形参变量有3个:x,y,z。类型都是int型的。注意:不能直接写成:int x,y,z。5.在古典式函数定义中,形参表只要形参名,不要类型名。如:x,y,z 表示形参变量有3个。形参的类型通过形参说明语句说明。

4、如:int x,y,z。形参说明表或形参表都可以缺省,缺省时表示函数无参数。,存储类型符 返回值类型符 函数名(形参说明表),说明,6.1 函数的概念,6.函数语句体是放在一对花括号 中,由局部数据类型描述和功能实现两部分组成。函数返回语句 通常用返回语句来结束函数的调用。两种形式的返回语句:函数无返回值的情况 return;函数有返回值的情况 return(表达式的值);,存储类型符 返回值类型符 函数名(形参说明表),说明,6.1 函数的概念,例如,编写自定义函数abs_sum(),求两个任意整数的绝对值的和。int abs_sum(int m,int n)if(m0)m=m;if(n0)

5、n=n;return(m+n);或直接调用系统函数来实现:int abs_sum(int m,int n)return(abs(m)+abs(n);注意:函数abs()的声明在头文件math.h。,6.1 函数的概念,6.1.2 函数的声明和调用通常情况下,自定义的函数在使用之前要先进行函数声明,才能在程序中进行函数调用。1函数声明函数声明语句的形式:存储类型符 返回值类型符 函数名(形参说明表);如:int abs_sun(int m,int n);2函数调用函数定义好后,若不通过函数调用,不会发挥任何作用。函数调用是通过函数调用语句来实现的。函数无返回值情况:函数名(实参表);,6.1 函

6、数的概念,函数有返回值的情况:变量名函数名(实参表);注意:变量名的类型必须与函数的返回值类型相同。函数调用时,会去执行函数中的语句内容,函数执行完毕后,回到函数的调用处,继续执行程序中函数调用后面的语句。例如:int x=5,y=10;int z;z=abs_sum(x,y);/*函数调用*/,6.1 函数的概念,6.1.3 函数的传值方式函数传值的4个要点:对于带有参数的函数,调用函数时,将实参表中每一个实参的值对应地传递给每一个形参变量;形参变量接收到实参传来的值后,会在内存临时开辟新的空间,保存形参变量的值;函数执行完毕时,释放临时开辟的内存空间;形参的值在函数中不论是否发生变化,实参

7、变量的值均不会发生变化。自定义函数在程序中的使用方式有两种形式:先进行函数声明,再进行函数调用,函数定义放在main函数的后面。先定义函数,再调用函数(不需要在调用前函数声明)。,6.1 函数的概念,例1:编写程序,通过调用函数int abs_sum(int a,int b),求任意两个整数的绝对值的和。第1种形式:先进行函数声明;再进行函数调用;最后给出函数定义。,/*example6_1.c*/#include int abs_sum(int m,int n);/*函数声明*/main()int x,y,z;scanf(%d%d,6.1 函数的概念,第2种形式:先定义函数;再调用函数。(不

8、需要在调用前函数声明)思考:1.怎样求任意3个整数的绝对值之和?参考答案见程序:example6_2.c 2.怎样求任意2个数的乘积?参考答案见程序:example6_3.c,/*example6_1.c*/#include int abs_sum(int m,int n)/*函数定义*/if(m0)m=-m;if(n0)n=-n;return m+n;main()int x,y,z;scanf(%d%d,6.1 函数的概念,重要概念 函数传值调用的性质:实参的值在函数调用前和函数调用后不会发生变化。如有程序:分析程序的运行结果。,/*exanple6_交换?*/#include void e

9、xchange(int a,int b)int temp;printf(3-a=%d,a=%dn,a,a);temp=a;a=b;b=temp;printf(4-a=%d,a=%dn,a,a);main()int x=10,y=20;printf(1-x=%d,y=%dn,x,y);exchange(x,y);/*函数调用*/printf(2-x=%d,y=%dn,x,y);,6.2 变量的作用域和存储类型,根据变量的作用域不同,可分为局部变量和全局变量两种。1变量的作用域变量的作用域:变量起作用的范围。局部变量:在函数内部或某个控制块的内部定义的变量。局部变量的作用域:函数内部。作用:增强了

10、函数模块的独立性。全局变量:在函数外面定义的变量称为全局变量。全局变量的作用域:从该变量定义的位置开始,直到源文件结束。作用:在同一文件中,所有函数都可以引用全局变量。增强了各函数间数据的联系。,局部变量和全局变量的作用域如图所示:,6.2 变量的作用域和存储类型,例2:阅读程序【例6-4】的程序,了解变量作用域。请注意区分局部变量和全局变量的作用域。程序:example6_4.c,6.2 变量的作用域和存储类型,2变量的存储类型变量的存储类型指的是变量的存储属性,它说明变量占用存储空间的区域。在内存中,供用户使用的存储区由程序区、静态存储区和动态存储区3部分组成。变量的存储类型:auto、r

11、egister、static和extern4种。auto型变量存储在内存的动态存储区;register型变量保存在寄存器中;static型和extern变量存储在静态存储器。,6.2 变量的作用域和存储类型,局部变量的存储类型默认值为auto型。全局变量的存储类型默认值为extern型。注意:一般情况下,常用auto型register型定义局部变量。static型既可作为局部变量,又可作为全局变量。作为局部变量时,局部变量的值将被保留,若定义时没有赋初值,则系统会自动为其赋0值;作为全局变量时,其有效范围为它所在的源文件,其他源文件不能使用。,6.2 变量的作用域和存储类型,例3:设计一个函数

12、:long fac(int n),用来计算正整数的阶乘,编写程序进行测试。分析:由于计算机对变量的字节长度分配有限,整型变量的最大值是一定的,因此,目前计算整数的阶乘只能针对较小的整数。假定要计算15的阶乘。算法的核心思想:对于任意正整数n,如果知道(n1)!,则n!=n(n1)!。可在函数中定义一个static型变量,用来保存每一次阶乘的计算结果。,6.2 变量的作用域和存储类型,程序如下:/*example6_5.c*/#include long fac(int n)/*计算n!的函数*/static int f=1;f=f*n;return f;main()int i;for(i=1;i

13、=5;i+)printf(%d!=%ldn,i,fac(i);,6.2 变量的作用域和存储类型,思考:1这个程序计算最大正整数的阶乘是多少?2如果不用循环,能否直接求出某个整数的阶乘?,6.3 内部函数与外部函数,自定义的函数有两种:内部函数和外部函数。1内部函数 若函数的存储类型为static型,则称其为内部函数(内部函数又称为静态函数),它表示在由多个源文件组成的同一个程序中,该函数只能在其所在的文件中使用,在其他文件中不可使用。内部函数的声明形式:static();例如:static int Statistic();2外部函数 若函数的存储类型定义为extern型,则称其为外部函数,它表

14、示该函数能被其他源文件调用。函数的默认存储类型为extern型。,6.3 内部函数与外部函数,例4:外部函数的应用示例。下面的程序由3个文件组成:file1.c、file2.c、example6_6.c。在file1.c、file2.c中分别定义了两个外部函数;在example6_6.c中可以分别调用这两个函数。,1file1.c/*file1.c 外部函数定义*/extern int add(int m,int n)return(m+n);,2file2.c/*file2.c 外部函数定义*/extern int mod(int a,int b)return(a%b);,6.3 内部函数与外

15、部函数,3example6_6.c/*example6_6.c 调用外部函数*/#include extern int mod(int a,int b);/*外部函数声明*/extern int add(int m,int n);/*外部函数声明*/main()int x,y,result1,result2,result;printf(Please enter x and y:n);scanf(%d%d,6.3 内部函数与外部函数,关于程序的几点说明(1)在程序file1.c、file2.c中的函数定义可以不需要extern加以说明,默认为外部函数。(2)在example6_6.c中对外部函数

16、的声明也可以不用extern加以说明,默认为外部函数。(3)由多个源文件组成一个程序时,main()函数只能出现在一个源文件中。(4)由多个源文件组成一个程序时,有3种连接方式:将各源文件分别编译成目标文件,得到多个目标文件(.obj后缀),然后用连接命令把多个.obj文件连接起来。Turbo c的连接接命令为tlink 例如:tlink example6_6.obj+file1.obj+file2.obj 结果:生成一个example6_6.exe文件。,6.3 内部函数与外部函数,建立项目文件(.prj后缀或.dsw后缀),具体操作可参阅各种C语言集成开发环境说明。使用文件包含命令。请参阅

17、本章6.6节。(5)如果将file1.c或file2.c中的extern改成static,则主程序在编译时无法通过。(6)在程序file1.c或file2.c中,也可以互相调用其外部函数。,6.4 递归函数的设计和调用,函数的嵌套调用:函数中的语句可以是对另一个函数的调用。函数嵌套调用的过程如图所示:,嵌套调用属于一种线性调用关系,函数执行完成后,返回到原调用点,继续执行函数调用下面的语句。,6.4 递归函数的设计和调用,函数的递归调用 两种递归形式:直接递归调用和间接递归调用。直接递归调用 直接递归:函数直接调用自身函数。间接递归调用 间接递归:函数互相调用对方函数。递归形式:,6.4 递归

18、函数的设计和调用,可能出现的陷阱 递归调用陷入无限递归状态。递归的限制 并不是所有的问题都可以设计成递归函数。为了避免错误的发生,对于递归函数的设计,有严格的数学模型。递归函数的条件 递归函数模型在数学上必须具备以下两个条件。问题的后一部分与原始问题类似。问题的后一部分是原始问题的简化。难点 递归函数设计的难点是建立问题的数学模型,有了正确的递归数学模型,很容易写出递归函数。,6.4 递归函数的设计和调用,例5:编写程序,要求从键盘输入一个正整数n,计算n!。分析:n!的数学表达式为:显然,它满足数学上对递归函数的两个条件:(n1)!与n!是类似的;(n1)!是n!的简化。可用递归函数long

19、 fac(int n)实现求n!。,6.4 递归函数的设计和调用,函数long fac(int n)的算法流程图及函数实现如图所示:,参考答案见程序:example6_7.c,6.4 递归函数的设计和调用,例6:Fibonacci数列的组成规律为:0,1,1,2,3,5,8,13,21,。编写程序,求Fibonacci数列第i项的值(0i40)。分析:数列的组成规律为:第1项为0,第2项为1,从第3项开始,数列每1项的值为前两项的和。Fibonacci数列用数字模型表达为:fibonacci(1)=0(i=1)fibonacci(2)=1(i=2)fibonacci(i)=fibonacci(

20、i1)+fibonacci(i2)(i=3,4,5,)从第3项开始,该Fibonacci数列的数学表达式满足递归函数的两个必要条件,设计递归函数long fibonacci(int n)来求得数列中第n项的值。,6.4 递归函数的设计和调用,函数long fibonacci(int n)的算法流程图:,思考程序存在的缺陷:提示:只能求出指定项的值;对输入的值没有限制;,函数程序:long fibonacci(int n)if(n=1|n=2)return n-1;else return fibonacci(n-1)+fibonacci(n-2);,参考答案见程序:example6_8.c,6.

21、5 预 处 理,预处理的作用:向编译系统发布信息或命令,告诉编译系统在对源程序进行编译之前应做些什么事。所有编译预处理都是以“#”号开头,单占源程序中的一行,放在源程序的首部。编译预处理不是C语句,行未不必加分号。C语言提供的预处理指令主要有3种:宏定义、文件包含和条件编译。,6.5 预 处 理,6.5.1 宏定义两种宏定义:不带参数的宏和带参数的宏。宏定义的作用:简化程序的书写。1不带参数的宏定义形式:#define 宏名 字符串说明:define是关键字,表示宏定义。宏名用标识符表示,为区别于变量,宏名一般采用大写字母。如:#define PI 3.14159宏的作用:将程序中的宏名用字符

22、串替换。宏名的有效范围是从定义命令之后,直到源程序文件结束,或遇到宏定义终止命令#undef为止。例7:阅读程序example6_9.c,了解不带参数的宏的作用。,6.5 预 处 理,2带参数的宏定义形式:#define 宏名(参数表)字符串说明:字符串应包含有参数表中的参数。宏替换时,将字符串中的参数用实参表中的实参替换。例8:阅读程序example6_10.c,了解带参数的宏定义的作用。分析程序运行结果。特别提示:有参数的宏定义与函数是完全不同的两个概念。,6.5 预 处 理,6.5.2 文件包含将另一个文件的全部内容包含到程序中,编译时,用包含文件的内容取代该预处理命令。文件包含命令的一

23、般形式:#include 或:#include 包含文件名注意:include是命令关键字,一个include命令只能包含一个文件。表示被包含文件在标准目录(include)中。表示被包含文件在指定的目录中,若只有文件名不带路径,则在当前目录中,若找不到,再到标准目录中寻找。包含文件名可以是.c源文件或.h头文件,如:#include#include myhead.h#include D:myexammyfile.c”,6.5 预 处 理,文件包含的作用:将多个源文件拼接在一起。如:有文件file2.c,其内容都是自定义的函数。另有文件file1.c,该文件有main函数。如果在file1.c

24、程序中要调用file2.c中的函数,可采用文件包含的形式:#include file2.c在对file1.c进行编译时,系统会用file2.c的内容替换掉文件包含命令#include file2.c,然后再对其进行编译。要注意区分外部函数与文件包含的区别。它们都是可以在某个程序中用到另一个文件中的函数,但使用的方法有所不同。,6.5 预 处 理,6.5.3 条件编译及其他条件编译:对程序源代码有选择地进行编译。ANSI标准定义的C语言预处理命令:#error#if#else#elif#endif#ifdef#ifndef#line#pragma,条件编译命令,略,6.6 综 合 范 例,例7:

25、编写程序,用扩展ASCII中的制表符在屏幕上画一个如图所示的n行m列大小的方格棋盘(x、y表示屏幕坐标)。提示:若程序要用扩展ASCII中的制表符,要求程序在文本模式下运行,可用适合于DOS模式的集成开发环境。分析:扩展ASCII共有128个,编号为128255方格的符号可由9个制表符组成,分别为:左上角、右上角、左下角、右下角、左 边、右 边、上 边、下 边、十字叉,6.6 综 合 范 例,程序设计思想:从扩展ASCII码表中查得制表符的编码,将要输出的制表符用宏名表示。对棋盘的每一行输出合适的制表符号。设计函数:void draw_cross(int y,int x)输出相应的制表符,完成

26、棋盘的绘制。程序:example6_13.c,思考,是否还有其他算法?,6.6 综 合 范 例,例8:编写程序,从键盘输入一个正整数number,通过函数int reverseDigits(int number)将number的数字反向返回。为简单起见,number的取值范围为19999。例如:整数:4629,函数的返回值:9264;整数:3027,函数的返回值:7203。程序以输入1作为结束。分析:问题的核心是将数字number反向后,返回一个新的数reverse。算法关键:分离number的每1位数字;使number的最低位成为reverse的最高位。,6.6 综 合 范 例,函数int

27、reverseDigits(int number)的算法流程如图所示:参考答案见程序:example6_14.c,思考,是否还有其他算法?,6.6 综 合 范 例,例9:编写程序,求方程f(x)=ax2+bx+c 在某区间的定积分:。为了程序的通用性,要求从键盘输入方程f(x)的系数a、b和c的值以及积分区间的上下限upper、lower的值。分析:积分的结果为图(a)所示阴影部分的平面面积。计算机求解时,是将积分区间分解成n个微小区间,如图(b)所示。求出这n个小区间的面积之和,即为整个区域面积。,6.6 综 合 范 例,在图(b)中,第i个区间的面积为:(0in1)式中的xi=lower+

28、ih。设计积分的求和函数:double integrate(double lower,double upper)积分算法思想:确定区间的个数:n(区间的个数决定计算结果的精度)。获得区间的宽度大小:h=(upperlower)/n计算某个小区间的面积:s=h(f(lower+ih)+f(lower+(i+1)h)/2对s求和:,结果即为该积分的近似值。被积分函数f(x)=ax2+bx+c另外用模块单独生成。参考答案见程序:example6_15.c,6.6 综 合 范 例,1.怎样控制积分计算的精度?2.是否还有其他算法?,思考,6.6 综 合 范 例,例10:由一个古老的传说演变成的汉诺塔游

29、戏:有三根柱子A、B、C,在A柱上按大小依次放着n个中间有孔的盘子,如图(a)所示。现在要将这n个盘子从A柱移到C柱上去,如图(b)所示。移动过程中,可以借助于中间的B柱,规定每次只能移动一个盘子,且在盘子的移动过程中,大盘子只能在小盘子的下面,怎样才能够以最少的移动步骤来完成这个任务?请编写程序,给出完成汉诺塔游戏的移动步骤。,6.6 综 合 范 例,分析:采用递归算法,分3步进行。将A柱上的n1个盘子移到B柱上;(与原始问题类似)直接将A柱上最下面的那个盘子移到C柱上;将B柱上的n1个盘子借助于A柱移到C柱。(原始问题简化)算法:,参考答案见程序:example6_16.c思考:1函数HanoTower(n,A,B,C)的递归调用过程。2用非递归算法求解。,6.7 本 章 小 结,本章重要概念1.函数定义、函数申明、函数调用的方法。2.函数传值调用的作用。3.静态存储的意义和作用。4.递归函数的设计条件。5.宏处理。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号