第6章函数与编译预处理PPT课件_第1页
第6章函数与编译预处理PPT课件_第2页
第6章函数与编译预处理PPT课件_第3页
第6章函数与编译预处理PPT课件_第4页
第6章函数与编译预处理PPT课件_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

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

文档简介

1、教学目的和基本要求:教学目的和基本要求:要求学生了解模块化程序设计的思想,掌握要求学生了解模块化程序设计的思想,掌握函数的定义及调用,理解变量的作用域与存函数的定义及调用,理解变量的作用域与存储方式的概念,理解编译预处理的概念。储方式的概念,理解编译预处理的概念。 教学重点:(教学重点:( 读程序写结果常考知识点)读程序写结果常考知识点)函数的定义及调用;函数的定义及调用;递归调用;递归调用;参数传递(单向传值和传地址)的区别;参数传递(单向传值和传地址)的区别;变量的存储属性;变量的存储属性;带参数的宏定义。带参数的宏定义。第1页/共57页6.1 模块化程序设计与函数一、模块化程序设计1、基

2、本思想:将一个大的程序按功能分割成一些小模块2、特点:u各模块相对独立、功能单一、结构清晰、接口简单各模块相对独立、功能单一、结构清晰、接口简单u控制了程序设计的复杂性控制了程序设计的复杂性u提高元件的可靠性提高元件的可靠性u缩短开发周期缩短开发周期u避免程序开发的重复劳动避免程序开发的重复劳动u易于维护和功能扩充易于维护和功能扩充3、开发方法: 自上向下,逐步分解,分而治之第2页/共57页源程序文件1预编译命令说明部分执行部分函数1函数n源程序文件i源程序文件nC程序C程序结构&C是函数式语言&必须有且只能有一个名为main的主函数&C程序的执行总是从main函数开始

3、,在main中结束&函数不能嵌套定义,可以嵌套调用第3页/共57页看这样一个问题:求200,1000的双胞胎数的对数。双胞胎数:两素数差为2称为双胞胎数。 这是我们上一章结束的一道练习题,下面的左边是我们当时编的程序。main( ) int a,b,n=0,i; for(a=200;a=998;a+) for(i=2;ia;i+) if(a%i=0) break; if(a=i) b=a+2; for(i=2;ib;i+) if(b%i=0) break; if(b=i) n+; printf(“n%d”,n);我们注意到,程序中用 筐住的部分是完成了相同的功能,即判断一个数(a或b)

