c语言教程 (8).ppt_第1页
c语言教程 (8).ppt_第2页
c语言教程 (8).ppt_第3页
c语言教程 (8).ppt_第4页
c语言教程 (8).ppt_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

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

文档简介

1、2020年8月2日星期日12时1分10秒,第八章函数,江苏大学计算机学院 计算机科学系,本章教学要求、重点与难点,函数的定义方法,类型 和返回值; 函数的正确调用; 形参与实参、参数值的传递; 函数的正确调用、嵌套调用、递归调用; 局部变量与全局变量; 变量的存储类别(自动的、静态的、寄存器的、外部的); 内部函数与外部函数,重点与难点 1. 函数的定义、调用 2. 函数的递规调用 3、全局变量和局部变量 4、静态存储变量,概述 函数定义的一般形式 函数的参数和函数的值 函数的调用 函数的嵌套调用 函数的递归调用 数组作为函数的参数 局部变量和全局变量 变量的存储类别 内部函数和外部函数 作业

2、 小结,第八章 函数,求 n! . for (s=1 , i=1;i=n; i+) s*= i;,m! ,n! (m-n)! ?,8.1 概述,*新课引入:,#include stdio.h main() long fac( ); int m,n; long f1,f2; scanf(%d,%d, ,long fac( int k) int i; long f=1; for(i=1;i=k;i+) f*=i; return (f); ,函数是程序的基本单位: 程序可由任意一个主函数和若干个子函数构成,main,a,e,b,c,d,f,h,h,g,g,e,i,下图是一个程序中函数调用的示意图:,

3、主函数,在第一章就已了解了函数的定义形式、引用方式 及程序执行起点,print_star ( ) / * print_star 函数 * / printf ( * * * * * * * * n ) ; ,main ( ), print_star ( ); / * 调用 print_star 函数 * /,print_message ( ); / * 调用 print_message 函数 * /,print_star ( );/*调用 print_star 函数 */,print_message ( ) /* print_message 函数 */ printf ( How do you d

4、o ! n ); ,例,运行结果如下: * * * * * * * * How do you do ! * * * * * * * *,执行过程如下:,main,调用print_star( ),结束,进入print_star( ),print_message( ),返回,输出一排 *,调用print_star( ),print_message( ),How do you do !,返回,说明:,一个源程序文件由一个或多个函数组成。 一个C程序由一个或多个源程序文件组成 C程序的执行总是从main 函数开始 所有函数是平行的,不能嵌套定义,8.2函数定义的一般形式,.按使用 分类:,标准函数:库

5、函数;,自定义函数:用户自己定义说明,专门的、特殊的;,.按形式 分类:,无参函数:如 main()由系统调用!,有参函数:定义时有及说明,引用时对应实参表;,一、分类:,二、定义:,函数定义的一般形式如下: 类型说明符 函数名(形参表) 说明部分; 语句部分(函数体部分) ,说明: 1. 函数名的命名规则同变量一样,应“见名知意”。 2. 形式参数是用于在调用函数和被调用函数之间进行数据传递的,因此也须进行类型说明,例: catt(int i ,int j ,float x) . 也可另起一行进行说明;如 catt(i,j,x) int i,j; float x; . ,3. 由花括号括起来

