C语言课件第六章函数2.0

上传人:仙*** 文档编号:180138114 上传时间:2023-01-04 格式:PPT 页数:33 大小:405.52KB
收藏 版权申诉 举报 下载
C语言课件第六章函数2.0_第1页
第1页 / 共33页
C语言课件第六章函数2.0_第2页
第2页 / 共33页
C语言课件第六章函数2.0_第3页
第3页 / 共33页
资源描述:

《C语言课件第六章函数2.0》由会员分享,可在线阅读,更多相关《C语言课件第六章函数2.0(33页珍藏版)》请在装配图网上搜索。

1、第第1页页第二部分讲义第二部分讲义第第2页页递归调用递归调用变量的存储类别和作用域变量的存储类别和作用域预编译指令预编译指令本部分讲述:本部分讲述:第第3页页函数的嵌套调用是指,在执行被调用函数时,被调用函数的嵌套调用是指,在执行被调用函数时,被调用函数又调用了其它函数。其关系可表示如下图。函数又调用了其它函数。其关系可表示如下图。void f2()void f1()f2();main()f1();1.函数的嵌套调用函数的嵌套调用第第4页页问题分析:问题分析:孪生素数是指间隔为孪生素数是指间隔为2的两个素数,如:的两个素数,如:5和和7 11和和13。若求若求100-200间的孪生素数,可以先

2、编写判断一个数是否素数的函数,间的孪生素数,可以先编写判断一个数是否素数的函数,然后再编写判断是否是孪生素数的函数。步骤如下:然后再编写判断是否是孪生素数的函数。步骤如下:(1)定义一个判断素数的函数)定义一个判断素数的函数isPrime;(2)定义一个判断是否是孪生素数的函数)定义一个判断是否是孪生素数的函数isTwinPrimes。(3)在主函数中调用)在主函数中调用isTwinPrimes,输出,输出100到到200之间的所有孪生之间的所有孪生素数。素数。例例6.6求求100-200之间孪生素数之间孪生素数第第5页页#include“stdio.h”#include“math.h”int

3、 isPrime(int m)int i,k;k=sqrt(m);for(i=2;i=k;i+)if(m%i=0)return 0;return 1;int isTwinPrimes(int n)if(isPrime(n)&isPrime(n+2)return 1;return 0;void main()int i;for(i=101;i1根据这个递推公式,写出如下的求阶乘函数:根据这个递推公式,写出如下的求阶乘函数:long fact(int n)if(n=1)return 1;else return n*fact(n-1);例例6.7第第9页页fact(5)5*fact(4)4*fact(

4、3)3*fact(2)2*fact(1)120 5*24 4*6 3*2 2*1 调用调用fact(4)调用调用fact(3)调用调用fact(2)调用调用fact(1)返回返回fact(5)返回返回fact(4)返回返回fact(3)返回返回fact(2)终止条件n=1 1!=1 递进递进调用过调用过程程fac(4)返回返回过程过程 fact(5)的递归调用过程的递归调用过程 第第10页页用递归法求两个整数的最大公约数。用递归法求两个整数的最大公约数。例例6.8问题分析:问题分析:可以用求最大公约数的可以用求最大公约数的欧几里德算法(辗转相除法)欧几里德算法(辗转相除法)。即:即:a 和和

5、b 的最大公约数,等于的最大公约数,等于 b 和和 a%b 的最大公约数。的最大公约数。可见,要求两个整数可见,要求两个整数a和和b的最大公约数,只需求出的最大公约数,只需求出b和和a%b的最大公约数即可。所以新问题要比原问题更易于的最大公约数即可。所以新问题要比原问题更易于求解,同时,该问题也可以按照类似的方法继续分解,当求解,同时,该问题也可以按照类似的方法继续分解,当分解到余数为分解到余数为0时,这时另一个整数就是所要求的最大公时,这时另一个整数就是所要求的最大公约数。约数。第第11页页#include int gcd(int m,int n)/递归函数定义递归函数定义 if(m%n=0

6、)/如能整数,则如能整数,则n就是最大公约数就是最大公约数 return n;else return gcd(n,m%n);/递归调用递归调用int main()int m,n,result;printf(“请输入两个整数请输入两个整数m、n:n”);scanf(“%d%d”,&m,&n);result=gcd(m,n);printf(“%d和和%d的最大公约数为:的最大公约数为:%dn”,m,n,result);return 0;程序如下:程序如下:第第12页页静态存储方式静态存储方式在程序整个运行期间分配固定的存储空间的方式。在程序整个运行期间分配固定的存储空间的方式。如:全局变量如:全局

7、变量由变量的由变量的作用域作用域来分:分为全局变量和局部变量。来分:分为全局变量和局部变量。由变量由变量内存分配方式内存分配方式来分:分为静态存储方式和动态存储方式。来分:分为静态存储方式和动态存储方式。动态存储方式动态存储方式在程序运行期间根据需要进行动态的分配存储空间的方式。在程序运行期间根据需要进行动态的分配存储空间的方式。如:局部变量如:局部变量程序内存区域划分程序内存区域划分静态存储方式静态存储方式代码区代码区静态数据区静态数据区栈区栈区堆区堆区动态存储方式动态存储方式数据区数据区第第13页页语言中,对变量的存储类型说明有以下四种:语言中,对变量的存储类型说明有以下四种:自动变量自动

8、变量(auto)(auto)寄存器变量寄存器变量(register)(register)外部变量外部变量(extern)(extern)静态变量静态变量(static)(static)动态存储方式动态存储方式静态存储方式静态存储方式第第14页页(1 1)定义格式:)定义格式:static static 数据类型数据类型 变量名;变量名;静态变量(静态变量(static)(2 2)特点)特点程序开始执行时分配空间。程序开始执行时分配空间。在程序执行期间始终存在。(生存期)在程序执行期间始终存在。(生存期)只在作用域内可用。只在作用域内可用。每次使用时,保留上次调用结束时的值。每次使用时,保留上次