4、是否是素数。我们可以考虑用一个独立的函数来完成判断素数的功能,在主函数中调用此函数即可。如下:main( ) int a,b,n=0; int f(int x); for(a=200;a=998;a+) if(f(a)=1) b=a+2; if(f(b)=1) n+; printf(“n%d”,n);int f(int x) int i; for(i=2;iy?x:y; return(z); 例 有参函数 int max(int x, y) int z; z=xy?x:y; return(z); 第7页/共57页6.2.2 函数的返回值u返回语句l 形式: return(表达式);l 或 re

5、turn 表达式;l 或 return;l 功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数l 说明: 函数中可有多个return语句 若无return语句,遇时,自动返回调用函数 若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换-函数调用转换 void型函数例 无返回值函数 void swap(int x,int y ) int temp; temp=x; x=y; y=temp; 第8页/共57页 printstar() printf(*);main() int a; a=printstar(); printf(%d,a);例 函数带回不确定值输

6、出:10void printstar() printf(*);main() int a; a=printstar(); printf(%d,a);编译错误!第9页/共57页例 函数返回值类型转换main() float a,b; int c; scanf(%f,%f,&a,&b); c=max(a,b); printf(Max is %dn,c);max(float x, float y) float z; z=xy?x:y; return(z);第10页/共57页6.2.3 函数的调用u调用形式函数名(实参表);n 说明:l 实参与形参个数相等,类型一致,按顺序一一对应l 实

7、参表求值顺序,因系统而定(Turbo C 自右向左)u调用方式n 函数语句: 例: printstar(); printf(“Hello,World!n”);n 函数表达式: 例: m=max(a,b)*2;n 函数参数: 例: printf(“%d”,max(a,b); m=max(a,max(b,c);第11页/共57页u函数说明n 对被调用函数要求:l 必须是已存在的函数必须是已存在的函数l 库函数库函数: #include : #include .hl 用户自定义函数用户自定义函数: : 函数类型说明函数类型说明n 函数声明l 一般形式:一般形式: 函数类型函数类型 函数名函数名( (

8、形参类型形参类型 形参名形参名,. );. ); 或或 函数类型函数类型 函数名函数名();();l 作用:告诉编译系统作用:告诉编译系统函数类型、参数个数及类型,以便检验函数类型、参数个数及类型,以便检验l 函数定义与函数说明不同函数定义与函数说明不同l 函数说明位置:程序的数据说明部分(函数内或外)函数说明位置:程序的数据说明部分(函数内或外)l 下列情况下,可不作函数说明下列情况下,可不作函数说明 若函数返值是若函数返值是charchar或或intint型,系统自动按型,系统自动按intint型处理型处理 被调用函数定义出现在主调函数之前被调用函数定义出现在主调函数之前l 有些系统有些系

9、统( (如如Borland C+)Borland C+)要求函数说明指出函数返值类型和形参类型,要求函数说明指出函数返值类型和形参类型,并且对并且对void void 和和 int int 型函数也要进行函数说明型函数也要进行函数说明第12页/共57页#include void main()float x,y; int n; float power (float x, int n); scanf(%f,%d, &x, &n); y = power(x, n); printf(“%8.2f”,y );float power( float x, int n) int i; floa

10、t t=1; for(i=1; i=n; i+) t = t * x; return t; P76 例6.4 计算x的n次乘方第13页/共57页 C规定:函数定义不可嵌套,但可以嵌套调用函数main( )调用函数a结束a函数b函数调用函数bu嵌套调用第14页/共57页n)!n!(mm!编程求C.例Pnm5677long fac(int k)long f=1; int i; for(i=1;i=n;i+) f=f*i; retrun f;long combination(int n ,int m)long c; int i; c=fac(m)/(fac(n)*fac(m-n) ); retrun

11、 c;main( ) int n,m; long c; scanf(“%d,%d”, &n,&m); c=combination (n,m); prnit(“%ld”, c); 第15页/共57页例 用弦截法求方程根08016523xxxxyf(x)0 x1x2xf(x1)f(x2)()()()(121221xfxfxfxxfxx第16页/共57页求f(x1)与f(x2)连线与x轴的交点x输入x1,x2,求f(x1),f(x2)直到f(x1)与f(x2)异号y=f(x),y1=f(x1)y与y1同号真假x1=xy1=yx2=x直到 |y|y?x:y; return(z); Ch

12、7_0.c例 比较两个数并输出大者main() int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(Max is %d,c);max(int x, int y) int z; z=xy?x:y; return(z);形参实参第18页/共57页u说明:l实参必须有确定的值l形参必须指定类型l形参与实参类型一致,个数相同l若形参与实参类型不一致,自动按形参类型转换函数调用转换l形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放u参数传递方式n 值传递方式l 方式:函数调用时,为形参分配单元,并将实参的值复制到形参

13、中;调用结束,形参单元被释放,实参单元仍保留并维持原值l 特点: 形参与实参占用不同的内存单元 单向传递第19页/共57页711x:y:调用前:调用结束:711x:y:例 交换两个数#include main() int x=7,y=11; printf(x=%d,ty=%dn,x,y); printf(swapped:n); swap(x,y); printf(x=%d,ty=%dn,x,y);swap(int a,int b) int temp; temp=a; a=b; b=temp;调用:711a:b:711x:y:swap:711x:y:117a:b:temp第20页/共57页n 地

14、址传递l 方式:函数调用时,将数据的存储地址作为参数传递给形参l 特点: 形参与实参占用同样的存储单元 “双向”传递 实参和形参必须是地址常量或变量第21页/共57页swap(int *p1,int *p2) int p; p=*p1; *p1=*p2; *p2=p;main() int a,b; scanf(%d,%d,&a,&b); printf(“a=%d,b=%dn”,a,b); printf(“swapped:n”); swap(&a,&b); printf(”a=%d,b=%dn,a,b);例 交换两个数a59b调前:a59b调swap:p1&

15、;a&bp2a95b交换:p1&a&bp2a95b返回:第22页/共57页例:参数传递的区别举例 (等级考试考题)#include sub(int x,int y,int *z) *z=y-x; main() int a,b,c; sub(10,5,&a); sub(7,a,&b); sub(a,b,&c); printf(“%4d,%4d,%4dn”,a,b,c);程序的运行结果是( B )A5,2,3 B-5,-12,-7 C-5,-12,-17 D5,-2,-7第23页/共57页6.3 函数的递归调用f( )调f调f2调f1f1( )f2(

16、 )u说明lC编译系统对递归函数的自调用次数没有限制l每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出int f(int x) int y,z; z=f(y); . return(2*z);int f1(int x) int y,z; z=f2(y); . return(2*z);int f2(int t) int a,c; c=f1(a); . return(3+c);u定义:函数直接或间接的调用自身叫函数的递归调用第24页/共57页例 求n的阶乘) 1()!1() 1 , 0(1!nnnnn#include int fac(int n

17、) int f; if(n0) printf(n0,data error!); else if(n=0|n=1) f=1; else f=fac(n-1)*n; return(f);main() int n, y; printf(Input a integer number:); scanf(%d,&n); y=fac(n); printf(%d! =%15d,n,y);第25页/共57页例:兔子问题: 第1个月有1对兔子 过2个月,兔子就可每个月生1对兔子 问第n个月有多少对兔子? 分析: 设第n个月有f(n)对兔子 根据题意有 f(0)=0, f(1)=1 f(n)= f(n-1)