6、的部分称为函数体,由说明部分和语句部分组成。说明部分用来说明函数内所使用的变量类型以及所调用的函数的类型;语句部分是实现函数功能的核心部分,由C语言的基本语句组成。 4. 当函数有返回值时,在函数名前应加上返回值的类型说明符。,.无参: ( ) ,.有参: ( ) ,.空函数: ( ) 即无,用于预先留空档,便于扩展,或从粗到细逐步求精的程序设计,三、三种常见函数的定义形式,一、.形参与实参:,例8.2求二个数最大者,main ( ) int a,b,c; scanf ( %d,%d , ,运行情况如下: 7 ,8 Max is 8,执行过程如下:,求出b, 赋给 y 求出a, 赋给x,求出z

7、值赋给c,main ( ),结束,调用max(a,b),打印Max is, c,读入a, b,8.3函数的参数和函数的值,注意:, 形参:调用执行时临时分配的存贮单元,调用返回时自动释放;, 实参:可以是(常量、变量或表达式)或函数引用而形参不行!, 传递(结合)方式:“值传递” “单向传递”, 形参与实参的类型应一致,调用,形参的变化不会影响实参, 调用函数,由函数名所得的值;利用 return( ) 实现。, 若无需返回值则 return 省略;, 圆括号可省略:returnz;, 类型:隐含地不加类型说明时当成整型, 若没有 return 则返回一个无用(不确定)的值, 但仍可以当成表达

8、式调用!,二、.函数的返回值, 为了明确地表示“不带回值” 可以用 “ void”定义“无类型”(或“空类型”),8.4函数的调用,一、调用的一般形式:,调用无参函数时:,实参与形参一一对应:,函数名(实参表列),函数调用的一般形式是:,实参表列可以没有,但()不能省略,实参与形参按顺序对应,一一传递数据,说明:对实参求值的顺序并不是确定的, 1. 有的系统按自左到右, 2. 有的(TC)按自右到左,例:若将调用max(a,b)改为max(a,a+=b),其结果如何?,小心!,实参表中,尽量不要有赋值,或自增减。,main ( ) int a,b,c; scanf ( %d,%d , , 函数

9、语句;printstar( ); 表达式; c=2*max(a,b); 实参 m=max(c,max(a,b);,三、.被调函数的说明:,使用(调用)库函数时: 应在文件头用 #include 插入相关说明文件; 如:stdio.h、math.h 、string.h 自定义函数也必须先定义后使用; 先定义的方式: 将函数定义即 () ;,二、调用方式:,2. 函数的返回值及其类型,有时函数调用的目的是为了得到一个计算结果,这时通常就需要使用返回语句,以便将计算结果返回给调用程序,同时也使程序的执行流程转到调用语句的下一语句去执行。 返回语句的一般形式如下: return(表达式); 或retu

10、rn表达式;,在此应注意: (1)如果函数有返回值,则在函数定义和函数调用时,一般都应该指明返回值的类型。,在函数定义时,返回值的类型在函数名的前面进行说明,如: float count( int n) float s; . return(s); ,(2)当函数有返回值时,在调用函数中,通常也应当对被调用函数的返回值类型进行说明,这种说明往往是在函数体中的说明部分进行的,它包括函数类型、函数名以及一对圆括号,不包括形参和函数体,如在main函数中调用count函数时,可进行如下说明: main() float count(int ); float s; . s=count(20); . ,C语

11、言规定,在以下情况中,可以不在调用函数内对被调用函数进行类型说明: (1)当被调用函数的定义位于调用函数之前时,可以不必说明,如: float count(int n) float s; . return(s); main() float s; . s=count(10); . ,(2)如果函数没有返回值或返回值的类型为整型或字符型,也可以不进行类型说明,系统将自动进行处理。但现在有的编译系统不允许这样,遇到这种情况,在编译时将给出警告信息,因此最好都进行说明。,(3)C语言允许在所有函数的外面、文件的开头对函数的类型进行说明,这样在调用函数时就可以不对被调用函数的类型进行说明,如:,floa

12、t count(); main() float s; . s=count(10); . float count(int n) float s; . return(s); ,例8.3编一函数,求x的n次方的值,其中n是整数,且大于0。分析:可以将x和n作为函数参数,所求结果通过return语句返回调用程序。,double power(float x,int n) int i; double pw; pw=1; for(i=1;i=n;i+) pw* =x; return(pw); ,例8.4编写程序,求s=s1+s2+s3+s4的值,其中: s1=1+12+13+.+150 s2=1+12+13

13、+.+1100 s3=1+12+13+.+1150 s4=1+12+13+.+1200 分析:首先编一函数,用于求1+12+13+.+1n的值,然后通过函数调用来求s的值。,main() float sum=0; int i; for(i=1;i=4;i+) sum+=fcount(i*50); printf(“Sum=%f”,sum); ,#include “stdio.h” float fcount(int n) float s=0; int i; for(i=1;i=n;i+) s+=1/(float)i; return(s); ,8.5函数的嵌套调用,c语句不能嵌套定义函数,但可以嵌套

14、调用函数,main函数,a函数,b函数,调a函数,调b函数,返回(结束),a返回,b返回,上图表示的是两层嵌套(连main函数共3层函数),例8.6,x=(x1*f(x2)-x2*f(x1)/(f(x2)-f(x1),用弦截法求方程的根,取两个不同点x1,x2,要求f(x1)和f(x2)符号相反,并且x1,x2的值不应相差太大,以保证(x1,x2)区间只有一个根。,#include math.h float f(x) /*定义 f(x)*/ float x; float y; y=(x-5)*x+16)*x-80; return(y);,程序如下:,float xpoint(x1,x2) /*

15、求弦与x轴的交点*/ float x1,x2; float x; x=(x1*f(x2)-x2*f(x1)/(f(x2)-f(x2); return(x);,x1,x2,x,x2,x,float root(x1,x2) /*求近似根*/ float x1,x2; float x,y,y1; y1=f(x1); do x=xpoint(x1,x2); y=f(x); if (y*y10) y1=y; x1=x; else x2=x; while(fabs(y)=0.0001); return(x); ,main ( ) float x1, x2, f1, f2, x; do scanf(%f %

16、f , ,8.6函数的递归调用,1.直接递归:在调用f 函数的过程中,又要调用f函数自身。,main 函数,调用f函数,f函数,main函数,f 函数,f 函数,调f 函数,调f 函数,main 结束,f 返回,f 返回,2.间接调用:在调用f1函数的过程中要调用f2函数,而在调用f2函数的过程中又要调用f1函数。,3.用语句来控制,只有在某一条件成立时才继续执行递归调用,否则就不再继续。,f1函数,f2函数,调用f2函数,调用f1函数,main 函数,main函数,f1 函数,f2 函数,调f1 函数,调f2 函数,main 结束,f1 返回,f2 返回,调f1 函数,例6.11用递归方法求

17、n! 先列出递归公式:n!= 1 (n=0,1) n (n-1)! (n1),程序如下: long fac(n) int n; long 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; long y; printf(“input a integer number:”); scanf(“%d”, ,fac(n)=n*fac(n-1),fac(5),递,归,将输入的字符反序输出,#include stdio.h inverse() cha

18、r ch; ch=getchar( ); if (ch!=#) inverse( ); putchar(ch); main() inverse( ); ,第一层 inverse( ) char ch; ch=getchar( ); if (ch!=#) inverse( );,putchar(ch); ,第二层 inverse( ) char ch; ch=getchar( ); if (ch!=#) inverse( );,putchar(ch); ,第三层 inverse( ) char ch; ch=getchar( ); if (ch!=#) inverse( );,putchar(c

19、h); ,第六层 inverse( ) char ch; ch=getchar( ); if (ch!=#) inverse( );,putchar(ch); ,第五层 inverse( ) char ch; ch=getchar( ); if (ch!=#) inverse( );,putchar(ch); ,第四层 inverse( ) char ch; ch=getchar( ); if (ch!=#) inverse( );,putchar(ch); ,输入A,输入B,输入C,输入D,输入E,输入#,输出#,输出E,输出D,输出C,输出B,输出A,n个盘从A移到C的步骤:,将n-1个盘

20、从B借助于A移到C,A针一有64个盘子,上小下大;借助B,从A移到C,每次移一个,都要上小下大.,例7.5 汉诺塔(Hanoi)问题,如:n = 3 个盘的分解步骤:,即: AC , AB , CB ;AC ;BA , BC , AC 。,将A上n-1 = 2个盘借助C移到B,将A针上剩下的一个盘移到C,将A上n-1个盘借助C移到B 将A针上剩下的一个盘移到C 将n-1个盘从B借助于A移到C,将A针上的一个盘移到C 将A针上的一个盘移到B 将C针上的一个盘移到B,将B针上的一个盘移到A 将B针上的一个盘移到C 将A针上的一个盘移到C,void move (getone, putone) cha

21、r getone, putone; printf (%c-%cn, getone, putone);,void hanoi(n,one,two,three) /*将n个从one借助two移到three*/ int n; char one, two, three; if (n=1) move(one,three); else hanoi(n-1,one,three,two); /*将A上n-1个盘借助C移到B*/ move(one,three); /*将A针上剩下的一个盘移到C*/ hanoi(n-1,two,one,three); /*将n-1个盘从B借助于A移到C*/ ,main( ) in

22、t m;scanf(%d,A针一有64个盘子,上小下大;借助B,从A移到C,每次移一个,都要上小下大.,例7.5 汉诺塔(Hanoi)问题,H(3, A, B, C),main ( ),H(3, A, B, C),结束,A C,读入3 m,H(2, A, C, B),H(2, A, C, B),H(1, A, B, C),H(1, A, B, C),M(A, C),M(A, C),M(A, B),H(1, C, A, B),H(1, C, A, B),M(C, B),M(A, C),H(2, B, A, C),8.7函数的参数及其传递方式,函数的参数主要用于在调用函数和被调用函数之间进行数据传

23、递。在函数调用时,首先需要将实参值传递给形参,然后才能执行函数体。,一、变量作函数参数,在函数调用时,C语言编译系统根据形参的类型为每个形参分配存储单元,并将实参的值复制到对应的形参单元之中,#include “stdio.h” int mult10(int n) n* =10; return(n); ,main() int num; int result; num=5; result=mult10(num); printf(“result=%dn”,result); printf(“num=%dn”,num); ,编一程序,将一整数乘以10后显示出来。,此程序运行结果是: result=50

24、 num=5,1、数组元素:等同于简单变量,#include “stdio.h” void swap(int a,int b) int c c=a; a=b;b=c; main() static int a3=0,1,2; swap(a1,a2); printf(%d,%d,a1,a2); ,二、数组作函数参数,调用,形参的变化不会影响实参,2、数组名作为函数参数,例:编一函数,用来统计一个一维数组中非0元素的个数。 int solve(int a,int n) int sum,i; sum=0; for(i=0;in;i+) if(ai!=0) sum+; return(sum); ,mai

25、n() int num,a10,i; for(i=0;i10;i+) scanf(%d, ,说明:,1、当数组名作为函数参数时,也需要对其进行相应的说明,如: int test(int array10) . 其中形参array被说明为具有10个元素的一维整型数组。 2、 int test(int array ,int n) . 用形参n来表示 array数组的实际长度。 3、当多维数组作为函数参数时,除第一维可以不指定长度外(也可以指定),其余各维都必须指定长度,如: check(float a 10,int n) . ,例:编一程序,将一维数组中的每个元素的值加1后显示出来。 #includ

26、e “stdio.h” void ADD(a,n) int a ,n; int i; for(i=0;in;i+) ai+; main( ) static int array =0,1,2,3,4,5,6,7,8,9; int i; ADD(array,10); for(i=0;i10;i+) printf(“%d”,arrayi); ,运行结果如下: 1 2 3 4 5 6 7 8 9 10,注意,数组名作为函数参数时,不是采用“值传递”方式,而是采用“地址传递”方式。 也就是说在函数调用时,是把实参数组的起始地址传递给形参数组,这样形参数组和实参数组实际上占用同样的存储区域,对形参数组中某

27、一元素的存取,也就是存取相应实参数组中的对应元素。 换句话说,形参数组中某一元素的改变,将直接影响到与其对应的实参数组中的元素,这一点是与变量作为函数参数的情形不同的,应引起注意。,8.8局部变量与全局变量,1、局部变量:在函数内部定义的变量,float f1( int a) int b,c; . char f2(int x,int y) int i,j,a,b; . main() int m,n; . ,a,b,c 有效,x,y,i,j,a,b 有效,m,n有效,在复合语句中定义的局部变量,main() int m,n; . int i; for(i=1;i=10;i+) . ,int f1

28、(int m, int n) int a,b; a=n+; b= m; return(a+b); main() int a,b,c; a=3;b=5 printf(a=%d,b=%dn,a,b); c=f1(a,b); printf(a=%d,b=%d,c=%dn,a,b,c); ,a=3,b=5 a=3,b=5,c=7,例:,外部变量:在函数之外定义的量。 其作用域为:从定义它的位置到本源文件结束。 如:,int p=1,q=5; /*外部变量p,q作用域为整个程序/ float f1(int a) /*形参为局部量,作用域为本函数/ int b,c; char c1,c2; /*外部变量c

29、1,c2作用域从此到程序尾/ char(int x,int y) int i ,j; main( ) int m,n; ,2、全局变量,例: #include stdio.h int x; main() int k=3; x=5; cude(k); printf(%d,%dn,x,k); cude (int a ) x=x*a; a+; ,结果: 15,3,注意a和k的值,在定义点前引用外部变量要作外部变量说明,如: max(x,y) int x,y; int z; return(xy?x:y); main( ) extern int a, b; /* 外部变量说明冠以extern*/ pri

30、ntf(%d, max(a,b); int a=13, b=-8;,外部变量的定义(在函数外)只有一次,说明可以多次(在函数内),int a=3, b=5; sub(a,b) int a,b; return a-b; /* 在此函数体内,外部量 a, b不起作用 * main( ) int a=6; printf(%dn, sub(b, a); /*外部量a在此不起作用,外部量b 在此起作用*/,当外部变量与局部变量同名,则在局部变量的作用域内,外部变量不起作用。如:,运行结果: 1,8.9 动态存储变量与静态存储变量,从作用域分全局和局部变量 从生存期分静态和动态存储变量,C语言程序占用的存

31、储空间通常分为三部分,分别称为程序区、静态存储区、动态存储区。,程序区:存放的是可执行程序的机器指令; 静态存储区:存放的是需要占用固定存储单元的变量; 动态存储区:存放的是不需要占用固定存储单元的变量。,静态存储指在程序运行时分配固定空间 动态存储指在程序运行时动态分配空间,在C语言中,变量的定义包含三方面的内容: (1)变量的数据类型,如int、char和float等。 (2)变量的作用域。 即一个变量能够起作用的程序范围,是由变量的定义位置决定的。 (3)变量的存储类型。 即变量在内存中的存储方法,不同的存储方法,将影响变量值的存在时间(即生存期)。(auto, static, register寄存器,extern外部),例: auto int a,b; static float x,y; register int f; extern float w,z;,说明: 未加专门说明的局部变量视为自动变量 寄存器与自动变量处理相同且只能是局部 局部静态变量在函数结束后保留其值。,自动类变量是在动态存储区内分配单元的,函数返回时,编译系统将放弃这些存储单元,因此当函数调用结束时,自动类变量中存放的数据也就消失了。 在变量初始化方面,自动类变量在每调用一次函数时都赋一次初值。,#include“stdio.h” void test_auto() int va=0; printf(“a

温馨提示

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

评论

0/150

提交评论