9、调用结束时的值。定义但不初始化,则自动赋以定义但不初始化,则自动赋以“”(3 3)何时使用静态内部变量)何时使用静态内部变量需要保留函数上一次调用结束时的值。需要保留函数上一次调用结束时的值。变量只被引用而不改变其值。变量只被引用而不改变其值。如如:static intstatic int x x;第第15页页#include int f(int a)auto int b=0;static int c=3;b=b+1;c=c+1;return(a+b+c);void main()int a=2,i;for(i=0;i3;i+)printf(“%4d”,f(a);思考:没有思考:没有static

10、和和有有static程序的输出程序的输出分别是什么?分别是什么?7 7 7 7 8 9例例第第16页页步骤:步骤:1、新建一个、新建一个VC工程;工程;2、在菜单栏中选择、在菜单栏中选择“工程工程|添加到工程添加到工程”,在弹出的对话框中,在弹出的对话框中选择源文件或头文件,添加到工程中;选择源文件或头文件,添加到工程中;3、如有必要,在适当的位置合理的声明变量和函数;、如有必要,在适当的位置合理的声明变量和函数;4、编译、链接、执行即可。、编译、链接、执行即可。注:注:VC中工程文件的后缀是中工程文件的后缀是.dsw。模块的组织:模块的组织:函数的定义写到函数的定义写到 .cpp 文件中;函

11、数的声明、全局文件中;函数的声明、全局变量的定义一般写到变量的定义一般写到.h 文件中。文件中。如何运行一个多文件的程序如何运行一个多文件的程序第第17页页预编译指令预编译指令所谓预编译所谓预编译,是指在对源是指在对源程序进行编译之前,先对源程程序进行编译之前,先对源程序中进行一些预处理;然后再序中进行一些预处理;然后再将处理的结果,和源程序一起将处理的结果,和源程序一起进行编译,以得到目标代码。进行编译,以得到目标代码。预编译预编译编译编译连接连接执行执行编辑编辑宏定义宏定义文件包含文件包含条件编译条件编译预编译的分类:预编译的分类:第第18页页1.1.不带参数的宏定义(简单替换)不带参数的

