版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
主讲:杨林第四章函数C源程序由函数组成,C语言称为函数式语言函数是C源程序的基本模块C采用了函数模块式的结构,易于实现结构化程序设计,有利于团队开发,有利于软件的维护与函数的可重用性。函数可分为库函数和用户定义函数两种。库函数:由C系统提供,用户无须定义,只需在程序前包含有该函数原型的头文件用户定义函数:由用户按需要编写的函数函数概述4.1
函数的定义与调用在C语言中,在一个函数的函数体内,不能再定义另一个函数,也就是不能嵌套定义函数。函数之间允许相互调用,习惯上将调用者称为主调函数,被调用者称为被调函数。main()函数是主函数,它可以调用其它函数,但不允许被其它函数调用。C程序的执行总是从main()函数开始,完成对其它函数的调用后再返回到main()函数,正常情况下,最后由main()函数结束整个程序。4.1.1
函数定义的一般形式1.无参函数定义的一般形式无参函数定义的一般形式如下:返回类型函数名(void){
函数体}其中“返回类型函数名(void)”称为函数首部。返回类型指明了本函数返回值的类型,有时也称函数类型。返回类型也可以是void,表示没有返回值。C89标准中,若没有返回类型,则默认为int类型。函数名是由用户定义的标识符。{}中的内容称为函数体。建议:自定义的函数名首字母大写,用以区别库函数。例4.1无参函数示例。#include<stdio.h> /*标准输入/出头文件*/#include<stdlib.h> /*包含库函数system()所需信息*/voidHello(void) /*函数首部*/{ printf("Hello,world!\n"); /*输出"Hello,world!"*/}intmain(void) /*主函数main()*/{ Hello(); /*调用函数Hello()*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出如下:
Hello,world!
请按任意键继续...2.有参函数的一般形式有参函数定义的一般形式如下: 返回类型函数名(形式参数表) {
函数体
}有参函数比无参函数多了形式参数表,形参表格式如下: 类型名1形式参数1,类型名2形式参数2,…在进行函数调用时,主调函数将赋予这些形式参数实际的值。例4.2有参函数示例。intMax(inta,intb) /*函数首部*/{ returna>b?a:b; /*返回a,b的最大值*/}intmain(void) /*主函数main()*/{ inta,b,m; /*定义变量*/ printf("输入a,b:"); /*输入提示*/ scanf(“%d,%d",&a,&b); /*输入a,b*/ m=Max(a,b); /*调用函数求最大值*/ printf("最大值:%d\n",m); /*输出最大值*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出参考如下: 输入a,b:23
最大值:3
请按任意键继续...4.1.2函数调用的一般形式在程序中是通过对函数的调用来执行函数体,在C语言中,函数调用的一般形式为:
函数名(实际参数表);对无参函数调用时无实际参数表,但括号不能省。实际参数表中的参数可以是常数,变量或表达式。各实参之间用逗号分隔。在C语言中,可以用以下几种方式调用函数:函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。
如:a=Max(x,y,z)/2;函数语句:函数调用的一般形式加上分号即构成函数语句。
如:printf(“Helloworld!\n”);对返回类型为void的函数,只能采用函数语句的形式调用,不能参与运算或赋值给变量。4.1.3函数的声明和函数原型在一个函数(即主调函数)中调用另一个函数(即被调函数)需具备如下条件:被调用的函数必须是已经定义的函数(库函数或用户自定义的函数)。如果使用库函数,还应在本文件开头用#include命令将调用有关库函数时所需用到的信息“包含”到本文件中来。如果使用用户自己定义的函数,而此函数的位置在调用它的函数的后面,则应在调用函数前对被调用函数作声明。例4.3对被调用函数的声明示例。intmain(void) /*主函数main()*/{
intMin(inta,intb); /*对被调用函数的声明*/ inta,b,m; /*定义变量*/ printf("输入a,b:"); /*输入提示*/ scanf("%d%d",&a,&b); /*输入a,b*/ m=Min(a,b); /*调用函数求最小值*/ printf("最小值:%d\n",m); /*输出最小值*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}intMin(inta,intb) /*函数首部*/{ returna<b?a:b; /*返回a,b的最小值*/}程序运行时屏幕输出参考如下: 输入a,b:23
最小值:2
请按任意键继续...例4.4在主调用函数前对被调用函数的声明示例。intMax(inta,intb); /*对被调用函数的声明*/intmain(void) /*主函数main()*/{ inta,b,m; /*定义变量*/ printf("输入a,b:"); /*输入提示*/ scanf("%d%d",&a,&b); /*输入a,b*/ m=Max(a,b); /*调用函数求最大值*/ printf("最大值:%d\n",m); /*输出最大值*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}intMax(inta,intb) /*函数首部*/{ returna<b?a:b; /*返回a,b的最大值*/}程序运行时屏幕输出参考如下: 输入a,b:23
最大值:3
请按任意键继续...对函数的声明与函数定义中的函数首部基本上是相同的,只多了一个分号。因此可以简单地照写已定义的函数的首部,再加一个分号,就成为了对函数的“声明”。函数声明也称为函数原型。编译系统并不检查函数声明中的参数名,只检查参数类型。因此参数名是什么都无所谓,所以函数声明中的参数名可以不写,如上面程序中的声明也可以写成:intMax(int,int); /*对被调用函数的声明,可 不写参数名,只写参数类型*/4.2
函数的参数和函数的值4.2.1函数的参数函数的参数分为形参和实参两种:形参出现在函数定义中,在整个函数体内都可以使用,离开函数则自动失效,不能使用。实参出现在主调函数中,进入被调函数后,实参变量也不能使用。形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送(复制)给被调函数的形参。函数的形参和实参具有以下特点:形参变量只有在被调用时才分配内存单元,在调用结束时,立即释放所分配的内存单元。实参可以是常量、变量、表达式等,实参必须具有确定的值,以便将这些值传送给形参。实参和形参在数量上,类型上,顺序上应一致,否则可能会发生“类型不匹配”的错误。函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。例4.5形参的值发生改变,而实参中的值不会变化示例。voidSum(intn); /*声明函数sum()*/intmain(void) /*主函数main()*/{ intn; /*整型变量*/ printf("输入n:"); /*输入提示*/ scanf("%d",&n); /*输入n*/ Sum(n); /*求1+2+3+...+n*/ printf("n:%d\n",n); *显示n的值*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}voidSum(intn){ inti; /*整型变量*/ for(i=n-1;i>=1;i--) n=n+i; /*循环求和*/ printf("n:%d\n",n); /*显示和*/}程序运行时屏幕输出参考如下: 输入n:10 n:55 n:10
请按任意键继续...本例的形参变量和实参变量的标识符都为n,但这是两个不同的变量,各自的作用域不同4.2.2函数的返回值函数的返回值指函数被调用之后,执行函数体中的程序段后返回给主调用函数的值。对函数的值(或称函数返回值)有以下一些说明:函数的返回值只能通过return语句返回给主调函数。return语句的一般形式为:
return表达式;或 return(表达式);说明:对于一个函数,每次只能使用一个return语句,只能返回一个函数值。函数返回值的类型应和主调函数中的类型保持一致。4.2.2函数的返回值如果两者不一致,则以函数类型为准,自动进行类型转换。如函数返回值为整型,在函数定义时可以省去类型说明。不返回值的函数,可以定义为“空类型”,类型说明符为“void”。如果函数中没有ruturn语句,则执行到函数最后一条语句后自动返回到主调函数。4.3
函数的嵌套调用C语言中允许在一个函数中调用另一个函数。这样就出现了函数的嵌套调用,在被调函数中可以又调用其它函数。除main函数外,每一个函数都可以调用其他函数或被其他函数调用。例4.6计算s=(2!)2+(3!)2+(4!)2。本题可编写两个函数,一个是用来计算阶乘平方值的函数f1(),另一个是用来计算阶乘值的函数f2()。主函数先调用f1()计算出阶乘平方值,在循环程序中计算累加和。longf1(longn){ intk,r; /*整型变量*/ longf2(long); /*函数声明*/ k=f2(n); /*调用函数f2()*/
r=k*k; /*求k的平方*/ returnr; /*返回r*/}longf2(longn){ longt=1; /*累乘积*/ inti; /*整型变量*/ for(i=1;i<=n;i++) t=t*i; /*循环求积*/ returnt; /*返回t*/}……程序运行时屏幕输出如下:
s=616
请按任意键继续...4.4
函数的递归调用函数的递归调用是指函数直接或间接对自已进行调用,在C语言中,数学上的迭代函数一般都可以用递归方法进行编程。例4.7用递归求累加和1+2+3+…+n。求累加和1+2+3+…+n可用迭代公式表示如下:用可递归编程如下:intSum(intn) /*用递归求和1+2+...+n*/{ if(n>0)returnn+Sum(n-1); /*递归调用*/ elsereturn0; /*递归结束*/}intmain(void) /*主函数main()*/{ intn; /*定义变量*/ printf("请输入一个非负整数n:"); /*输入提示*/ scanf("%d",&n); /*输入n*/ printf("累加和为%d.\n",Sum(n)); /*输出累加和*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出参考如下: 请输入一个非负整数n:5
累加和为15.
请按任意键继续...下面对递归函数Sum()进行分析,可以先考虑基本情况,然后再由基本情况推算其他情况函数调用返回值Sum(0)0Sum(1)1+Sum(0),即1+0Sum(2)2+Sum(1),即2+1+0Sum(3)3+Sum(2),即3+2+1+0Sum(4)4+Sum(3),即4+3+2+1+0Sum(5)5+Sum(4),即5+4+3+2+1+0简单递归通常都有对函数的入口进行测试的基本情况,上例中n==0就是基本情况,然后再将函数中的一个变量的表达式作为参数进行递归调用上例中递归调用Sum(n-1),最终将递归情况演化为基本情况,上例每次将n的值减1,直到n等于0的基本情况为止。一般递归具有如下的形式:
if(<递归结束条件>) { /*递归结束条件成立,结束递归调用*/
递归结束处理方面的语句; } else { /*递归结束条件不成立,继续进行递归调用*/
递归调用方面的语句; }或:
if(<递归调用条件>) { /*递归调用条件成立,继续进行递归调用*/
递归调用方面的语句; } [else { /*递归调用条件不成立,结束递归调用*/
递归结束处理方面的语句; }]上面的括号“[]”中的部分是可省略的部分#include<stdio.h>voidfun(intx){if(x/2>1)fun(x/2);printf("%d",x);}main(){fun(7);printf("\n");}以上程序运行结果?#include<stdio.h>intf(intx);main(){intn=1,m;m=f(f(f(n)));printf("%d\n",m);}intf(intx){returnx*2;}以上程序运行结果?4.5
变量的作用域形参变量只在被调用期间才分配内存单元,调用结束立即释放,表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了变量有效性的范围称变量的作用域不仅对于形参变量,C语言中所有的变量都有自己的作用域按作用域范围可分为两种局部变量全局变量4.5.1局部变量局部变量也称为内部变量。在函数内作定义说明的变量是局部变量。局部变量作用域仅限于函数内,离开该函数后再使用这种变量是非法的。关于局部变量的作用域还要说明以下几点:主函数中定义的变量只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。允许在不同的函数中使用相同的变量名,它们代表不同的对象,被分配不同的单元,互不干扰,也不会发生混淆在复合语句中也可定义变量,其作用域只在复合语句范围内。例4.8作用域示例。intmain(void) /*主函数main()*/{ inti=2,j=3,k; /*定义变量i,j,k*/ k=i+j; /*求和*/ { /*复合语句*/ intk=8; /*定义变量k*/ printf("%d\n",k); /*输出k*/ } printf("%d,%d\n",i,k); /*输出i,k*/
system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出如下:
8 2,5
请按任意键继续...4.5.2全局变量全局变量也称为外部变量,在函数外部定义的变量是全局变量。全局变量不属于哪一个函数,而属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,一般应作全局变量声明。全局变量的说明符为extern。在一个函数之前定义的全局变量,在该函数内使用可不再加以说明
例4.9输入正方体的长宽高l,w,h。求体积及三个面的面积。ints1,s2,s3; /*三个面的面积*/intGetVolArea(intl,intw,inth){ intv; /*定义变量v*/ v=l*w*h; /*计算体积*/ s1=l*w; /*计算面积*/ s2=l*h; /*计算面积*/ s3=w*h; /*计算面积*/ returnv; /*返回体积*/}intmain(void) /*主函数main()*/{ intv,l,w,h; /*定义变量v,l,w,h*/ printf("输入长,宽和高:"); /*输入提示*/ scanf("%d%d%d",&l,&w,&h); /*输入长,宽和高*/ v=GetVolArea(l,w,h); /*计算体积的面积*/ printf("v=%ds1=%ds2=%ds3=%d\n",v,s1,s2,s3); /*输出体积的面积*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出参考如下: 输入长,宽和高:234 v=24s1=6s2=8s3=12
请按任意键继续...C语言规定函数返回值只有一个,当需要增加函数的返回数据时,用外部变量是一种很好的方式对于全局变量还有以下几点说明:外部变量的定义和外部变量的声明并不是一回事。外部变量定义必须在所有的函数之外,且只能定义一次。其一般形式为: 变量类型变量名1,变量名2,…; 例如
: intm,n;
在整个程序内,外部变量的声明可能出现多次,外部变量说明的一般形式为:
extern
变量类型变量名1,变量名2,…;
外部变量在定义时就已分配了内存单元,外部变量定义可作初始赋值,外部变量的声明不能再赋初始值,只是表明在函数内要使用某外部变量外部变量可加强函数模块之间的数据联系(耦合性),但使得函数的独立性降低。在不必要时尽量不要使用全局变量。在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。例4.10已知正方体的长宽高l,w,h。求体积。intGetVol(intl,intw) { externinth; /*声明全局变量h*/ intv; /*定义变量v*/ v=l*w*h; /*计算体积*/ returnv; /*返回体积*/}intmain(void) /*主函数main()*/{ externintw,h; /*声明全局变量w,h*/ intl=5; /*定义变量l*/ printf("v=%d\n",GetVol(l,w)); /*输出体积*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}intl=6,w=8,h=10; /*定义全局变量l,w,h*/程序运行时屏幕输出如下:
v=400
请按任意键继续...4.6
变量的存储类型和生存期存储类型是指变量占用内存空间的方式,也称为存储方式,变量的存储方式可分为:静态存储动态存储静态存储变量通常在变量定义时就分配存储单元并一直保留到整个程序结束。4.5.2节中介绍的全局变量就属于此类存储方式动态存储变量是在程序执行过程中,使用它时才分配存储单元,使用完毕立即释放。典型的例子是函数的形式参数,在函数定义时并不给形参分配存储单元,只是在函数被调用时,才予以分配,调用函数完毕立即释放。生存期表示变量存在的时间。生存期和作用域是从时间和空间这两个不同的角度来描述变量的特性。在C语言中,对变量的存储类型说明有以下四种:auto(自动变量)register(寄存器变量)extern(外部变量)static(静态变量)。自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式对一个变量的说明不仅应说明其数据类型,还应说明其存储类型。因此变量说明的完整形式应为:存储类型数据类型变量名1,变量名2…;例如:staticinta,b;
/*说明a,b为静态类型变量*/autocharc1,c2;
/*说明c1,c2为自动字符变量*/externintx,y;
/*说明x,y为外部整型变量*/4.6.1自动变量自动变量的类型说明符为auto,函数内凡未加存储类型说明的变量均视为自动变量,也就是说自动变量可省去说明符autointFun(void){ inti,j,k; /*定义变量i,j,k*/ charc; /*定义变量c*/ ……}等价于:intFun(void){ autointi,j,k; /*定义变量i,j,k*/ autocharc; /*定义变量c*/ ……}自动变量具有以下特点:自动变量的作用域仅限于定义该变量的模块内。自动变量属于动态存储方式,只有在使用时,也就是定义此变量的函数被调用时才给它分配存储单元,开始它的生存期。函数调用结束,释放存储单元,生存期结束。在复合语句中定义的自动变量,在退出复合语句后也不能再使用。例4.11复合语句中定义的自动变量示例。intmain(void) /*主函数main()*/{ autointa; /*定义自动变量a*/ printf("输入a:"); /*输入提示*/ scanf("%d",&a); /*输入a*/ if(a>0) { autoints,p; /*复合语句内定义自动变量s,p*/ s=a+a; /*求和*/ p=a*a; /*求积*/ printf("s=%dp=%d\n",s,p); /*输出s,p*/ }
printf(“s=%dp=%d\n”,s,p); /*错误,在复合语句外,s,p无效*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出参考如下: 输入a:8 s=16p=64
请按任意键继续...自动变量的作用域和生存期都局限于定义它的个体内(函数或复合语句内),不同的个体中允许使用同名的变量不会混淆。例4.12函数内定义的自动变量与该函数内部的复合语句中定义的自动变量同名示例。intmain(void) /*主函数main()*/{ autointa,s=600,p=600; /*定义自动变量a,s,p*/ printf("输入a:"); /*输入提示*/ scanf("%d",&a); /*输入a*/ if(a>0) { autoints,p; /*复合语句内定义自动变量s,p*/
s=a+a; /*求和*/
p=a*a; /*求积*/ printf("s=%dp=%d\n",s,p); /*输出s,p*/ } printf("s=%dp=%d\n",s,p); /*输出s,p*/
system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}程序运行时屏幕输出参考如下: 输入a:8 s=16p=64 s=600p=600
请按任意键继续...4.6.2外部变量外部变量的类型说明符为extern。当一个源程序由若干个源文件组成时,在一个源文件中定义的外部变量在其它的源文件中也有效。例如:/*文件名:f1.c*/inta,b; /*定义外部变量*/charc; /*定义外部变量*/intmain(void) /*主函数main()*/{ ……}/*文件名:f2.c*/externinta,b; /*声明外部变量*/externcharc; /*声明外部变量*/Func(intx,y){ ……}4.6.3静态变量静态变量的类型说明符是static。静态变量属于静态存储方式。外部变量虽属于静态存储方式,但不一定是静态变量,必须由static加以定义后才能成为静态外部变量,或称静态全局变量。对于在函数内或复合语句中定义的变量,可以用static定义它为静态变量,或称静态局部变量。1.静态局部变量在局部变量的说明前再加上static说明符就构成静态局部变量。例如:staticinta,b; /*定义静态变量*/静态局部变量属于静态存储方式,具有以下特点:静态局部变量在函数或复合语句内定义,静态局部变量始终存在着,也就是生存期为整个程序。静态局部变量的生存期虽然为整个程序,但是其作用域为定义该变量的函数或复合语句。对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是随机的。静态局部变量是一种生存期为整个程序的量。虽离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。例4.13静态局部变量示例。intmain(void) /*主函数main()*/{ inti; /*定义自动变量*/ voidf(); /*声明函数*/ for(i=1;i<=5;i++) f(); /*循环调用函数f()*/ system("PAUSE"); /*输出系统提示信息*/ return0; /*返回值0,返回操作系统*/}voidf(){ staticintcount=0; /*定义静态局部变量*/ ++count; /*计数*/ printf("%d\n",count); /*显示count*/}count为静态局部变量,能在每次调用后保留其值并在下一次调用时继续使用,所以输出值成为累加的结果程序运行时屏幕输出如下:
1 2 3 4 5
请按任意键继续...2.静态全局变量全局变量(外部变量)的说明之前再冠以static就构成了静态全局变量。全局变量本身就是静态存储方式,静态全局变量显然也是静态存储方式。这两者在存储方式上并无不同。当一个源程序由多个源文件组成时,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 伤口治疗师培训汇报
- 2024家庭居室装饰合同
- 2024解除房屋租赁合同通知书范本
- 2024至2030年中国顶杆滚轮数据监测研究报告
- 2024年证券登记、结算机构服务项目成效分析报告
- 2024至2030年中国连续式渗碳自动线数据监测研究报告
- 2024年能源大数据项目成效分析报告
- 2024至2030年中国羊毛绒鞋垫行业投资前景及策略咨询研究报告
- 2024至2030年中国石墨改性聚丙烯换热器数据监测研究报告
- 2024至2030年中国球型改性石墨行业投资前景及策略咨询研究报告
- 店长离职交接表
- DB51∕T 5057-2016 四川省高分子复合材料检查井盖、水箅技术规程
- 2022年联合办学方案范文
- 百错图与答案
- 职业病体检报告模版
- 口腔科临床路径16个
- 广东省医疗、预防、保健机构医师聘用证明
- 临床试验样本量简易计算器
- 课题设计论证活页
- 祖国不会忘记合唱谱(1)
- 小学二年级家长课堂-动物的世界(课堂PPT)
评论
0/150
提交评论