第06章函数与预处理.ppt

上传人:sccc 文档编号:5885825 上传时间:2023-08-29 格式:PPT 页数:87 大小:418.54KB
返回 下载 相关 举报
第06章函数与预处理.ppt_第1页
第1页 / 共87页
第06章函数与预处理.ppt_第2页
第2页 / 共87页
第06章函数与预处理.ppt_第3页
第3页 / 共87页
第06章函数与预处理.ppt_第4页
第4页 / 共87页
第06章函数与预处理.ppt_第5页
第5页 / 共87页
点击查看更多>>
资源描述

《第06章函数与预处理.ppt》由会员分享,可在线阅读,更多相关《第06章函数与预处理.ppt(87页珍藏版)》请在三一办公上搜索。

1、第6章 函数与预处理,*重点与难点6.1 模块化软件与C程序的模块结构6.2 函数定义、参数和返回值6.3 函数调用6.4 函数中使用的变量,6.5 内部函数与外部函数6.6 多文件的程序运行6.7 预处理命令*本章小结*作业,重点与难点,重点:函数的定义、声明、参数传递和调用;函数的嵌套调用;变量的作用域与生存期。难点:参数传递和函数的嵌套调用。,6.1 模块化软件与C程序的模块结构,6.1.1 模块化软件6.1.2 C语言的模块结构,6.1.1 模块化软件,模块化:就是将一个较为复杂的、大型的项目按其功能与结构,划分为若干个功能相对独立的模块(Module),每个模块实现一个功能。C语言:

2、是一种结构化程序设计语言,结构化程序设计的基本思想之一就是程序的“模块化”。每个模块在C语言中可以用函数来实现。,6.1.2 C语言的模块结构,C程序的组成,C程序:可以由一个或多个C源程序文件组成。在C语言中,一个C语言的源程序文件就是一个编译单位。函数:它是C源程序的基本模块。,函数分类,从用户使用的角度 标准库函数与用户自定义函数从有无函数返回值的角度 有返回值函数与无返回值函数从有无参数的角度 有参函数与无参函数,6.2 函数定义、参数和返回值,6.2.1 函数定义的一般形式6.2.2 函数参数与参数传递6.2.3 函数返回值,6.2.1 函数定义的一般形式,1、无参函数2、有参函数3

3、、空函数,1、无参函数,类型标识符 函数名()类型说明 语句,void printmessage()printf(nHello!);,2、有参函数,类型标识符 函数名(形式参数列表)类型说明 语句,int max(int x,int y)return(xy?x:y);,3、空函数,类型说明符 函数名(),调用这种函数没有任何实际作用,但在系统规划的初期用于标示各个部分,使得程序结构清楚,可读性好,以后扩充新的功能方便。,6.2.2 函数参数与参数传递,1、分类:形式参数和实际参数。2、形参:在函数定义的时候声明的参数称为形式参数,简称形参。形参是变量名。3、实参:在函数调用的时候使用到的参数称

4、为实际参数,简称实参。实参是表达式。,参数传递,1、参数传递是实参传递给形参。2、传递要求:在参数传递的过程中,实参的个数必须与形参的个数一样多,并且类型应相同或保持兼容,否则系统会给出错误。3、分类 值传递与地址传递,值传递方式,一般采用的是单向的值传递,即将实参的值拷贝给形参。形参在调用前和调用后都是不存在的,只有函数被调用时形参才被分配相应的存储单元。实参与形参即使是同名的变量,它们也代表不同的存储单元,互不影响。,值传递图示,c=min(a,b);,函数调用开始,函数调用结束,地址传递方式,如果形参是地址方式,实参传递给形参采用地址传递方式,即形参共用实参的地址,这样,形参的改变也会间

