收藏 分享(赏)

第10章 函数与程序结构.ppt

上传人:hskm5268 文档编号:7249398 上传时间:2019-05-10 格式:PPT 页数:34 大小:430KB
下载 相关 举报
第10章 函数与程序结构.ppt_第1页
第1页 / 共34页
第10章 函数与程序结构.ppt_第2页
第2页 / 共34页
第10章 函数与程序结构.ppt_第3页
第3页 / 共34页
第10章 函数与程序结构.ppt_第4页
第4页 / 共34页
第10章 函数与程序结构.ppt_第5页
第5页 / 共34页
点击查看更多>>
资源描述

1、1,第10章 函数与程序结构,编程模块化,从上到下逐步细化,C语言程序由一个主函数或一个主函数与若干其它函数构成,10.1 函数的组织,10.1.1 函数结构,main(),函数1,函数2,函数m,函数11,函数mq,函数1q,函数m1,每个函数是独立的模块,函数结构图,2,例10-1 设计一个常用圆形体体积的计算器。采用对话方式输入1、2、3分别计算球体、圆柱体、圆锥体的体积,并输入相应的计算参数,结构化考虑,main(),cal(),vol_ball(),vol_cylind(),vol_cone(),#include #define PI 3.1415926 double vol_bal

2、l() double r;printf(“球半径:“);scanf(“%lf“, ,void cal(int sel) switch(sel)case 1:printf(“球体积=%fn“,vol_ball();break;case 2:printf(“圆柱体积=%fn“,vol_cylind();break;case 3:printf(“圆锥体积=%fn“,vol_cone(); void main() int sel;while(1)printf(“ 1.计算球体体积n“);printf(“ 2.计算圆柱体积n“);printf(“ 3.计算圆锥体积n“);printf(“ 其他.退出程序

3、运行n“);scanf(“%d“,3,10.1.2 函数的嵌套调用,函数嵌套 在被调用函数体中又调用另一个函数,如 main() a函数 b函数 调用a函数 调用b函数 ,例9-1,main,a,b,void main() int sel;while(1)cal(sel); ,void cal(int sel) switch(sel) . ,double vol_ball() double vol_cylind() double vol_cone() ,4,10.1.3 函数与程序文件模块,C程序,源程序文件1,源程序文件2,源程序文件n,预编译命令,函数1,函数m,注C程序由一个或多个源程序

4、文件组成,每个源程序文件由一个或多个函数构成。一个源程序文件是一个编译单位,分别编译,然后连接成执行文件。多个源程序文件中只能一个主函数main()。,声明全局变量,5,多个源程序文件组合,例10-1 分别存储在2个源文件中。,#include void cal(int sel); void main() int sel;while(1)printf(“ 1.计算球体体积n“);printf(“ 2.计算圆柱体积n“);printf(“ 3.计算圆锥体积n“);printf(“ 其他.退出程序运行n“);scanf(“%d“,源文件1:prog1.c,#define PI 3.1415926

5、double vol_ball() double r;printf(“球半径:“);scanf(“%lf“, ,源文件2:prog2.c,6,1.使用文件包含,格式 #include 或 #include “文件名.扩展名“,其中 扩展名,如 .c .cpp .h,#include “file2.c“,A,B,B,A,如 源文件file1.c 源文件file2.c 源文件file1.c,:在C系统的include文件夹下找指出的库文件。 “ “:先在当前工作文件夹下指出的文件再在C系统的include文件夹找指出的文件 可以直接指出文件夹下指出的文件如 #include “e:cfile.c“

6、,7,例10-1 分别存储在prog1.c、prog2.c源文件中。,源文件1:prog1.c,VC环境操作,设置被包含文件的路径 ToolsoptionDirectories 在Directories:增加被包含文件的路径,或被包含文件放置当前工作文件夹下,注:被包含文件不能装载在工程,#include #include “prog2.c“ void cal(int sel); void main() int sel;while(1)printf(“ 1.计算球体体积n“);printf(“ 2.计算圆柱体积n“);printf(“ 3.计算圆锥体积n“);printf(“ 其他.退出程序运

7、行n“);scanf(“%d“,8,2.源文件各自作为独立的程序模块,定义函数 extern 类型标识符 函数名(形参说明表) extern定义的函数称是外部函数(所有源程序文件中能调用的函数) 在调用另一个源程序文件的外部函数时, 一般需要事先声明声明格式 extern 类型标识符 函数名(形参说明表);,在一个源文件中,函数的有效域:(1)函数定义在前,使用在后。(2)若函数定义在后,使用在前时,必须满足下列之一:被调用的函数类型是int类型说明在调用函数的模块中声明被调用函数在函数外说明被调用函数,(1)在一个源文件调用另一源文件中的函数,在多源文件中,函数的有效域:,9,例10-1 分

8、别存储在2个源文件中。,源文件1:prog1.c,源文件2:prog2.c,#include extern double vol_ball(); extern double vol_cylind(); extern double vol_cone(); void cal(int sel); void main() int sel;while(1)printf(“ 1.计算球体体积n“);printf(“ 2.计算圆柱体积n“);printf(“ 3.计算圆锥体积n“);printf(“ 其他.退出程序运行n“);scanf(“%d“,#include #define PI 3.1415926

9、extern double vol_ball() double r;printf(“球半径:“);scanf(“%lf“, ,定义外部函数,声明外部函数,10,注:定义函数和声明使用函数时,VC extern可以省略。完全与在一个源文件中使用函数一样。,VC环境操作,(1)源文件全部加入工程,鼠标右键点击 source filesadd files folder浏览选择加入的源文件 若增加的是新源文件,按新源文件操作。,(2)逐个编译源文件,(3)连接、运行,11,定义格式 static 类型标识符 函数名(形参说明表) static定义的函数称静态函数,仅本源程序文件中能调用。又称内部函数,

10、3.定义只能在本源文件中调用的函数时,在多人合作时,使用静态函数避免各自定义的函数重名,12,4. 全局变量与程序文件模块,前面讲过全局变量是指在一个源程序文件,其作用域是定义变量的位置起到本源程序文件结束。当多个源程序文件时,全局变量作用域如何定义?,(1)在一个源程序文件中声明使用另一个源程序文件定义的全局变量使用extern变量 extern 类型名 变量名表; extern只是说明变量起作用,告诉C编译器该变量后面或外部文件定义。它不分配存储单元,所对应存储单元在变量定义处分配。,如在文件file1.c为#includeint f(int x);int v;void main()int

11、 j=3;v=j;printf(“%d %d “,v,f(v);,在文件file2.c为int f(int x)extern int v;return(3*x*v);,声明v是外文件定义的全局变量,全局变量,13,(2)用static声明全局变量的作用域从定义起到本源程序文件结束,割断与外源程序文件联系,使全局变量只有本源程序本文件内有效,即使外源程序文件用extern声明,也无效。,如在文件file1.c为#includestatic int a;void main()int j=2;printf(“%d “,a);,在文件file2.c为extern int a;fun(int n)a=a

12、*n;.,外部说明无效,在多人合作时,使用静态全局变量避免各自定义的全局变量重名,静态全局变量,14,10.2 递归函数,1.直接调用 如 int f(x)int x;int y,z;.z=f(x). ,2.间接调用 如 int f1(x)int x;int y,z;.z=f2(x);.,int f2(t)int t;int a,c;.c=f1(a);.,注递归不能无终止的自身调用,递归函数:函数自己调用自己,10.2.1 递归函数概念,15,例有5人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人多少岁?他说比第3个人大2岁。 问第3个人多少岁?他说比第2个人大2岁。 问第2个人

13、多少岁?他说比第1个人大2岁。 最后问第1个人,他说10岁。求第5个人的岁数?,若用函数age(n)表示第n个人的岁数 显然 age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10,则,用递归函数表示 int age(int n) int c;if(n=1) c=10;else c=age(n-1)+2;return(c); void main() printf(“%dn “,age(5); 输出 18,16,执行过程,age(5) age(4) age(3) age(2) age(1),c=age(4)+2

14、c=age(3)+2 c= age(2)+2 c=age(1)+2 c=10,主函数 4n 3n 2n 1n n=1,age(1)=10,age(2)=12,age(3)=14,age(4)=16,age(5)=18,int age(int n) int c;if(n=1) c=10;else c=age(n-1)+2;return(c);,17,分析 n!=n*(n-1)!(n-1)!=(n-1)*(n-2)!.2!=2*1!1!=1*0!0!=1,则,float fac(int n) float f;if(n=0)f=1;else f=fac(n-1)*n;return(f); main(

15、) int n; float y;scanf(“%d“, ,fac(3) fac(2) fac(1) fac(0)2n 1n 0n n=0 f=3*fac(2) f=2*fac(1) f=1*fac(0) f=1,fac(0)=1,fac(1)=1,fac(2)=2,fac(3)=6,主函数,一些循环可改为递归做,如求n!,18,10.2.2 递归函数的阅读,例10-4 求下列递归程序的输出,#include long f (int g) switch(g)case 0:return 0;case 1:case 2:return 2;printf(“g=%d,“,g);return (f (g

16、-1)+f (g-2); void main() long k;k=f (5);printf(“k=%ldn“,k); ,f(5),f(4)+f(3),f(3)+f(2),f(2)+f(1),2,2,=4,2,=6,4,=10,=10,输出:g=5,g=4,g=3,g=3,k=10,g=5,g=4,g=3,g=3,19,构造递归的条件 1.问题转化一个比原问题简单的且有相同结构的问题(递归表达式) 2.递归终止条件(函数的出口),10.2.3 递归程序设计,例 计算Ackermenn函数,int ack(int m,int n) int t;if(m=0) t=n+1;else if(n=0)

17、 t=ack(m-1,1);else t=ack(m-1,ack(m,n-1);return t; ,函数的出口,递归表达式,20,例 用递归方法实现对一个正整数的各位逆序输出,分离整数各位算法,整数x x%10 余数 分离最低位x/=10 去掉最低位当x0 循环分离整数所有的位,分析,循环实现程序 main() long x,;scanf(“%ld“, ,递归出口: x=0,递归表达式:x0输出x%10f(x/10),void f(int x) if(x0)printf(“%d“,x%10);f(x/10); void main() int a;scanf(“%d“, ,21,void f(

18、int x) if(x0)printf(“%d“,x%10);f(x/10); void main() int a;scanf(“%d“, ,输入1000,输出0001 若要求, 输入1000,输出1,void f(int x,int *s) if(x0)*s=*s*10+x%10;f(x/10,s); void main() int a,s=0;scanf(“%d“, ,22,10.3 编译预处理,预处理功能主要有三种1.宏定义2.文件包含3.条件编译,在头文件出现(函数之外),夹在函数之内,10.3.1 宏定义 1. 基本宏定义 格式 #define 标识符 字符串 操作 指定一个标识符来

19、代表一个字符串,即定义符号常量,例 #define PI 3.1415926 编译预处理先把程序中的PI均用3.1415926替换,然后再编译,23,例 字符串常量的定义,#define PI 3.1415926 main() float m,s,r;scanf(“%f“,main() float m,s,r;scanf(“%f“,编译前,程序转化为(宏展开),然后,再编译,24,使用宏定义减少程序中重复书写某些字符串的工作量,其好处改动方便例如在主函数中定义可调数组#define size 1000int a size根据算题需要对宏定义size修改设置数组大小,宏定义字符串替换前不做语法检

20、查,但对换后展开的语句检查语法例 #define PI 3.1415926;area=PI*r*r;经宏展开后 area=3.1415926;*r*r显然编译出错,指出错误的位置不是在宏定义处,而在宏引用处,25,在进行宏定义时可以引用已经定义的宏名,例 #define R 3.0#define PI 3.1415926#define L 2*PI*R#define S PI*R*Rmain()printf(“L=%fn S=%fn “,L,S);,宏展开 printf(“L=%fn S=%fn “,2*3.1415926*3.0,3.1415926*3.0*3.0);,在双引号中的字符串内的

21、字符不能展开,引号中的L、S不能宏展开,宏定义应一行完成。用“可以续行。例 #define Long_String “it is a long string that is used as an example.“,26,#define的命令出现在函数体外部的任何位置。作用域从定义点起至源程序文件的结束。 #undef命令提前终止#define定义的作用域。,例10-6 宏定义作用域,#define A “This is the first macro“ void f1() printf(A);printf(“n“); #define B “This is the second macro“

22、void f2() printf(B);printf(“n“); #undef B main() f1();f2(); ,B作用域,A作用域,27,2. 带参数的宏定义 格式 #define 标识符(参数表) 字符串 操作 不但进行字符串替换,还要参数替换,例10-7 简单的带参宏定义程序#define MAX(a,b) ab?a:b#define SQR(x) x*xmain()int x,y;scanf(“%d %d“, ,宏展开 x=MAX(x,y); x=ab?a:b; x=xy?x:y; y=SQR(x); y=x*x;,main()int x,y;scanf(“%d %d“, ,2

23、8,注宏展开是字符串替换,程序中相应的参数是表达式替换也不例外如上例中要求 y=(x+y)2,所以参数宏定义时一般把参数用括号括起来,例10-7 程序改为#define MAX(a,b) ab?a:b#define SQR(x) x*xmain()int x,y;scanf(“%d %d“, ,宏展开 y=SQR(x+y); y=x*x; y=x+y*x+y;显然与要求不符,宏定义应改为 #define SQR(x) (x)*(x),则宏展开 y=SQR(x+y); y=(x)*(x); y=(x+y)*(x+y);符合要求,29,带参数的宏定义与函数定义区别(1)函数的形参、实参要定义类型,

24、而宏定义不需要(2)函数虚实结合实参求值后传递给形参,而宏只是字符串替换(3)函数在运行时动态分配内存,而宏展开后在编译时进行,例10-7 宏定义 #define MAX(a,b) ab?a:b main() int x,y;scanf(“%d,%d“,函数 int max(int a,int b) return ab?a:b; main() int x,y;scanf(“%d,%d“,编译完成 main() int x,y; scanf(“%d,%d“,函数执行x-a,y-b 执行函数一次,30,例 求宏定义的程序输出,#define F(x) x-2 #define D(x) x*F(x)

25、 main() printf(“%d,%d“,D(3),D(D(3); ,宏展开,D(3)=x*F(x)=x*x-2=3*3-2,main() printf(“%d,%d“, 3*3-2, 3*3-2*3*3-2-2); ,输出:7,-13,注:一定要宏展开后再计算不可D(3)=7D(D(3)=D(7)= x*x-2=7*7-2=47,D(D(3)=D(3*3-2) D(y)x*F(x)x*x-2y*y-2 =3*3-2*3*3-2-2,设y=3*3-2,31,10.3.2 文件包含,文件包含在一个源程序文件内将另个源程序文件的内容包含进来 格式 #include “文件名.扩展名“ 或 其中

26、 扩展名: .c .h .cpp,如 源文件file1.c 源文件file2.c 源文件file1.c,#include “file2.c“,A,B,B,A,注 一个#include只能声明一个被包含文件,n个被包含文件需要n个#include命令。允许包含文件嵌套,即被包含文件中又出现#include命令被包含文件与其所在的文件视为一个文件,变量、函数的作用域按一个文件规定定义,32,10.3.3 条件编译,条件编译源程序的语句根据条件与否参加编译,格式#if 条件程序段1#else程序段2#endif,或 #if 条件程序段#endif,操作 当条件为真(非0),则对程序段1进行编译,否则编译程序段2。程序段2不存在#else可省条件必须是常量表达式讲义讲: 条件只能是宏名,应该改为 #ifdef 标识符 当标识符已经被定义过,则对程序段1进行编译,否则编译程序段2。,33,例 输入一行字母字符根据需要设置条件编译,使之能将全改大写或小写输出,#define LETTER 1 main() char str20=“C Languge“,c;int i;i=0;while(c=stri)!=0)i+;#if LETTERif(c=a ,条件编译主要用于程序调试或商业程序不同版本 例 #if DEBUG调试用的程序段#endif,34,作业:第10章作业下载http:/

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

当前位置:首页 > 中等教育 > 小学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报