《函数与程序结构课件精.ppt》由会员分享,可在线阅读,更多相关《函数与程序结构课件精.ppt(42页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、函数与程序结构课件函数与程序结构课件第1页,本讲稿共42页5.1 C程序的一般结构程序的一般结构5.1.1 模块化程序设计模块化程序设计n一个较大的程序一般应分为若干个程序一个较大的程序一般应分为若干个程序模块,每一个模块用来实现一个特定的模块,每一个模块用来实现一个特定的功能。功能。nC语言中,模块使用函数实现的。语言中,模块使用函数实现的。第2页,本讲稿共42页5.1.2 C程序的一般结构程序的一般结构 n函数函数:构成构成C语言程序的基本功能模块,是一段程语言程序的基本功能模块,是一段程序,它完成一项相对独立的任务。序,它完成一项相对独立的任务。例如:例如:printf();mainab
2、cdefhg第3页,本讲稿共42页n一个一个c程序由一个主函数和若干个函数组程序由一个主函数和若干个函数组成成 nC程序的执行总是从主函数开始,又从主程序的执行总是从主函数开始,又从主函数结束,其他函数只有通过调用关系函数结束,其他函数只有通过调用关系发生作用。发生作用。n函数相互独立,不能嵌套定义函数相互独立,不能嵌套定义。第4页,本讲稿共42页n 从用户使用的角度看,函数有两种:从用户使用的角度看,函数有两种:(1)标准函数,即库函数标准函数,即库函数(2)用户自己定义的函数用户自己定义的函数n从函数的形式看,函数分两类:从函数的形式看,函数分两类:(1)无参函数无参函数 一般用来执行指定
3、的一组操作。一般用来执行指定的一组操作。(2)有参函数有参函数 例:例:e5-1.c e5-1-2.c第5页,本讲稿共42页5.2 函数的定义与调用函数的定义与调用5.2.1 函数的定义函数的定义函数定义的一般形式为函数定义的一般形式为类型标识符类型标识符函数名(形参表列)函数名(形参表列)说明部分说明部分语句部分语句部分没有形式参数没有形式参数为无参函数为无参函数 第6页,本讲稿共42页在定义在定义C函数时要注意以下几点。函数时要注意以下几点。(1)函数类型标识符同变量类型说明符,它表示返回)函数类型标识符同变量类型说明符,它表示返回的函数值类型。的函数值类型。(2)如果省略函数的类型标识符
4、,则默认为是)如果省略函数的类型标识符,则默认为是int型。型。(3)C语言允许定义空函数。如语言允许定义空函数。如dummy()(4)如果)如果“形参表列形参表列”中有多个形式参数,则它们之中有多个形式参数,则它们之间要用间要用“,”分隔。分隔。(5)C函数不能嵌套定义。函数不能嵌套定义。第7页,本讲稿共42页(6)函数中返回语句的形式为)函数中返回语句的形式为return(表达式);(表达式);或或return 表达式;表达式;注:如函数不需要有返回值时,函数名前最好注:如函数不需要有返回值时,函数名前最好加一个加一个void,此时,此时return后的表达式可以省略。后的表达式可以省略。
5、例:例:e5-1-1.c e5-2.c第8页,本讲稿共42页5.2.2 函数的调用函数的调用 n函数调用的函数调用的一般形式为:为:函数名函数名(实参表列实参表列);例:例:e5-2-1.c sum=1!+2!+3!+6!第9页,本讲稿共42页说明:说明:(1)调用函数时,函数名称必须与自定义函数名称完)调用函数时,函数名称必须与自定义函数名称完全一致。如果是调用无参函数则实参表列可以没有,全一致。如果是调用无参函数则实参表列可以没有,但括弧不能省略。但括弧不能省略。(2)实参可以是常数、变量或表达式。如果实参不止)实参可以是常数、变量或表达式。如果实参不止1个,则相邻实参之间用逗号分隔。个,
6、则相邻实参之间用逗号分隔。(3)实参的个数、类型和顺序,应该与被调用函数所)实参的个数、类型和顺序,应该与被调用函数所要求的参数个数、类型和顺序一致要求的参数个数、类型和顺序一致(4)对实参表求值的顺序并不是确定的。)对实参表求值的顺序并不是确定的。Turbo C规规定是自右至左顺序求值。定是自右至左顺序求值。第10页,本讲稿共42页被调用函数的说明和函数原型被调用函数的说明和函数原型在调用自定义函数之前,应对该函数进行在调用自定义函数之前,应对该函数进行说明,说明,一般格式如下:一般格式如下:函数类型函数类型 函数名函数名(数据类型数据类型1 参数名参数名1 ,数据类型数据类型2 参数名参数
7、名2);例例 e5-4.c第11页,本讲稿共42页 但但C语言规定,在以下几种情况下可以不在调用函语言规定,在以下几种情况下可以不在调用函数中对被调用函数作类型说明:数中对被调用函数作类型说明:被调用函数为整型或字符型,自动按整型处理。被调用函数为整型或字符型,自动按整型处理。被调用函数的定义出现在调用函数之前。被调用函数的定义出现在调用函数之前。第12页,本讲稿共42页5.2.3 函数的参数传递函数的参数传递 Sub(x,y)s=a+b;returns;调用函数调用函数main()被调用函数被调用函数sub(a,b)数值传递数值传递:一个模块调用另一个模块时,直接将实参值一个模块调用另一个模
8、块时,直接将实参值传送给形参被存放在形参地址中传送给形参被存放在形参地址中第13页,本讲稿共42页【例例】调用函数时的数据传递。调用函数时的数据传递。#include#include void main()void main()int max(int,int);int max(int,int);int a,b,c;int a,b,c;printf(input integer a,b:);printf(input integer a,b:);scanf(%d,%d,&a,&b);scanf(%d,%d,&a,&b);c=max(a,b);c=max(a,b);printf(max is%dn,c
9、);printf(max is%dn,c);int max(int x,int y)int max(int x,int y)int z;int z;z=xy?x:y;z=xy?x:y;return(z);return(z);第14页,本讲稿共42页说明:说明:当函数被调用时才给形参分配内存单元。调用当函数被调用时才给形参分配内存单元。调用结束,所占内存被释放。结束,所占内存被释放。实参可以是常量、变量或表达式,但要求它们实参可以是常量、变量或表达式,但要求它们有确定的值。有确定的值。实参与形参类型要一致,字符型与整型可以兼实参与形参类型要一致,字符型与整型可以兼容。容。实参与形参的个数必须相等
10、。在函数调用时,实参与形参的个数必须相等。在函数调用时,实参的值赋给与之相对应的形参。实参的值赋给与之相对应的形参。“单向值传递单向值传递”。因此,在执行一个被调用函数时,形参的值如果发生因此,在执行一个被调用函数时,形参的值如果发生改变,并不会改变主调函数的实参的值。改变,并不会改变主调函数的实参的值。第15页,本讲稿共42页例例分析下列分析下列C程序:程序:voidswap(x,y)intx,y;intt;tx;xy;yt;return;#includestdio.hmain()intx,y;scanf(x%d,y%d,&x,&y);swap(x,y);printf(x%d,y%dn,x,
11、y);第16页,本讲稿共42页5.3 局部变量与全局变量局部变量与全局变量5.3.1 局部变量局部变量n 在函数内部定义的变量称为局部变量。在函数内部定义的变量称为局部变量。n函数内部定义的变量只在该函数范围内函数内部定义的变量只在该函数范围内有效,有效,n不同函数中的局部变量可以重名,互不不同函数中的局部变量可以重名,互不混淆。混淆。第17页,本讲稿共42页floatf1(inta)intb,c;.Charf2(intx,inty)inti,j;main()intm,n;a,b,c作用范围作用范围x,y,i,j作用范围作用范围m,n作用范围作用范围第18页,本讲稿共42页5.3.2 全局变量
12、全局变量 在函数外定义的变量称为全局变量在函数外定义的变量称为全局变量(或外部变量或外部变量)。作用范围:从定义变量位置开始到本源文件结束作用范围:从定义变量位置开始到本源文件结束第19页,本讲稿共42页intp=1,q=5;floatf1(inta)intb,c;.charc1,c2;charf2(intx,inty)inti,j;main()intm,n;c1,c2作用作用范围范围p,q作用范围作用范围第20页,本讲稿共42页int x,y;void swap()int t;t=x;x=y;y=t;return;#include stdio.hmain()printf(Please inp
13、ut x and y:);scanf(x=%d,y=%d,&x,&y);swap();printf(x=%d,y=%dn,x,y);第21页,本讲稿共42页说明:说明:1.如果定义点之前的函数需要引用这些外部变量,如果定义点之前的函数需要引用这些外部变量,需要在函数内对被引用的外部变量进行说明需要在函数内对被引用的外部变量进行说明。extern类型说明符类型说明符变量名变量名1,变量名,变量名2,;2.同一源文件中,允许全局变量和局部变量同名。同一源文件中,允许全局变量和局部变量同名。但在局部变量的作用域内,全局变量被但在局部变量的作用域内,全局变量被“屏蔽屏蔽”不起作用不起作用.例例e5-4
14、-1.c第22页,本讲稿共42页5.4 变量的存储类型变量的存储类型5.4.1 存储类型区分符存储类型区分符 静态存储变量 动态存储变量变量生存时间第23页,本讲稿共42页其中:其中:程序区用于存放程序;程序区用于存放程序;静静态态存存储储区区是是在在程程序序开开始始执执行行时时就就分分配配的的固固定定存存储储单单元元,如如全全局局变变量;量;动动态态存存储储区区是是在在函函数数调调用用过过程程中中进进行行动动态态分分配配的的存存储储单单元元,如如函数形参、自动变量、函数调用时的现场保护和返回地址等。函数形参、自动变量、函数调用时的现场保护和返回地址等。第24页,本讲稿共42页n变量的属性:变
15、量的属性:数据类型和存储类型。自动类型(自动类型(auto)、静态类型()、静态类型(static)、寄存器类型)、寄存器类型(register)、外部类型()、外部类型(extern)。)。存储类别存储类别存储类别存储类别 数据类型数据类型数据类型数据类型 变量名变量名变量名变量名1,1,变量名变量名变量名变量名n;n;静态存储类型:static、extern动态存储类型:auto、register第25页,本讲稿共42页变量的属性数据类型:数据类型:数据类型:数据类型:决定为变量分配内存单元的长度,决定为变量分配内存单元的长度,决定为变量分配内存单元的长度,决定为变量分配内存单元的长度,数
16、据的存放形式,数据的存放形式,数据的存放形式,数据的存放形式,数的范围。数的范围。数的范围。数的范围。存储类别:存储类别:存储类别:存储类别:决定了变量的生存期,决定了变量的生存期,决定了变量的生存期,决定了变量的生存期,给它分配在哪个存储区。给它分配在哪个存储区。给它分配在哪个存储区。给它分配在哪个存储区。第26页,本讲稿共42页5.4.2 自动变量自动变量 n函数中的局部变量,如不做专门的说明函数中的局部变量,如不做专门的说明(说明为静态的存储类别),都是动态(说明为静态的存储类别),都是动态分配存储空间的,存储在动态存储区中。分配存储空间的,存储在动态存储区中。例:例:auto int
17、x;第27页,本讲稿共42页 内存分配内存分配调用函数或执行分程序时在动态存储区为其分配存储调用函数或执行分程序时在动态存储区为其分配存储单元,函数执行结束,所占内存空间即刻释放。单元,函数执行结束,所占内存空间即刻释放。变量的初值变量的初值定义变量时若没赋初值,变量的初值不确定;如果赋初值则定义变量时若没赋初值,变量的初值不确定;如果赋初值则每次函数被调用时执行一次赋值操作。每次函数被调用时执行一次赋值操作。(e5-1-2.c)生存期生存期 在函数执行期间。在函数执行期间。作用域作用域自动变量所在的函数内。自动变量所在的函数内。第28页,本讲稿共42页5.4.3 静态变量静态变量static
18、说明的局部变量为局部静态变量说明的局部变量为局部静态变量*局部静态变量在函数调用结束后其值不消失而保留原值,局部静态变量在函数调用结束后其值不消失而保留原值,下次调用时的值为上次调用结束时的值。下次调用时的值为上次调用结束时的值。例例e5-4-2.ce5-4-3.c1!2!5!static说明的全局变量为全局静态变量说明的全局变量为全局静态变量第29页,本讲稿共42页 内存分配内存分配编译时,将其分配在内存的静态存储区中,程序运行结编译时,将其分配在内存的静态存储区中,程序运行结束释放该单元。束释放该单元。静态变量的初值静态变量的初值若定义时未赋初值,在编译时,系统自动赋初值为若定义时未赋初值
19、,在编译时,系统自动赋初值为0 0;若定义时赋初值,则仅在编译时赋初值一次,程序运若定义时赋初值,则仅在编译时赋初值一次,程序运行后不再给变量赋初值行后不再给变量赋初值 。生存期生存期整个程序的执行期间。整个程序的执行期间。作用域作用域局部静态变量的作用域是它所在的函数或分程序。全局静局部静态变量的作用域是它所在的函数或分程序。全局静态变量的作用域是从定义处开始到本源文件结束。态变量的作用域是从定义处开始到本源文件结束。第30页,本讲稿共42页5.5.1 函数的嵌套调用函数的嵌套调用nC语句不能嵌套定义函数,但可以嵌套调语句不能嵌套定义函数,但可以嵌套调用函数用函数 例:例:e5-7.c5.5
20、 函数的嵌套与递归调用函数的嵌套与递归调用第31页,本讲稿共42页mainmain函数函数函数函数 调用函数调用函数调用函数调用函数f2f2;函数函数函数函数 f2f2 调用函数调用函数调用函数调用函数f1f1;函数函数函数函数 f1f1 第32页,本讲稿共42页5.5.2 函数的递归调用函数的递归调用递归:函数直接或间接调用本身。递归:函数直接或间接调用本身。递归分为直接递归与间接递归两种。递归分为直接递归与间接递归两种。所谓直接递归,是指直接调用函数本身。所谓直接递归,是指直接调用函数本身。间接递归:间接递归:是指通过别的函数调用自身。是指通过别的函数调用自身。第33页,本讲稿共42页例:
21、用递归法求例:用递归法求n!n!=1 (n=0,1)n*(n-1)!(n1)float fac(int n)float f;if(n=0|n=1)f=1;else f=fac(n-1)*n;return f;y=fac(3)f=fac(2)*3Return ff=fac(1)*2Return ff=1Return fmainfac(3)fac(2)fac(1)Ed.c第34页,本讲稿共42页应用递归算法能求解的问题一般应符合下面三个条件:应用递归算法能求解的问题一般应符合下面三个条件:可以把一个问题转化为新的问题,而这个新问题的解可以把一个问题转化为新的问题,而这个新问题的解决方法仍与原问题的
22、解法相同,只是所处理的对象有决方法仍与原问题的解法相同,只是所处理的对象有所不同,但它们只是有规律的递增或递减。所不同,但它们只是有规律的递增或递减。可以通过转化过程使问题得到解决。可以通过转化过程使问题得到解决。必须有一个明确的结束递归的条件,否则递归将无止境的必须有一个明确的结束递归的条件,否则递归将无止境的进行下去。进行下去。例:例:fib.c第35页,本讲稿共42页5.7 编译预处理编译预处理n编编译译预预处处理理是是指指在在系系统统对对源源程程序序进进行行编编译译之之前前,对对程程序序中中某某些些特特殊殊的的命命令令行行的的处处理理,预预处处理理程程序序根据源代码中的预处理命令修改程
23、序。根据源代码中的预处理命令修改程序。例:例:#include“stdio.h”#define PI 3.1415926第36页,本讲稿共42页#define#define 宏名宏名 字符串字符串功能:功能:在进行编译前,用字符串原样替换程序中的宏名。在进行编译前,用字符串原样替换程序中的宏名。1 1符号常量(不带参数)的宏定义符号常量(不带参数)的宏定义命令的一般格式:命令的一般格式:5.7.1 宏定义宏定义第37页,本讲稿共42页例如:例如:#definePI3.14#definePI3.14main()main()main()main()float r,s,c;float r,s,c;f
24、loat r,s,c;float r,s,c;scanf(scanf(scanf(scanf(“%f%f%f%f”,&r);,&r);,&r);,&r);s=r*r*PI;s=r*r*PI;s=r*r*PI;s=r*r*PI;c=2*r*PI;c=2*r*PI;c=2*r*PI;c=2*r*PI;printf(printf(printf(printf(“s=%f,s=%f,s=%f,s=%f,c=%fc=%fc=%fc=%f”,s,c);,s,c);,s,c);,s,c);替替换换3.143.143.143.14第38页,本讲稿共42页2带参数的宏定义命令的一般形式#define#define
25、#define#define 宏名宏名宏名宏名(形参表形参表形参表形参表)字符串字符串字符串字符串例:例:#defineM(y)y*y+3*yvoidmain()k=M(5);第39页,本讲稿共42页【例例】#defineSQ(x*x)#defineCUBE(x)(SQ(x)*x)#defineFIFTH(CUBE(x)*SQ(x)voidmain()y=FIFTH(a);第40页,本讲稿共42页注意宏定义与函数调用的区别注意宏定义与函数调用的区别#include stdio.h#define PQ 4.5#define ABC(x)PQ+(x*x)main()int a=3,b,c,d;b=ABC(a);c=ABC(a+1);d=2.0*ABC(a);printf(b=%d,c=%d,d=%dn,b,c,d);原样替换原样替换第41页,本讲稿共42页5.7.2 文件包含文件包含 ninclude “包含文件名”或或 include 例例 5-11-1.c第42页,本讲稿共42页
限制150内