5、接地改变形参的值。,6.2.3 函数返回值,函数的返回值是通过return语句返回主调函数。该语句的形式如下:,return 表达式;,一个函数至多只能返回一个值。,返回值类型,return语句的表达式的计算结果的类型常常与函数定义的返回类型不一致。这时应该以哪一个为准呢?(1)C语言规定,函数的返回值的类型以函数定义的类型为准。(2)如果return语句中的表达式是数值型的,系统自动进行类型转换。如果系统不能自动转换的,则需要编程人员进行强制转换。,函数默认类型,如果在函数定义时没有指定返回值的类型,系统默认为int型的。,无return语句,如果被调用函数中没有return语句,是不是没有

6、返回值呢?其实不是,函数仍然返回一个值,只不过这个值是不确定的、也不是用户所希望得到的。如果一个函数没有返回值,最好是用void明确地表示出来。这样,可以保证函数正确调用,减少出错。,6.3 函数调用,6.3.1 函数的一般调用6.3.2 函数的嵌套调用6.3.3 函数的递归调用,6.3.1 函数的一般调用,函数名(实参表列),函数调用形式,(1)函数语句 printf(Welcome to C language.);(2)函数表达式 c=max(a,b);(3)函数作参数 d=max(a,max(b,c);,6.3.2 函数的嵌套调用,举例:用弦截法求方程的根。,自定义函数,1、f(x)=2

7、、xpoint(,)=3、root(x1,x2),函数调用关系,root函数,float root(float x1,float x2)float x,y,y1=f(x1);do x=point(x1,x2);y=f(x);if(y*y10)y1=y;x1=x;else x2=x;while(fabs(y)=0.0001);return(x);,6.3.3 函数的递归调用,1)直接调用自身,2)间接调用自身,递归的两个阶段,回推和递推 回推到可以确定值(即递归结束条件)时结束;递推从起初值开始进行迭代。,4!的回推与递推举例,回推 f(4)=4*f(3)=4*3*f(2)=4*3*2*f(1)

8、递推 f(1)=1 f(2)=2*f(1)=2 f(3)=3*f(2)=3*2=6 f(4)=4*f(3)=4*6=24,递归调用实质,在不能计算出结果时,先压栈;在能够计算时,逐个出栈。,例6.8 利用递归算法求Fibonacci数列,0(n=0)f(n)=1(n=1)f(n-1)+f(n-2)(n1),long f(int n)long c;if(n=0)c=0;else if(n=1)c=1;else c=f(n-1)+f(n-2);return(c);,课堂训练,自定义两个函数实现:(1)判断一个整数是否为完数;(2)在屏幕上显示完数的因子。要求:在main函数中输入整数,并调用上述两

9、个函数进行测试。,6.4 函数中使用的变量,6.4.1 局部变量与全局变量6.4.2 变量的存储方式6.4.3 变量的存储类别,6.4.1 局部变量与全局变量,1、局部变量2、全局变量,1、局部变量,在一个函数内部定义的变量是内部变量,也称局部变量。局部变量只在定义它的函数范围内有效(即可以使用),在其他函数不能使用。,局部变量举例,float f1(int a)int b,c;.char f2(int x,int y)int i,j;.main()int a,b;.int c;c=a+b;,a,b,c有效,x,y,i,j有效,c有效,a,b有效,2、全局变量,程序的编译单位是源程序文件,一个

10、源文件可以包含一个或若干个函数。在函数内定义的变量是局部变量;而在函数外定义的变量是外部变量,也称全局变量。全局变量的有效范围:从定义变量的位置开始到本源文件结束。,全局变量举例,int p=1,q=5;float f1(a)int b,c;.char a,b;char f2(int x,int y)int i,j;.main()int a,b;.char c;c=a+b;.,a,b,c有效,x,y,i,j有效,c有效,a,b有效,全局变量a,b有效,全局变量p,q有效,例6.9 全局变量a,int a=10;fun(int i)a+=2*i;return a;main()int a=10;p

11、rintf(n%d,%d,fun(a),a);printf(n%d,%d,fun(a),a);,运行结果:20,1040,10,例6.10 有一个数组存放10个学生的成绩,编一个函数求出10个学生的平均成绩、最高分和最低分。,float max=0,min=0;float averagescore(float a,int n)int i;float sum=a0;max=min=a0;for(i=1;imax)max=ai;else if(aimin)min=ai;sum=sum+ai;return(sum/n);,全局变量应慎用,全局变量在程序执行过程中一直占用内存。降低了函数的通用性。使用

