8函数(1).ppt_第1页
8函数(1).ppt_第2页
8函数(1).ppt_第3页
8函数(1).ppt_第4页
8函数(1).ppt_第5页
已阅读5页,还剩73页未读 继续免费阅读

下载本文档

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

文档简介

1、2020/8/6,1,第七章 函数,武汉理工大学计算机学院,2020/8/6,2,第七章 函数,7.1 函数的概念 7.2 函数的定义 7.3 函数的调用和函数的返回值 7.4 函数应用实例 7.5 嵌套调用和递归调用 7.6 变量的作用域和存储类别 7.7 内部函数和外部函数(*) 7.8 编译预处理,函数小结,2020/8/6,3,7.1函数的概念,#include void stars(int n); void print_message( ); main( ) stars(20); print_message( ); stars(20); void stars(int n) int i

2、; for (i=1; i=n; i+) putchar(*); putchar(n); void print_message( ) printf(How do you do!n); ,函数stars( )、 print_message( )的声明,/*main函数的定义*/,stars( )、print_message( )函数调用,定义stars( )函数,定义print_message( )函数,程序运行后输出结果为:,2020/8/6,4,C 程序结构,2020/8/6,5,说明 :,C是函数式语言 一个C程序有且只能有一个名为main的主函数。 所有的函数都是互相独立的,除main函

3、数不能调用外,其它函数可以互相调用。 函数 库函数(标准函数) 自定义函数,2020/8/6,6,7.2 函数的定义,类型说明符 函数名(形参说明表) 说明部分 语句部分 ,说明函数返回值的数据类型; 若缺省,则为 int 类型; 若函数无值,则定义为 void 类型,由用户自己命名, 合法的标识符,说明参数的个数和类型,说明函数中用到的除形参以外的其它变量等,为了完成函数特定的功能而设计的一个或多个语句,特殊情况: 空函数 : Function( ) ,2020/8/6,7,函数定义实例,打印一行 n 个* void stars(int n) int i; for (i=1; i=n; i+

4、) putchar(*); putchar(n); ,求整数x的n次幂(n0) long power(int x, int n) int i; long mul=1; for (i=1; i=n; i+) mul=mul*x; return(mul); ,传统的定义风格,2020/8/6,8,传统的函数定义形式,long power(x, n) int x, n; int i; long mul=1; for (i=1; i=n; i+) mul=mul*x; return(mul); ,2020/8/6,9,7.3 函数的调用和函数的返回值,7.3.1 函数的参数 7.3.2 函数的返回值

5、7.3.3 函数的声明 7.3.4 函数的调用,2020/8/6,10,7.3.1 函数的参数,形式参数: 函数定义时所使用的参数称为形式参数。形参可以是:变量或数组名。 实际参数: 函数调用时所使用的参数称为实际参数。实参可以是:具有确切值的常量、变量、表达式或数组名。,2020/8/6,11,int max(int x, int y); void main( ) int a, b, c; scanf(%d%d, ,形参只能是变量或数组名,int max(int x, int y),c=max(a, b),实参可以是常量、变量、表达式或数组名,但要求它们有确定的值 如: c=max(10,

6、(a+b)/2); 实参与形参之间:个数一致,类型一致或赋值兼容,顺序一致。,形参:变量,值,2020/8/6,12,7.3.2 函数的返回值,返回语句(return语句): 格式: return(表达式) ; 或 return 表达式; 或 return; 功能:将流程及表达式的值从被调用函数返回到函数的调用处。 说明:,int max(int x, int y) int z; z=(xy)?x:y; return(z); ,若return后面带表达式,首先计算表达式的值,表达式的值就是所求的函数值。,return z ;,return(xy)?x:y);,2020/8/6,13,说明(续)

7、,一个函数体内可以有多个或没有return语句;,int max(int x, int y) int z; if(xy) return(x); else return(y); ,void output(int m) printf(”%d”,m); return; ,若return后面没有表达式,或没有return语句,则可能会返回不定值。,output(int m) printf(”%d”,m); return; ,/*默认为int类型函数*/,void: 空类型,2020/8/6,14,说明(续),int fun1(int m) x=11.9; return(x/2); ,若return的表

8、达式值的类型与函数的类型不一致时,以函数定义的类型为准。,x/2,5.95,11.9/2,函数fun1的返回值: 5,float fun2(int k) return(20); ,函数fun2的返回值?,2020/8/6,15,7.3.3 函数的声明,/*对库函数的声明*/ #include /*对自定义函数的声明*/ void stars(int n); void print_message( ); main( ) /*主函数*/ stars(20); print_message( ); stars(20); ,/*自定义函数*/ void stars(int n) int i; for (