18、 + f(n-2) f(n-1): 前一个月的兔子数 f(n-2): 本月生的兔子数 第26页/共57页long f(int n ) switch (n ) case 0: return 0; break ; case 1: return 1; break ; default: return f(n-1) + f(n-2); void main() long f(int n ); int n; printf(“n input n:”);scanf(“%d”,&n); printf(“n f(%d)=%ld”,n, f(n) ); 第27页/共57页P82 例6.9辗转相除法求最大公约数

19、 求 m和 n 的公约数算法 if (m % n) = 0 n 是公约数; else 求 n 和 m % n 的公约数; int gcd(int m, int n) if (m % n) = 0 return n ; else return gcd(n, m % n); void main() int m,n,t;int gcd(int m, int n);scanf(“%d %d”,&m,&n);if (m0 第28页/共57页例 Hanoi问题void move(char getone, char putone) printf(%c-%cn,getone,putone);

20、void hanoi(int n,char one,char two,char three) if(n=1) move(one,three); else hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three); main() int m; printf(Input the number of disks:); scanf(%d,&m); printf(The steps to moving %3d disks:n,m); hanoi(m,A,B,C);ABC第29页/共57页例:下面程序执行时,如果输入字符序列

21、ABCDE!运行结果是( ) (递归调用知识点等级考试考题)void reverse() char c; c=getchar(); if(c=!)prinf(“%c,c); else reverse(); printf(c,c); #include void main() void reverse(); reverse();第30页/共57页6.4 变量的作用域与存储方式6.4.1变量的作用域-即变量的有效范围变量按作用域分为全局变量和局部变量第31页/共57页u局部变量-内部变量 在函数内定义,只在本函数内有效u说明lmain中定义的变量只在main中有效l不同函数中同名变量,占不同内存单元

22、l形参属于局部变量l可定义在复合语句中有效的变量l局部变量可用存储类型:auto register static (默认为auto)float f1(int a) int b,c; .char f2(int x,int y) int i,j; main() int m,n; .a,b,c有效x,y,i,j有效m,n有效例 不同函数中同名变量main() int a,b; a=3; b=4; printf(main:a=%d,b=%dn,a,b); sub(); printf(main:a=%d,b=%dn,a,b);sub() int a,b; a=6; b=7; printf(sub:a=%

23、d,b=%dn,a,b);例 复合语句中变量#define N 5main() int i; int aN=1,2,3,4,5; for(i=0;iN/2;i+) int temp;temp=ai;ai=aN-i-1;aN-i-1=temp; for(i=0;iN;i+) printf(%d ,ai);运行结果:5 4 3 2 1例 复合语句中变量#define N 5main() int i; int aN=1,2,3,4,5; for(i=0;iN/2;i+) int temp;temp=ai;ai=aN-i-1;aN-i-1=temp; for(i=0;i第33页/共57页 如果在全局变