12、宏定义(简单替换)用标识符来代表一个字符串(给字符串取个名用标识符来代表一个字符串(给字符串取个名字)。字)。C编译系统在编译前将这些标识符替换成编译系统在编译前将这些标识符替换成所定义的字符串。所定义的字符串。概念概念格式格式define 标识符标识符 字符串字符串相关相关概念概念宏名:宏名:宏定义中的标识符称为宏定义中的标识符称为“宏名宏名”。宏调用:宏调用:在程序中用宏名替代字符串称为在程序中用宏名替代字符串称为“宏调宏调用用”。宏展开:宏展开:在预编译时将宏名替换成字符串的过程称在预编译时将宏名替换成字符串的过程称 为为“宏展开宏展开”。#define PI 3.1415926(一)宏

13、定义(宏替换)(一)宏定义(宏替换)第第19页页1 1、宏名遵循标识符规定,习惯用大写字母表示,以便区别普通的变量。、宏名遵循标识符规定,习惯用大写字母表示,以便区别普通的变量。2 2、宏定义字符串不要以分号结束,否则分号也作为字符串的一部分参、宏定义字符串不要以分号结束,否则分号也作为字符串的一部分参加展开。加展开。说明说明#define PI 3.14;#define PI 3.14;在下面语句使用宏:在下面语句使用宏:area=PIarea=PI*r r*r;r;area=3.14;area=3.14;*r r*r;r;宏展开后宏展开后3、宏定义是预处理指令,与定义变量不同,使用宏时只是

14、进行简、宏定义是预处理指令,与定义变量不同,使用宏时只是进行简单的字符串替换。单的字符串替换。4、宏定义用宏名代替一个字符串,也不管宏展开后的词法和语法、宏定义用宏名代替一个字符串,也不管宏展开后的词法和语法的正确性,只是简单的替换。是否正确,编译时由编译器判断。的正确性,只是简单的替换。是否正确,编译时由编译器判断。例如:例如:#define PI 3.I4 照样进行宏展开(替换),是否正确,由编译器来判断。照样进行宏展开(替换),是否正确,由编译器来判断。第第20页页2.2.带参数的宏定义带参数的宏定义 带参数的宏定义不只是进行简单的字符串替换,还带参数的宏定义不只是进行简单的字符串替换,

15、还要进行参数替换。要进行参数替换。格式格式概念概念define 宏名(参数表)宏名(参数表)字符串字符串类似函数头,但是没类似函数头,但是没有类型说明,参数也有类型说明,参数也不要类型说明不要类型说明展开置展开置换规则换规则按照按照#define#define命令行中指定的命令行中指定的“字符串字符串”从左到右进行置从左到右进行置换(扫描置换)。如果串中包含宏定义中的形参,则将程换(扫描置换)。如果串中包含宏定义中的形参,则将程序中相应的实参代替形参,其它字符原样保留,形成了替序中相应的实参代替形参,其它字符原样保留,形成了替换后的字符串。换后的字符串。举例举例#define S(a,b)a*

16、barea=S(3,2);宏替换后宏替换后area=3*2;第第21页页例例 2用带参数的宏定义表示圆的面积。用带参数的宏定义表示圆的面积。#define PI 3.14#define S(r)PI*r*r void main()float a,area;a=3.6;area=S(a);printf(“r=%fnarea=%fn”,a,area);area=3.14*a*a;宏展开宏展开第第22页页 1 1、因为带参宏定义本质还是简单字符替换(除了参数、因为带参宏定义本质还是简单字符替换(除了参数替换),所以容易发生错误。替换),所以容易发生错误。例:有宏定义:例:有宏定义:define S(

17、r)3.14define S(r)3.14*r r*r r 则语句则语句area=S(a+barea=S(a+b););应如何改呢?应如何改呢?宏定义改为宏定义改为 define S(rdefine S(r)3.14)3.14*(r)(r)*(r)(r)说明说明宏展开宏展开area=3.14*a+b*a+b;不再是求不再是求面积了。面积了。2 2、定义带参数宏时还应该注意宏名与参数表之间不能有、定义带参数宏时还应该注意宏名与参数表之间不能有空格。空格。则,宏替换后,原语句展开为则,宏替换后,原语句展开为 area=3.14*(a+b)*(a+b);第第23页页3 3、带参数的宏定义与函数的本质

