欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    c语言第六章函数与宏定义.ppt

    • 资源ID:6504291       资源大小:793KB        全文页数:49页
    • 资源格式: PPT        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    c语言第六章函数与宏定义.ppt

    2023/11/7,1,第六章 函数与宏定义,6.1 函数概念,6.2 变量作用域和存储类型,6.3 内部函数与外部函数,6.4 递归函数设计和调用,6.6 综合范例,2023/11/7,2,6.1 函数概念,C语言允许把问题设计成一个一个的模块,程序通过调用模块功能来解决问题。这些模块通常都是通过函数来实现的,又可称其为函数模块。,C语言中,函数可分为两类:,一类是由系统定义的标准函数,又称为库函数,其函数声明一般是放在系统的include目录下以.h为后缀的头文件中,如在程序中要用到某个库函数,必须在调用该函数之前用#include命令将库函数信息包含到本程序中。,另一类函数是自定义函数,两种形式:,第一种:函数声明、函数调用、函数定义。第二种:函数定义、函数调用。,2023/11/7,3,6.1.1 函数定义,函数定义的一般形式可以有两种。,形式一:,存储类型符 返回值类型符 函数名(形参说明表)函数语句体,形式二:,存储类型符 返回值类型型符 函数名(形参表)形参说明;函数语句体,2023/11/7,4,说明:,1存储类型符指的是函数的作用范围,它只有两种形式:static和extern。static说明函数只能作用于其所在的源文件,用static说明的函数又称为内部函数。extern说明函数可被其它源文件中的函数调用,用extern说明的函数,又称为外部函数。缺省情况为extern。,2返回值类型符指的是函数体语句执行完成后,函数返回的值的类型,如int,float,char等等,若函数无返回值,则用空类型void来定义函数的返回值。缺省情况为int型。,2023/11/7,5,3函数名由任何合法的标识符构成。建议将函数名的命名与函数内容有一定关系。,4在第一种函数定义的形式中,形参说明表是一系列用逗号分开的每个形参变量说明。如:int x,int y,int z这表示形参变量有三个:x,y,z。它们的类型都是int型。在第二种函数定义的形式中,形参表是一系列用逗号分开的形参变量。如:x,y,z,5函数语句体是放在一对花括号 中,由局部数据类型描述和功能实现两部分组成。,2023/11/7,6,6函数返回语句的形式有以下两种:函数无返回值的情况:return;函数有返回值的情况:return(表达式的值);在第种情况下要注意“表达式的值”的类型必须与函数返回值的类型相一致。,例如:求两个任意整数的绝对值的和,用函数abs_sum()实现。,/*直接调用库函数来计算m和n的绝对值*/int abs_sum(int m,int n)return(abs(m)+abs(n);/*函数abs()是在头文件math.h中声明的*/,2023/11/7,7,函数定义如下:int abs_sum(int m,int n)if(m0)m=-m;if(n0)n=-n;return(m+n);,6.1.2 函数声明和调用,一函数的声明函数声明的一般形式:,存储类型符 返回值类型符 函数名(形参说明表);如:int abs-sun(int m,int n);,2023/11/7,8,二函数调用函数调用是通过函数调用语句来实现的,分两种形式:,无返回值的情况:函数名(实参表);有返回值的情况:变量名函数名(实参表);该变量名的类型必须与函数的返回值类型相同。,函数调用时都会去执行函数语句中的内容,函数执行完毕后,回到函数的调用处,继续执行下面的语句。,2023/11/7,9,6.1.3 函数的传值方式,函数的传值方式:采用实参表将每一个实参的值相应地传递给每一个形参变量,形参变量在接收到实参表传过来的值时,会在内存临时开辟新的空间,以保留形参变量的值,当函数执行完毕时,这些临时开辟的内存空间会被释放,并且形参的值在函数中不论是否发生变化,都不会影响到实参变量的值的变化,这就是函数的传值方式。,自定义函数在程序中的使用顺序有两种形式:,先进行函数声明,再进行函数调用,函数定义放在函数调用之后。函数声明在函数调用之前。函数定义放在函数调用之前。,2023/11/7,10,【例6-1】编程序,通过调用函数abs-sum(),求任意两个整数的绝对值的和。,/*exam6_1.c 调用函数求两整数绝对值的和*/#include int abs_sum(int m,int n);main()int x,y,z;scanf(%d%d,程序运行结果:7 12sum is 19,2023/11/7,11,用传值方式调用函数时,实参也可以是函数调用语句,【例6-2】求任意三个数的绝对值的和。,/*exam6_2.c 调用函数求三个整数绝对值的和*/#include int abs_sum(int m,int n);main()int x,y,z,sum;scanf(%d%d%d,程序运行结果:7 12 5sum is 24,2023/11/7,12,注意:,对于有返回值的函数,调用时若没有把它赋给某个变量,仍然是可以的,只是函数的返回值有可能会被丢失。,【例6-3】求任意两数的乘积。,自定义一个函数mul(),用于求两数的乘积,程序:/*exam6_3.c 求两个数的乘积*/#include float mul(float a,float b);main()float x,y,z;scanf(%f%f,/*/,2023/11/7,13,x=x*2;y=y*2;printf(z=%f,mul(%f,%f)=%fn,z,x,y,mul(x,y);/*/float mul(float a,float b)return a*b;,程序运行结果:5 6z=30.000000,mul(30.000000,-8.000000)=-240.000000,2023/11/7,14,程序说明:,注释处调用函数后的返回值赋给变量z。,注释处调用函数后的返回值没有赋给任何变量,函数的返回值被丢失。,注释处调用函数后的返回值成为了printf()函数的参数。,2023/11/7,15,6.2 变量作用域和存储类型,一变量的作用域,变量的作用域:指的是变量的有效范围,针对变量不同的作用域,可把变量分为局部变量和全局变量。,局部变量:在函数内部或某个控制块的内部定义的变量为局部变量,局部变量的有效范围只限于本函数内部,退出函数,该变量自动失效。,全局变量:在函数外面定义的变量称为全局变量,全局变量的作用域是从该变量定义的位置开始,直到源文件结束。在同一文件中的所有函数都可以引用全局变量。,2023/11/7,16,局部变量和全局变量的作用域如图所示:,2023/11/7,17,【例6-4】变量作用域应用举例,阅读下面的程序,注意区分局部变量和全局变量的作用域。,/*exam6_4.c 变量作用域举例*/#include void a(void);void b(void);void c(void);int x=1;main()int x=5;printf(local x in outer scope of main is%dn,x);,2023/11/7,18,int x=7;printf(local x in inner scope of main is%dn,x);printf(local x in outer scope of main is%dn,x);a();b();c();a();b();c();,前三次输出结果:local x in outer scope of main is 5local x in inner scope of main is 7local x in outer scope of main is 5,2023/11/7,19,printf(local x in main is%dn,x);getchar();return 0;void a(void)int x=25;printf(nlocal x in a is%d after entering an,x);+x;printf(local x in a is%d before exiting an,x);,2023/11/7,20,void b(void)static int x=50;printf(nlocal static x is%d on entering bn,x);+x;printf(local static x is%d on exiting bn,x);void c(void)printf(nglobal x is%d on entering cn,x);x*=10;printf(global x is%d on exiting cn,x);,2023/11/7,21,程序运行结果:后6次函数调用,local x in a is 25 after entering alocal x in a is 26 before exiting alocal static x is 50 on entering blocal static x is 51 on exiting bglobal x is 1 on entering cglobal x is 10 on exiting clocal x in a is 25 after entering alocal x in a is 26 before exiting alocal static x is 51 on entering blocal static x is 52 on exiting bglobal x is 10 on entering cglobal x is 100 on exiting c,最后一次输出:local x in main is 5,2023/11/7,22,二变量的存储类型,变量的存储类型:指的是变量的存储属性,它说明变量占用存储空间的区域。,在内存中,供用户使用的存储区由程序区、静态存储区和动态存储区三部分组成。,变量的存储类型有四种:auto型、register型、static型和extern型。,auto型变量存储在内存的动态存储区。register型变量保存在寄存器中。static型变量和extern型变量存储在静态存储器。,2023/11/7,23,局部变量的存储类型缺省值为auto型。全局变量的存储类型缺省值为extern型。,auto型变量和register型变量只用于定义局部变量。static型变量即可定义成局部变量,又可定义成全局变量。,【例6-5】设计一个函数:long fac(int n),可用来计算15的阶乘。,分析:可在函数中定义一个static型变量,用来保存上次的计算结果。,2023/11/7,24,/*exam6_5.c 用static型变量保留上次阶乘的值*/#include long fac(int n)static int f=1;f=f*n;return f;main()int i;for(i=1;i=5;i+)printf(%d!=%ldn,i,fac(i);,程序运行结果:1!=1 2!=2 3!=6 4!=24 5!=120,局部变量f被定义成static型的,因此,它只在该函数第1次被调用的时候初始化其值为1,以后再调用该函数时,不再进行初始化,而是使用上一次调用的值。,2023/11/7,25,6.3 内部函数与外部函数,一内部函数,若函数的存储类型为static型,则称其为内部函数或称静态函数,它表示在同一个程序中(由多个源文件组成),该函数只能在一个文件中存在,在其它文件中不可使用。,如:static int fun-name();内部函数只能被其所在的源文件调用。,二外部函数,若函数的存储类型定义为extern型,则称其为外部函数,它表示该函数能被其它源文件调用。函数的缺省存储类型为extern型。,注意:在需要用到外部函数的文件中,其函数声明必须用extern进行说明。,2023/11/7,26,例如:有两个源文件file1.c和file2.c如下所示:,/*file1.c 调用外部函数*/#include int mod(int a,int b);extern int add(int m,int n);/*外部函数声明*main()int x,y,result;scanf(“%d%d”,2023/11/7,27,int mod(int a,int b)return(a%d);/*file2.c外部函数*/extern int add(int m,int n)return(m+n);,说明:,1在文件1(file1.c)中的函数声明:int mod(int a,int b);实际上相当于:extern int mod(int a,int b);,2023/11/7,28,2在文件2(file2.c)中的函数定义:extern int add(int m,int n)return(m+n);实际上相当于:int add(int m,int n)return(m+n);,3由多个源文件组成一个程序时,main()函数只能出现在一个源文件中。,2023/11/7,29,4多个源文件的连接方式有三种:,将各源文件分别编译成目标文件,得到多个目标文件(.obj后缀),然后用连接命令(tlink)把多个.obj文件连接起来,在Turbo c上用如下命令:tlink file1.obj+file2.obj+filen.obj生成一个file1.exe的可执行文件。,建立项目文件(.prj后缀),具体操作可参阅各种C编译手册。,使用文件包含命令。,2023/11/7,30,6.4 递归函数设计和调用,C语言中一个函数中的语句可以是对另一个函数的调用。,函数嵌套调用图例:,调用过程按图中箭头所示的方向和顺序进行,属于一种线性调用关系,每次调用后,最终返回到原调用点,继续执行以下语句。,2023/11/7,31,C语言中还允许在函数中调用自身,或函数之间相互调用,这种调用方式称之为递归。递归又分为直接递归调用和间接递归调用。,直接递归调用;函数直接调用自身。,间接递归调用:函数互相调用对方。,直接递归:,int temp(int x)int y,z;z=temp(y);,2023/11/7,32,间接递归:,显然,递归有可能陷入无限递归状态,最终导致错误发生。因此,设计一个递归问题必须具备两个条件:,1后一部分与原始问题类似。2后一问题是原始问题的简化。,2023/11/7,33,【例6-6】编程,从键盘输入一个正整数n,求n!。,n!的数字表达式为:n!=,定义一个求n!的函数:long fac(int n)long fac(int n)long result;if(n=0|n=1)result=1;else result=n*fac(n-1);return(result);,2023/11/7,34,完整程序如下:,/*exam6_6.c 用递归法求n!*/#include long fac(int n)long result;if(n=0|n=1)result=1;elseresult=n*fac(n-1);return result;main()int x;long f;,2023/11/7,35,scanf(%d,程序运行结果:66!=720,2023/11/7,36,【例6-7】求Fibonacci数列第i项的值。Fibonacci数列:0,1,1,2,3,5,8,13,21,其数字表达式为:fibonacci(0)=0 fibonacci(1)=1 fibonacci(n)=fibonacci(n-1)+fibonacci(n-2)(n1),设计一个函数:long fibonacci(int n)用于计算数列中第n项的值,,2023/11/7,37,程序如下所示:,/*exam6_7.c 求第n项Fibonacci数列的值*/#include long fibonacci(int n);main()int x=0;long result;doresult=fibonacci(x);printf(fibonacci(%d)=%ldn,x,result);scanf(%d,2023/11/7,38,long fibonacci(int n)if(n=0|n=1)return n;elsereturn fibonacci(n-1)+fibonacci(n-2);,程序运行结果:fibonacci(0)=03fibonacci(3)=24fibonacci(4)=36,2023/11/7,39,以x=4为例,下图说明了fibonacci函数是怎样计算fibonacci(4)的。图中把fibonacci简写成f。,2023/11/7,40,6.6 综合范例,【例6-12】在屏幕上画一个1818大小的棋盘。,程序如下:,/*exam6_12.c 在屏幕上画一个棋盘*/#include#include#include/*定义画棋盘所需的制表符*/#define LU 0 xda/*左上角*/#define RU 0 xbf/*右上角*/#define LD 0 xc0/*左下角*/#define RD 0 xd9/*右下角*/#define L 0 xc3/*左边*/#define R 0 xb4/*右边*/,2023/11/7,41,#define U 0 xc2/*上边*/#define D 0 xc1/*下边*/#define CROSS 0 xc5/*十字叉*/*棋盘左上角坐标*/#define MAP_X 5#define MAP_Y 5void draw_cross(int x,int y);void draw_map();main()textmode(C40);draw_map();,2023/11/7,42,/*函数定义:*/void draw_map()/*画棋盘*/int i,j;for(i=0;i19;i+)for(j=0;j19;j+)draw_cross(i,j);void draw_cross(int x,int y)gotoxy(x+MAP_X,y+MAP_Y);textcolor(GREEN);if(x=0,2023/11/7,43,if(x=0,2023/11/7,44,if(x=0)putch(L);/*画左边*/return;if(x=18)putch(R);/*画右边*/return;if(y=0)putch(U);/*画上边*/return;,2023/11/7,45,if(y=18)putch(D);/*画下边*/return;putch(CROSS);/*画十字叉*/,程序中宏定义的制表符的值可从ASC码表中查得,如:0 xbf为十六进制表示,它代表右上角制表符“”。,该程序必须在纯DOS模式下运行,其运行结果是在屏幕上显示一个绿色的1818大小的方格棋盘,如后图所示。,2023/11/7,46,该程序显示一个绿色的1818大小的方格棋盘,2023/11/7,47,【例6-13】将一个字符串的字符反向输出到屏幕。,采用递归函数调用方法,程序如下:,/*exam6_13.c 反向显示字符串*/#include#include void backwards(char s,int index);/*函数声明*/main()char str80;/*定义字符数组*/int index=0;strcpy(str,Show this string.);/*字符串拷贝*/backwards(str,index);/*函数调用*/,2023/11/7,48,void backwards(char s,int index)/*函数定义*/if(sindex)printf(%c,sindex);/*输出字符*/backwards(s,index+1);/*递归调用*/printf(%c,sindex);/*输出字符*/,程序运行结果:Show this string.gnirts siht wohS,2023/11/7,49,小结:,介绍了函数的定义和传值调用函数的使用方法。,注意:若用全局变量作为函数的参数,则在函数中可以使得该全局变量的值发生变化。,对于递归函数的设计一定要有可使递归结束的条件,否则会使程序产生无限递归。,使用预处理命令时,要注意以下几点:1宏替换定义的末尾不能使用分号“;”。2在有参数的宏定义中,参数加括号和不加括号有时会有区别。3使用文件包含时,要避免出现变量和函数发生重定义的现象。4要区分条件编译与条件语句的作用。,

    注意事项

    本文(c语言第六章函数与宏定义.ppt)为本站会员(小飞机)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开