9、i=1; i=n; i+) putchar(*); putchar(n); void print_message( ) printf(How do you do!n); ,2020/8/6,16,函数声明的一般形式: 函数类型 函数名( 类型名 形参1, 类型名 形参2,) 包含参数和返回值类型的函数声明称为函数原型。 函数类型 函数名(类型名, 类型名, ) 若有函数: float fun(double a, int b, float c) 则可有函数声明: float fun(double a, int b, float c); float fun(double, int, float);

10、 float fun( );,说明:,2020/8/6,17,说明(续):,如果函数的值是 int 或 char 型,可以不必进行声明,系统自动按 int 型声明。,如果被调用函数出现在主调函数之前,可以不必进行声明。,#include main( ) int a, b, c; scanf(%d%d, ,int max(int x, int y) int z; z=xy?x:y; return(z); ,2020/8/6,18,说明(续):,如果已在所有函数定义之前,在函数的外部已作了函数声明,则在各个主调函数中不必对所调用的函数再做声明。,2020/8/6,19,7.3.4 函数的调用,调用

11、的一般形式: 函数名(实参1,实参2,) 说明: 若调用无参函数,则无实参表列,但括弧不能省略; 如果实参表列包含多个实参,则各参数间用逗号隔开; 实参与形参的个数应相等,类型应一致或赋值相容; 实参与形参按顺序一一对应传递数据;,2020/8/6,20,调用方式 函数语句:由函数调用加上分号构成,在主调函数中可作为一个独立的语句。如: stars(20); 或 printf(”C program”); 函数表达式:函数调用作为一个运算对象出现在表达式中,此时要求函数带回一个确定的值以参加表达式的运算。 如: c=mysqrt(a); 函数参数:函数调用作为另一个函数的实参,其值作为一个实际参