18、区别、带参数的宏定义与函数的本质区别1 1)函数调用函数调用时,先求表达式的值,然后将时,先求表达式的值,然后将值传递值传递给形参;给形参;带参宏展开带参宏展开只在编译时进行的简单只在编译时进行的简单字符置换字符置换。2 2)函数调用是在程序运行时处理的,给形参分配临时的函数调用是在程序运行时处理的,给形参分配临时的内存单元;而宏展开是在编译时进行的,展开时并不给内存单元;而宏展开是在编译时进行的,展开时并不给形参分配内存,也不进行形参分配内存,也不进行“值传递值传递”,也没有,也没有“返回值返回值”的概念。的概念。3 3)函数的形参要定义类型,且要求形参、实参类型一致。函数的形参要定义类型,

19、且要求形参、实参类型一致。宏不存在参数类型问题。宏不存在参数类型问题。4 4)宏占用的是编译时间,函数调用占用的是运行时间。宏占用的是编译时间,函数调用占用的是运行时间。在多次调用时,宏使得程序变长,而函数调用不明显。在多次调用时,宏使得程序变长,而函数调用不明显。说明说明第第24页页总结:使用宏的优点总结:使用宏的优点 1 1、程序中的常量可以用有意义的符号代替,程序更加清晰,容易理解、程序中的常量可以用有意义的符号代替,程序更加清晰,容易理解(易读)。(易读)。2 2、常量值改变时,不用在整个程序中查找修改,只要改变宏定义就可、常量值改变时,不用在整个程序中查找修改,只要改变宏定义就可以。

20、比如,提高以。比如,提高PIPI精度值。精度值。3 3、带参数宏定义比函数调用具有更高的时间效率,因为相当于代码的、带参数宏定义比函数调用具有更高的时间效率,因为相当于代码的直接嵌入。(空间效率:多次调用占用空间较多,一次调用没有什直接嵌入。(空间效率:多次调用占用空间较多,一次调用没有什么影响)。么影响)。第第25页页(二)、文件包含(二)、文件包含概念概念格式格式#include“#include“文件名文件名”或或#include#include 所谓所谓“文件包含文件包含”预处理是指一个源文件可以将预处理是指一个源文件可以将另外一个源文件的全部内容包含进来,即将另外另外一个源文件的全部

21、内容包含进来,即将另外的文件包含到本文件之中。的文件包含到本文件之中。示意图示意图#include AB 包含包含file2.cfile1.cABfile1.c第第26页页1 1、被包含的文件常常被称为、被包含的文件常常被称为“头文件头文件”(#include#include一般写在文件的一般写在文件的开头)。头文件常常以开头)。头文件常常以“.h”.h”为扩展名(也可以用其它的扩展为扩展名(也可以用其它的扩展名,名,.h.h只是习惯或风格)。只是习惯或风格)。2 2、一条一条#include#include只能包含一个头文件,如果要包含多个头文件,使只能包含一个头文件,如果要包含多个头文件,

22、使用多条用多条#include#include命令。命令。3 3、在一个被包含的文件中又可以包含另一个被包含文件,即文件包、在一个被包含的文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。含是可以嵌套的。4 4、被包含的头文件可以用被包含的头文件可以用“”“”括起来,也可以用括起来,也可以用括起来。区别括起来。区别在于:在于:“”“”先在用户当前目录查找头文件,如果没找到,再到先在用户当前目录查找头文件,如果没找到,再到存放存放C C库函数头文件的目录中查找;而库函数头文件的目录中查找;而直接到存放直接到存放C C库函数头文库函数头文件的目录中查找。件的目录中查找。一般地说,使用双引号

23、比较保险。一般地说,使用双引号比较保险。5 5、习惯上,用户头文件一般在用户目录下,所以常常用、习惯上,用户头文件一般在用户目录下,所以常常用“”“”;系统;系统库函数的头文件一般在系统指定目录下,所以常常用库函数的头文件一般在系统指定目录下,所以常常用。说明说明第第27页页(三)、条件编译(三)、条件编译概念概念常见形式常见形式#ifdef#ifdef、#ifndef#ifndef、#if#if条件编译,是指程序代码只有在满足一定条件时才被编译,条件编译,是指程序代码只有在满足一定条件时才被编译,不满足条件的不参加编译。不满足条件的不参加编译。#ifdef#ifdef 宏名宏名程序段程序段1