24、量定义之前的函数想引用该外部变量,则应该在该函数中用关键字externextern作“外部变量说明”。第34页/共57页#include int a=123;void main() extern a,b; printf(%dt%dn,a,b); /123,456 int a=3,b=2,c=l; c-=+b; b*=a+c; printf(%dt%dt%dn,a,b,c); /3,3,-2 int b=5,c=12; c/=b*2; a-=c; printf(%d,%d,%dn,a,b,c); /2,5,1 a+=-c; printf(“%dt%dn”,a,b); /123,456 int b

25、=456; 变量作用域知识点等级考试典型考题分析-例1.程序的输出结果是 ( ) 第35页/共57页变量作用域知识点等级考试典型考题分析-例2.程序的输出结果是 ( 5,25 ) #include int x,y,a=15,b=10; void num() x=a-b; y=a+b; void main() int a=7,b=5; x=x+a; y=y-b; num(); printf(“%d,%dn”,x,y); 第36页/共57页变量作用域知识点等级考试典型考题分析-例3.程序的输出结果是 ( 4,5 ) #include int x=1,y=4,z=2; int min(int x,i

26、nt y) int z; z=xy?x:y; return(z); main() int x=5,z=6,i=0; while(i2) printf(“%d”,min(x,min(y,z); i+; y+=2; 第37页/共57页#include int x=l2,y=7;void main() int x=15,z; z=x-y+; int y,z; while(y=x-) y/=3; if(y%3=0) z=(+y); break; printf(“d,d,n”,x,y,z); printf(“d,d,dn”,x,y,z); #includeextern int j=1;void main

27、() void add(); int sum(int x); int k,s; add(); j+; printf(“j=%dn”,j); for(k=1;k=10;k+) s=sum(k); printf(“s=%dn”,s); void add() int j=0; j+; int sum(int j) int x=0; x+=j; return(x); 思考以下两题 (03年1次)10,4,410,8,82,10第38页/共57页1.变量按存在时间分: 静态变量 和动态变量静态存储类型的变量的生存期为程序执行的整个过程,在该过程中占有固定的存储空间,通常称它们为永久存储。动态存储类型变量

28、只生存在某一段时间内。例如,函数的形参和函数体或分程序中定义的变量, 只是在程序进入该函数或分程序时才分配存储空间, 当该函数或分程序执行完后,变量对应的存储空间又被撤销了。2.c语言中每一个变量有两个属性:数据类型,存储特性 完整的变量定义: 存储特性 数据类型 变量名;6.4.2 变量的存储特性第39页/共57页3.变量的存储特性 自动型 auto 静态型 static 寄存器型 register 外部型 extern(1) auto型每次进入程序是自动分配内存,不长期占用内存例如:形式参数,自动型局部变量(2)static 型 局部静态变量 全局静态变量 长期占用内存第40页/共57页例

29、例1 1:分析执行结果f(int a)int b=0; static int c=3; b+;c+; printf(“%5d%5d%5d”,a,b,c); return(a+b+c);main() int a=2,k; for(k=0;k3;k+) printf(“%5dn”,f(a);静态变量只初始化一次结果:2 1 4 (a,b,c) 7 (f(a)2 1 5 82 1 6 9第41页/共57页(3) register型将使用频率高的变量定义为register型,可以提高运行速度. 数据内存 运算器 运算器 结果 控制器 数据寄存器寄存器变量只限于整型、字符型、指针型的局部变量。寄存器变量

30、是动态变量,而且数目有限, 一般仅允许说明两个寄存 器变量。例如: register int d; register char c;第42页/共57页(4) extern型l引用: extern 类型 变量名;l如果某个模块文件中要用到另一个模块文件中的全局变量,就要用externextern说明例如: :程序模块file1.cfile1.c中定义了全局变量 int s ;int s ;而在另一个程序模块file2.cfile2.c中的函数fun1( )fun1( )中需要使用这个变量s s。为此,可以在file2.cfile2.c的函数fun1( )fun1( )中加上外部变量说明语句: :

31、 fun1( )fun1( ) extern int s;/ extern int s;/* *表明变量s s是在其他文件定义的* */ / l定义时分配内存, ,其他文件引用时不再分配内存. .第43页/共57页变量存储属性知识点等级考试典型考题分析-例1.程序的输出结果是 ( ) main() int i; for(i=0;i2;i+) add(); add() int x=0; static int y=0; printf(“%d,%dn”,x,y); x+;y=y+2; 0,00,2第44页/共57页变量存储属性知识点等级考试典型考题分析-例2.程序的输出结果是 ( 30 ) #inc

32、lude void main() int f(int n); int i,k,s=0; for(i=1;i100) break; s=s+k; printf(“%d”,s); int f(int n) static int f=1; f=f*n; return f; 第45页/共57页第七章 编译预处理u作用:对源程序编译之前做一些处理,生成扩展C源程序u种类l 宏定义 #definel 文件包含 #includel 条件编译 #if-#else-#endif等u格式:l “#”开头l 占单独书写行l 语句尾不加分号6.5 编译预处理第46页/共57页如如 if(x=YES) printf(“

33、correct!n”); else if (x=NO) printf(“error!n”);展开后:展开后: if(x=1) printf(“correct!n”); else if (x=0) printf(“error!n”);6.5.1 宏定义u不带参数宏定义l 一般形式: #define 宏名 宏体l 功能:用指定标识符(宏名)代替字符序列(宏体)l 宏展开:预编译时,用宏体替换宏名-不作语法检查如如 #define YES 1 #define NO 0 #define PI 3.1415926 #define OUT printf(“Hello,World”);宏体可缺省,表示宏名定

34、义过或取消宏体l 定义位置:任意(一般在函数外面)l 作用域:从定义命令到文件结束l #undef可终止宏名作用域 格式: #undef 宏名例例 #define YES 1 main() . #undef YES #define YES 0 max() . YES原作用域YES新作用域l 宏定义可嵌套,不能递归例例 #define MAX MAX+10 ( )l 引号中的内容与宏名相同也不置换例例 #define PI 3.14159 printf(“2*PI=%fn”,PI*2);宏展开:宏展开:printf(“2*PI=%fn”,3.14159*2);l 宏定义中使用必要的括号()例例

35、#define WIDTH 80 #define LENGTH WIDTH+40 var=LENGTH*2;宏展开:宏展开:var= 80+40 *2;( )( )例例 #define WIDTH 80 #define LENGTH WIDTH+40 var=LENGTH*2;宏展开:宏展开:var= 80+40 *2;第47页/共57页u带参数宏定义l 一般形式: #define 宏名(参数表) 宏体例例 #define S (r) PI*r*r相当于定义了不带参宏相当于定义了不带参宏S,代表字符串代表字符串“(r) PI*r*r” l 宏展开:形参用实参换,其它字符保留l 宏体及各形参外一

36、般应加括号()例 #define S(a,b) a*b . area=S(3,2);宏展开: area=3*2;不能加空格例例 #define POWER(x) x*x x=4; y=6; z=POWER(x+y);宏展开:宏展开:z=x+y*x+y;一般写成:一般写成: #define POWER(x) (x)*(x)宏展开:宏展开: z=(x+y)*(x+y);第48页/共57页#define MAX(x,y) (x)(y)?(x):(y) .main() int a,b,c,d,t; . t=MAX(a+b,c+d); 宏展开:宏展开:t=(a+b)(c+d)?(a+b):(c+d);int max(int x,int y) return(xy?x:y);main() int a,b,c,d,t; . t=max(a+b,c+d

温馨提示

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

评论

0/150

提交评论