12、全局变量过多,会降低程序的可读性。建议不在必要时不要使用全局变量。,6.4.2 变量的存储方式,静态存储方式,静态存储方式是指在程序运行期间分配固定的存储空间的方式。全局变量和静态(static)变量全部存放在静态存储区。静态存储方式在程序执行过程中一直占据固定的存储单元,直到程序执行完毕才释放。,动态存储方式,动态存储方式:是在程序运行期间根据需要进行动态分配存储空间的方式。在动态存储区存放如下数据:形参、非静态变量、堆栈(函数调用时的现场保护和返回地址)。动态存储方式根据函数调用的需要,动态地分配和释放存储空间。,6.4.3 变量的存储类别,在C语言中,每一个变量和函数有两个属性:数据类型

13、和存储类别。存储类别分四类,auto变量,auto int b,c=3;int b,c=3;,两者等价,static,f(int a)auto int b=0;static int c=3;b=b+1;c=c+1;return(a+b+c);main()int a=2,i;for(i=0;i3;i+)printf(%d,f(a);,运行结果:7 8 9,为何结果不是:7 7 7呢?,原因:static型变量是在编译时赋初值的,只赋值一次,即在程序运行时它已有初值。,举例 打印15的阶乘值,int fac(int n)static int f=1;f=f*n;return(f);main()in

14、t i;for(i=1;i=5;i+)printf(n%d!=%d,i,fac(i);,运行结果1!=12!=23!=64!=245!=120,慎用static变量,static变量长期占用内存,直到程序执行完才释放。降低了程序的可读性。,register变量,寄存器的存取时间比内存要快C语言允许频繁使用的局部变量的值存放在cpu的寄存器中。register int i;Turbo c将register变量作auto变量处理。,用extern声明外部变量,编译时,将外部变量(即全局变量)分配在静态存储区。如果外部变量定义处在后或在其他文件中并且使用在前时,则需要对它进行声明。声明分为:1、在一

15、个文件内声明外部变量2、在多文件的程序中声明外部变量,声明与定义,定义:是定义性声明,需要建立存储空间。定义只能有一次。声明:是引用性声明。声明可以出现多次。声明的作用是一个已在后面定义的外部变量,仅仅是为了“提前”引用该变量而作的“声明”。声明要求外部变量已经定义。,例6.13 外部变量声明,main()extern x,y;int z;z=x*y;printf(nz=%d,z);int x=2,y=3;,例6.14 在多文件的程序中声明外部变量,*eg0614a.cint a=4;int max(int x,int y)return(xy?x:y);,*eg0614b.cextern a;

16、main()int x=2,y=3,z;z=x*a+a*y*max(x,y);printf(nz=%d,z);,6.5 内部函数与外部函数,1、内部函数2、外部函数,1、内部函数,如果一个函数只能被本文件中的其他函数调用,而不能被其他文件中的函数调用,这种函数称为内部函数(或称静态函数)。定义内部函数的一般形式是(函数头):,static 类型说明符 函数名(形参表),2、外部函数,若一个函数除了可以被本文件中的其他函数调用外,还可以被程序中的其他源文件的函数调用,这样的函数称为外部函数。它的定义一般形式:,extern 类型说明符 函数名(形参表),注意:extern可以省略,例6.15 内

17、部函数与外部函数,*eg0615a.cextern int a;extern int max(int m,int n);static int z=12;static int min(int x,int y)return(xy?x:y);main()int x=2,y=3;printf(max=%d,min=%d,max(x,y),min(a,z);,*eg0615b.cint a=10;int max(int m,int n)if(m=n)return(m);else return(n);,6.6 多文件的程序运行,1、工程方法2、文件包含方法,1、工程方法,2、文件包含方法,在eg0615.

18、c的开始添加一行:#include在文件包含方式中,由于最终生成一个目标文件。所以关于变量、函数的声明都不必要了。,6.7 预处理命令,在前面章节已经使用了如下形式:#define PI 3.14#include,预处理命令,ANSI C 标准规定可以在C源程序中加入一些“预处理命令”,以改进程序设计环境,提高编程效率。预处理命令不是C语言本身的组成部分,必须在正式编译前进行处理。C提供的预处理功能主要有一下3种:,1、宏定义2、文件包含3、条件编译,6.7.1 宏定义,1、不带参数的宏定义2、带参数的宏定义,1、不带参数的宏定义,一般形式#define 标识符 字符串 不带参数的宏常用来表示

19、符号常量举例#define PI 3.1415926,宏定义的作用,宏定义是用宏名代替一个字符串,即只作简单的置换,不作正确性检查。也不分配存储空间。举例#define PI 3.14;area=PI*r*r;展开后如下:area=3.14;*r*r;/*error*/,宏定义的作用域,宏名的有效范围为定义命令之后到本源文件结束。可以用#undef命令终止宏定义的作用域。,宏的作用域举例,#define G 9.8main().#undef Gf1().,G的作用范围,宏的层层置换,#define R 3.0#define PI 3.14#define L 2*PI*R#define S PI

20、*R*Rmain()printf(nL=%fnS=%f,L,S);,9.1.2 带参数的宏定义,一般形式#define 宏名(参数表)字符串,带参数宏举例(例6.17),#define PI 3.14#define S(r)PI*r*rmain()float a,area;a=3.6;area=S(a);printf(nr=%f area=%f,a,area);,带参数宏与函数,形式相同,容易混淆不同之处主要有:(1)函数调用需要参数检查;宏只作简单置换。(2)函数调用在程序运行时处理,分配内存单元;宏展开在正式编译前进行,不分配存储单元,无返回值概念。(3)函数调用占运行时间,源程序保持不变

21、;宏展开只占编译时间,展开后源程序变长。,举例:可以得到多个结果的宏,#define PI 3.14#define CIRCLE(R,L,S)L=2*PI*R;S=PI*R*R;main()float r,l,s;printf(nr=);scanf(%f,6.7.2“文件包含”处理,“文件包含”处理是指一个源文件可以将另外一个源文件的全部包含进来。一般形式,#include文件名或#include,两种包含形式比较,#include:系统到存放C库函数文件所在的目录中寻找要包含的文件,这种称为标准方式。#includefile2.c:系统先在用户当前目录中寻找要包含的文件,如果找不到,再按标准

22、方式查找。,“文件包含”的含义,file1.c,#include,file2.c,B,A,file1.c,A,B,“文件包含”的实质,被包含的文件与其所在的文件,在预编译后已经成为同一个文件(而不是两个文件)。被包含的文件的外部变量作用域扩展到了包含文件,所以不必用extern声明。,6.7.3 条件编译,一般情况下,源程序中所有的行都参加编译。但如果对其中一部分内容只在满足一定条件才进行编译,这就是“条件编译”。,条件编译形式,1)#ifdef 标识符 程序段1#else 程序段2#endif2)#ifdef 标识符 程序段1#endif,3)#ifndef 标识符 程序段1#else 程序

23、段2#endif4)#if 表达式 程序段1#else 程序段2#endif,例9.7 条件编译大小写转换,#define LETTER 1main()char str20=C language,c;int i=0;while(c=stri)!=0)i+;,#if LETTER if(c=a,程序调试输出,#define DEBUG 1main()int i,s=0;while(i=100)s=s+i i+#ifdef DEBUG printf(ni=%d,s=%d,i,s);#endif printf(nsum=%d,s);,课堂训练,简单的学生成绩管理程序。要求编写下列函数:(1)输入函数:输入5个学生3门课程的成绩;(2)输出函数:在屏幕上按一行一个学生资料显示成绩。(3)计算函数:计算课程的平均成绩。,本章小结,函数的定义;函数参数的传递;函数的嵌套调用、递归调用;变量的作用域和生存期;内部函数与外部函数;多文件程序的运行。,作业,p119 6.28,6.29,6.32,6.31,

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

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号