第10章 函数与程序结构.ppt_第1页
第10章 函数与程序结构.ppt_第2页
第10章 函数与程序结构.ppt_第3页
第10章 函数与程序结构.ppt_第4页
第10章 函数与程序结构.ppt_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

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( 其他.退出程序运行n); s

3、canf(%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 double vo

5、l_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,7,例10-1 分别存储在prog

6、1.c、prog2.c源文件中。,源文件1:prog1.c,VC环境操作,设置被包含文件的路径 Tools-option-Directories 在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( 其他.退出程序运行n); scanf(%d,8,2.源文

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

8、: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 extern double vol_ba

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

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

11、ntf(%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为 #include static int a; void main() int j=2; printf(%d ,a); ,在文件file2.c为 extern int a; fun(int n) a=a*n

12、; . ,外部说明无效,在多人合作时,使用静态全局变量避免各自定义的全局变量重名,静态全局变量,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个人多少岁?他

13、说 比第2个人大2岁。 问第2个人多少岁?他说比第1个人大2岁。 最 后问第1个人,他说10岁。求第5个人的岁数?,若用函数age(n)表示第n个人的岁数 显然 age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(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) ag

14、e(2) age(1),c=age(4)+2 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; e

15、lse f=fac(n-1)*n; return(f); main() 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:re

16、turn 2; printf(g=%d,g); return (f (g-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

17、 n) int t; if(m=0) t=n+1; else if(n=0) 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%10 f(x/10),void f(int x) if(x0) printf(%d,x%10); f(x/10

18、); void main() int a; scanf(%d, ,21,void f(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

19、.1 宏定义 1. 基本宏定义 格式 #define 标识符 字符串 操作 指定一个标识符来代表一个字符串,即定义符号常量,例 #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 1000

20、 int a size 根据算题需要对宏定义size修改设置数组大小,宏定义字符串替换前不做语法检查,但对换后展开的语句检查语法 例 #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*R main() printf(L=%fn S=%fn ,L,S);,宏展开 printf(L=%fn

21、S=%fn ,2*3.1415926*3.0,3.1415926*3.0*3.0);,在双引号中的字符串内的字符不能展开,引号中的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);

22、printf(n); #define B This is the second macro 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*x main() int x,y; scanf(%d %d, ,宏展开 x=MAX(x,y); - x=ab?a:b; - x=xy?x

23、:y; y=SQR(x); - y=x*x;,main() int x,y; scanf(%d %d, ,28,注宏展开是字符串替换,程序中相应的参数是表达式替换也不例外 如上例中要求 y=(x+y)2,所以参数宏定义时一般把参数用括号括起来,例10-7 程序改为 #define MAX(a,b) ab?a:b #define SQR(x) x*x main() 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); -

24、y=(x)*(x); - y=(x+y)*(x+y);符合要求,29,带参数的宏定义与函数定义区别 (1)函数的形参、实参要定义类型,而宏定义不需要 (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) 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

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论