12、数传给被调函数的形参进行处理;此时也要求函数带回一个确定值。如: m=max(a, max(b, c); printf(%d, max(a, b) );,2020/8/6,21,调用过程 float add( ); main( ) float a,b,c; scanf(”%f,%f ”, ,调用,流程从主调函数转移到被调用函数,且实参将值传给对应的形参; 执行被调用函数; 流程从被调用函数返回到主调函数,并返回函数值。,6,15,6,15,21,sum is 21.0,2020/8/6,22,调用过程 float add( ); main( ) float a,b,c; scanf(”%f,%

13、f ”, ,6,15,10,17,17,27,11,18,29,29,形参: 变量,实参: 常量 变量 表达式,值,10,2020/8/6,23,7.4 函数应用实例,例7.1 求累加和 sum=1!+2!+10! 分析:可以编写一个求阶乘的函数fac(n)计算n! 实现: long fac(int n);,main( ) int i; long sum=0; for(i=1;i=10;i+) sum+=fac(i); printf(”nsum=%ld”,sum); ,long fac(int n) int i; long x=1L; for(i=1;i=n;i+) x*=i; return(

14、x); ,2020/8/6,24,例7.2 由键盘输入x、y及z的值,计算函数 sin(x) sin(y) sin(z) func(x,y,z)= + + sin(x-y)sin(x-z) sin(y-z)sin(y-x) sin(z-x)sin(z-y),分析: 可以定义一个函数part(x,y,z)求每加项的值 另外定义一个度与弧度之间的转换函数change(x) 主函数中 以度为单位输入x、y及z的值,并转换为弧度; 多次调用part( )函数求出func的值 输出func的值,2020/8/6,25,sin(x) sin(y) sin(z) func(x,y,z)= + + sin(x

15、-y)sin(x-z) sin(y-z)sin(y-x) sin(z-x)sin(z-y),#include /* 对sin()函数进行说明 */ double change(float x); /*对自定义函数进行说明*/ double part(float x,float y,float z); main( ) /*主函数*/ float x,y,z,sum; scanf(”%f%f%f”, ,2020/8/6,26,sin(x) sin(y) sin(z) func(x,y,z)= + + sin(x-y)sin(x-z) sin(y-z)sin(y-x) sin(z-x)sin(z-y

16、),double change(float x) /* 角度单位转换:度-弧度*/ return(x*3.14159/180); ,double part(float x,float y,float z); float tmp; tmp=sin(x)/sin(x-y)/sin(x-z); return(tmp); ,2020/8/6,27,7.5 函数的嵌套调用和递归调用,7.5.1 函数的嵌套调用 7.5.2 函数的递归调用,2020/8/6,28,7.5.1 函数的嵌套调用,语言的函数定义都是互相平行的、独立的,即不允许嵌套定义函数;但是,可以嵌套调用函数,即程序在调用一个函数的过程中,该

17、被调函数又可以调用其它函数。 如:,main函数,调用a函数,a函数,调用b函数,b函数,结束,2020/8/6,29,2020/8/6,30,n m!例7.1 求组合数 C = m n! * (m-n)!,long cmn(int m, int n);,long cmn(int m, int n) long x; x=fac(m)/fac(n)/fac(m-n); return(x); long fac(int n) long x=1L; while(n=1) x*=n-; return(x); ,/* 求组合数 */,/* 求阶乘n! */,main( ) int m,n; long c;

18、 printf(”n输入两整数: ”); scanf(”%d%d”, ,long fac(int n);,调用过程,2020/8/6,31,调用过程,main函数,调用cmn函数,cmn(m,n),调用fac函数,fac(m),调用fac函数,fac(n),调用fac函数,fac(m-n),结束,2020/8/6,32,7.5.2 函数的递归调用,概念:定义一个函数时,在函数体内直接或间接地调用了自身,则称为函数的递归调用。,int f(int x) int y, z; z=f(y); return(z*z); ,直接递归,间接递归,2020/8/6,33,递归的两个方面: 递归的一般形式 递

19、归的结束条件,如: n! 递推形式: n!=12n 递归形式:,long f(int n) long y; if (n=0) y=1; else y=f(n-1)*n; return(y); ,main( ) int n; printf(ninput n(n0):); scanf(%d, ,运行过程演示,2020/8/6,34,main( ) n=5; print(f(5); ,long f(5) long y; y=5*f(4); ,long f(4) long y; y=4*f(3); ,long f(3) long y; y=3*f(2); ,long f(3) long y; y=3*

20、f(2); ,long f(2) long y; y=2*f(1); ,long f(1) long y; y=1*f(0); ,return(1);,return(2);,return(6);,return(6);,return(24);,return(120);,long f(0) long y; y=1; ,return(1);,调用过程,2020/8/6,35,7.6 变量的作用域和存储类别,7.6.1 变量的作用域 7.6.2 变量的存储类别 7.6.3 小结,2020/8/6,36,7.6.1 变量的作用域,变量的作用域:是指在程序中不同位置所定义的变量,其变量起作用的区域。 根据

21、变量起作用的范围,变量可分为: 局部变量:在函数内部或复合语句中定义的变量,也称为内部变量。其作用域仅在所定义的函数或复合语句中。 全局变量:在所有函数外部定义的变量,也称为外部变量。其作用域从定义位置开始到其所在 的源文件结束。,2020/8/6,37,1. 局部变量,main() int j,x, c; int c; c=j%2; ,int f1(int a) int v1, x; int f2( ) int v2, x, y; ,2020/8/6,38,例,void f( ) int a =1; printf(n1.a=%d, a ); main( ) int a =10, i; f(

22、); for(i=1;i=2;i+) int a =50; a +; printf(n2.%d:a=%d, i, a ); printf(n3.a=%d, a ); ,1,1,2,2,3,3,3,程序运行结果为:,1.a=1,1,51,2.1:a=51,2,50,51,2.2:a=51,3,3.a=10,2020/8/6,39,2. 全局变量,#include int p=1, q=5; main( ) int m,n; float f1(int a) int b, c; char c1, c2; char f2(int x, int y) int i, j; . ,p, q 的作用范围,c1

23、, c2的作用范围,2020/8/6,40,说明,全局变量增加了函数间的数据联系 尽量少使用全局变量(除非在必要时),int k; void show( ) printf(n2.k=%d,k); k=9; main( ) k=2; show( ); printf(n1.k=%d,k); ,运行结果:,2.k=2 1.k=9,2020/8/6,41,说明(续),若全局变量与局部变量同名,则在局部变量的作用范围内,全局变量不起作用,int a=3, b=5; int max(int a ,int b ) int c; c=a b ? a : b; return(c); main( ) int a

24、=10; printf(%d, max(a ,b) ); ,形参a、b的作用域 全局变量a、b不起作用,局部变量a的作用域 全局变量a不起作用,运行结果为:,10,2020/8/6,42,说明(续),可以用extern作外部变量声明,扩大全局变量的作用域,void f1( ) extern int c; extern int b; void f2( ) main( ) extern int a; int a=8,b=-2,c=15;,a b c,注意: extern int b=1; ,2020/8/6,43,7.6.2 变量的存储类别,存储空间的划分,程序区:用于存放程序编译后形成的可执行代

25、码(执行时装入) 静态存储区:用于存放程序中的静态数据,如全局变量等 动态存储区:用于存放程序中的动态数据,如函数形参、局部变量、函数调用时的现场保护和返回地址等,静态数据:说明时在静态存储区中分配存储单元并在程序执行过程中始终占用该单元,直到程序结束才释放; 动态数据:在函数开始执行时分配动态存储空间,函数结束时释放这些空间。 的存储类别有四种:auto、static、register和extern。,2020/8/6,44,void f(int c); main( ) register int i; /* i:局部寄存器变量*/ for (i=1; i=3; i+) f( i ); voi

26、d f(int c) auto int a=0; /*a:局部自动变量,int a=0; */ static int b; /*b:局部静态变量,static int b=0;*/ a+; b+; printf(%d: a=%d, b=%dn, c, a, b); ,局部变量的存储属性,自动的(auto)、静态的(static)、寄存器的(register),存放在动态存储区,存放在静态存储区,存放在寄存器中,无地址,2020/8/6,45,寄存器变量说明,为了减少从内存中存取变量值的时间,语言允许将局部变量的值放在寄存器中;用关键字register声明。 int fac(int n) reg

27、ister int i, f=1; for (i=1; i=n; i+) f=f * i; return( f ); 不能定义太多的寄存器变量,因为寄存器数量有限,太多无效(将自动按自动变量处理) 寄存器无地址,因此: static int b=0; a+; b+; printf(n%d: a=%d, b=%d, n, a, b); main( ) register int i; for (i=1; i=3; i+) f( i ); ,1,1,1:a=1, b=1,2,2,2,3,3:a=1, b=3,2:a=1, b=2,0,1,3,0,1,3,4,程序结束,2020/8/6,47,局部静态

28、变量 说明,函数编译时在静态存储区分配存储单元,函数调用结束后不释放存储单元,即在整个程序的运行中不释放存储单元。用static声明该变量为“局部静态变量” 若对变量赋初值,对于静态变量,只执行一次,再次调用函数时不再赋初值而保留上次函数调用结束时的值;而对于自动变量,每次调用都要重新分配内存单元并赋初值 若不对变量赋初值,对于静态变量系统自动赋缺省值;而对于自动变量,只分配存储单元,其值不确定 虽然静态局部变量在函数调用结束后仍占存储单元,但由于是局部变量,其它函数不能引用它,2020/8/6,48,全局变量的存储方式,全局变量是在函数外部定义的,存放在静态存储区,在程序的整个运行过程中占用

29、存储单元,生存期为整个程序的运行期间,2020/8/6,49,int c; void f(int n) int a=0; a+; c+; printf(n%d: a=%d, c=%d, n, a, c); main( ) int i; for (i=1; i=3; i+) f( i ); c+; printf(nc=%d,c); ,1,1,1,1:a=1, c=1,2,2,2,0,1,3,2:a=1, c=3,4,3,3,0,1,5,3:a=1, c=5,6,c=6,4,程序结束,2020/8/6,50,7.6.3 存储类别小结,1、数据的两种属性:,数据类型,存储类别,auto float

30、a;,static int b;,register char c;,extern int d;,(声明变量是已定义的变量),2、从作用域分:,局部变量,全局变量,自动变量,静态局部变量,寄存器变量,形参,静态全局变量,非静态全局变量,2020/8/6,51,3、从生存期分:,动态存储,静态存储,自动变量,寄存器变量,形参,静态局部变量,静态全局变量,非静态全局变量,4、从存放位置分:,内存的静态存储区:,内存的动态存储区:,CPU中的寄存器:,静态局部变量,静态全局变量,外部变量,自动变量,形参,寄存器变量,2020/8/6,52,变量存储类型,局部变量默认为auto型 register型变量

31、个数受限,且不能为long, double, float型 局部static变量具有全局寿命和局部可见性 局部static变量具有可继承性 extern不是变量定义,可扩展外部变量作用域,2020/8/6,53,外部变量的说明:,(动态)内部变量的说明:,静态外部变量的说明:,static 类型名 变量名;,extern 类型名 变量名;,auto 类型名 变量名;,靜态内部变量的说明:,static 类型名 变量名;,变量存储类的说明(定义)方式:,在 函 数 外,在 函 数 内,2020/8/6,54,变 量 的 存 储 类 别,静 态 存 储 类,动 态 存 储 类,外 部 变 量,静态

32、外部变量,静态内部变量,自动变量,寄存器变量,形式参数,静 态 变 量,离开函数 其值消失,允许其它文件引用 在引用它文件中 用extern作说明,离开函数其值保留,只限本文件引用 但应先定义后引用, 否则须作声明: extern 类型符 变量名;,全 局 量,局 部 量,在函数外定义,其值永久保留,只限本函数或 本复合语句中 使用。,在函数或复合 语句内定义。,在cpu中分配 临时空间。,动态内部变量,2020/8/6,55,8.6 函数的存储类别,语言允许一个大程序分成若干个程序单元,编译成若干个源程序文件。 1. 主文件与外部文件 语言把由若干个源文件组成的文件中含有主函数程序单元的文件

33、,称为程序的主文件。 把由若干个源文件组成的文件中不含有主函数程序单元的文件,称为外部文件。 外部文件中函数将直接或间接地被主函数进行调用。,2020/8/6,56,2. 函数的内部调用与外部调用 当一个源程序由多个源文件组成时,语言根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。 (1)函数的内部调用,所谓内部调用是指同一个文件内函数之间的调用。 (2)函数的外部调用,所谓外部调用是指一个文件中的函数调用另一个文件的函数。,2020/8/6,57,3.内部函数(又称静态函数) 如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这

34、种函数称为内部函数。 定义一个内部函数如下: static 函数类型 函数名( 函数参数表 ) 函数体语句 static的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。 使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。,2020/8/6,58,4.外部函数 外部函数在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数. 外部函数定义形式为 : extern 函数类型 函数名(函数参数表) /*函数体语句*/ 调用外部函数时,需要对其进行说明: extern 函数类型

35、 函数名(参数类型表) ,函数名2(参数类型表2);,2020/8/6,59,例8.19 外部函数应用举例。 (1)文件mainf.c main() extern void input(); extern void process(), output(); input(); process(); output(); (2)文件subf1.c extern void input() /*定义外部函数*/ (3)文件subf2.c extern void process() /*定义外部函数*/ (4)文件subf3.c extern void output() /*定义外部函数*/,2020/8

36、/6,60,例8.20 程序由两个源文件组成。 c1.c中的主函数功能为从键盘读取两个整数并赋给变量i和j,在调用sum(),在c1.c中,将sum()原型说明为extern。 在源文件c2.c中,将i、j和sum()说明为extern; 程序如下: /* file c1.c */ #include extern int sum(); /* 外部函数原型 */ int i,j; /* 全局变量 */,2020/8/6,61,main() int x; printf(“Enter two numbers: “); scanf(“%d%d”, ,2020/8/6,62,7.7 内部函数和外部函数,

37、2020/8/6,63,函数小结:,2020/8/6,64,如:stdio.h用于标准输入/输出,math.h用于数学计算,ctype.h用于字符处理,string.h用于字串处理,time.h 用于时间/日期的处理,dir.h 用于控制目录和路径,graphics.h用于图形操作,dos.h,bios.h,用于接口处理,2020/8/6,65,7.8 编译预处理,7.8.1 宏定义预处理命令 7.8.2 文件包含预处理命令 7.8.3 条件编译预处理命令,2020/8/6,66,7.8.1 宏定义预处理,宏定义分无参宏定义和有参宏定义; 无参宏定义的一般格式 #define 标识符 字符序列

38、 如: #define PI 3.1415926 作用:用标识符(称为“宏名” PI )代替字符序列(3.1415926)。 说明 (1)宏名一般用大写字母表示,以示与变量区别。但这并非是规定。 (2)宏定义是用宏名代替字符序列,宏展开时仅作简单替换,不检查语法。,2020/8/6,67,例如:,#define YES 1 #define NO 0 main( ) int x; if (x=YES) printf(“%dn”,YES); else if (x=NO) printf(“%dn”,NO); ,main( ) int x; if (x=1) printf(“%dn”,1); else if (x=0) printf(“%dn”,0); ,经过编译预处理后,程序中的宏名被宏体替换,得到如下的源程序:,比较: #define M 20+30 或 #define M 50,t=m*2; t的值?,2020/8/6,68,说明(续),(3)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。 (4) 在进行宏定义时,可以引用已定义的宏名 。如: #define M 10 #define N 2*M (5) 对双

温馨提示

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

评论

0/150

提交评论