24、 1#else#else 程序段程序段#endif#endif#ifdef#ifdef DEBUG DEBUG printf(“Thisprintf(“This is a debug edition!n”);is a debug edition!n”);#else#else printf(“Thisprintf(“This is a release is a release edition!n”);edition!n”);#endif#endif#ifdef举例举例第第28页页作业:作业:2.12.1,2.22.2,2.42.4,2 2,8 83.13.1,3.33.3,3.53.5第第29页

25、页例例6.1调用库函数生成调用库函数生成10个个0100之间的伪随机数。之间的伪随机数。#include“stdio.h”#include“time.h”#include“stdlib.h”int main()int i;srand(time(NULL);for(i=0;i10;i+)printf(“%dn”,rand()%100);return 0;初始化种子初始化种子随即函数调用随即函数调用获取当前时间获取当前时间问题分析:问题分析:要生产伪随机数,要先用srand函数用来对随机数种子进行初始化。一般使用时间来作为参数来进行初始化。time()函数用来得到系统当前的时间。rand函数用来生

26、成一个0RAND_MAX之间的伪随机数。我们用这个伪随机数对101求余,可以保证输出的伪随机数在0100之间。第第30页页例例6.3在函数中交换在函数中交换两个变量的值。两个变量的值。#include void swap(int x,int y)int t;t=x;x=y;y=t;printf(“x=%d,y=%dn”,x,y);int main()int a=1,b=2;printf(“a=%d,b=%dn”,a,b);swap(a,b);printf(“a=%d,b=%dn”,a,b);return 0;a=1,b=2x=2,y=1a=1,b=2?请写出程序的运请写出程序的运行结果!行结果

27、!第第31页页虽然在虽然在swap函数中交换了两个变量的值,但是在主函数中调用函数中交换了两个变量的值,但是在主函数中调用swap函数前后,两个变量函数前后,两个变量a、b的值并没有改变。的值并没有改变。这就是因为实参给形参进行的参数传递是单向的,形参虽然发生这就是因为实参给形参进行的参数传递是单向的,形参虽然发生了改变,但并不会反过来影响到实参。了改变,但并不会反过来影响到实参。1 a b 2 主函数主函数主函数主函数1 a b 2 1 a b 1 x y 2 2 参数传递参数传递1 x 2 x y y 2 1 被调函数被调函数 在程序执行过程中,在程序执行过程中,main函数和函数和swa

28、p函数中变函数中变量的值的变化过程:量的值的变化过程:第第32页页函数调用的过程函数调用的过程(1)程序在主调函数中执行,遇到函数调用,则)程序在主调函数中执行,遇到函数调用,则在主调函数中暂停执行,保存上下文和当前指在主调函数中暂停执行,保存上下文和当前指令地址;令地址;(2)为函数中的形参等分配内存,把实参的值按)为函数中的形参等分配内存,把实参的值按顺序复制到对应的形参变量中;顺序复制到对应的形参变量中;(3)执行函数体中的语句,直到遇到)执行函数体中的语句,直到遇到return语句语句或函数体语句执行完毕为止;或函数体语句执行完毕为止;(4)计算)计算return语句中的表达式的值,把

29、该值转语句中的表达式的值,把该值转换为函数返回值类型;换为函数返回值类型;(5)释放函数中局部变量和形参的内存,返回到)释放函数中局部变量和形参的内存,返回到主调函数中;主调函数中;(6)在主调函数中继续执行后续语句。)在主调函数中继续执行后续语句。第第33页页#include int main()int n;double p,x;double power(double,int);/函数声明函数声明 printf(“请输入请输入x和指数和指数n:n”);scanf(“%lf%d”,&x,&n);p=power(x,n);/函数调用函数调用 printf(“%.2lf的的%d次方为次方为:%.2lf。n”,x,n,p);double power(double x,int n)/函数定义函数定义 int i;double f=1.0;for(i=0;in;i+)f=f*x;return f;用函数编程求用函数编程求x的的n次方次方例例6.4

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!