第11讲函数的定义与调用一、C程序的模块化结构与函数定义二、函数的调用三、函数间的数据传送1、形参与实参、函数的返回值2、Void函数、函数原型3、数组作为函数的参数1、C程序的模块化结构结构化程序设计:自顶向下,逐步细化;模块化设计。特点:程序结构清晰,易于维护,可重用性和可扩充性。一、概述2、模块化设计的方法:将大程序分割成小函数。3、函数可以分为库函数和用户自定义函数,本节讨论自定义函数。[类型符]函数名称([形参表])[形参说明]{数据说明语句可执行语句}4、函数的定义函数头函数体floatsum(x,y)floatx,y;{intz;z=x+y;returnz;}例如下面的函数定义:floatsum(floatx,floaty){intz;z=x+y;returnz;}也可以缩写成:函数定义格式的详细解释:floatsum(x,y)floatx,y;{intz;z=x+y;returnz;}类型说明符:函数的类型是指函数的返回值的类型,函数返回值所具有的数据类型的种类与变量相同。省略时则默认为int型。若明确表示函数不带回值,可以用void作类型符,称无类型或称空类型。函数定义格式的详细解释(续):floatsum(x,y)floatx,y;{intz;z=x+y;returnz;}函数名:通常是一个标识符,在一个程序中除了主函数外其余函数的名字可以任意取,但不能与变量等其他标识符同名,最好能做到见名识义。一对圆括号是函数的标志。函数定义格式的详细解释(续):floatsum(x,y)floatx,y;{intz;z=x+y;returnz;}形参表(形式参数表):函数定义时的参数称为形式参数,形式参数彼此间用逗号分隔。形式参数省略时称无参函数,但此时函数名后的圆括号不能省。形参说明是用来指明各个形式参数的类型,它随形参的存在而存在。函数定义格式的详细解释(续):floatsum(x,y)floatx,y;{intz;z=x+y;returnz;}函数体:函数中最外层一对花括弧{···}括起来的语句,它由若干个数据说明语句和可执行语句组成,决定函数要实现的功能、完成的任务。函数体内若无任何语句时,为空函数。函数定义格式的详细解释(续):floatsum(x,y)floatx,y;{intz;z=x+y;returnz;}函数返回值(结果):函数返回值是return后面的表达式。函数调用时,返回值通过return语句带回。return语句可以有多个,当执行某个return语句后,其后的语句不再执行。return后面的表达式应该尽量与函数类型相同,否则将自动转换。2、return语句返回函数的当被调用函数在完成一定的功能后,可以将处理的结果通过return语句带回到调用函数。return语句的作用:将表达式的值传给调用函数,并把控制权转向调用函数实现函数的返回,即结束被调用函数的执行,并将控制返回到调用它的函数。return语句的格式:return表达式;或者return(表达式);关于函数返回值的类型函数返回值的类型以说明为准。例写出下面程序的执行结果。#includestdio.hintadd(floata,floatb){floatsum;sum=a+b;returnsum;}voidmain(){floatx,y,z;x=4.5;y=4.3;z=add(x,y);printf(“z=%f\n”,z);}执行结果为:8例编写自定义函数。计算:分析:1)形参:求c要用到f,设形参为f,设为实型。2)返回值:返回值即为c,设为实型。函数定义如下:)32(95fcfloatf_to_c(f)floatf;{floatc;c=5.0/9*(f–32);returnc;}例编写一个自定义函数求n!分析:1)形参:求n!要用到n,设形参为n,整型。2)返回值:设返回值为s,设为整型。函数定义如下:intjiechen(intn){inti,s=1;for(i=1;i=n;i++)s*=i;returns;}二、函数的调用1、函数调用的一般格式函数名([实参列表]);说明:实参与形参的个数相等、类型相同、顺序一致,呈一一对应的关系。实参应有确定的值。2、函数调用的两种形式:1)作为语句形式例如:printf(%d,x);2)作为表达式形式例如:c=abs(-6);实参(实际参数、实际参数)是函数调用时调用函数传送给被调用函数参数的实际值。实参可以是常量、变量和表达式三种形式,实参必须有确定的值。而形参是函数定义时,形式参数表中的参数。形参只能是变量。三、函数的参数传递1、形参与实参例如:fabs(-2)中的2,为常量形式putchar(c)中的c,为变量形式sqrt(x*x+2)中的x*x+2,为表达式形式形参与实参的参数传递intadd(x,y)floatx,y;{intz;z=x+y;returnz;}参数传递方法:在函数调用时,将实参的值赋给形参。当执行到main()函数中的add(a,b)时,将a和b的值分别赋给x和y。main(){inta=2,b=3,c;c=add(a,b);printf(%d,c);}例写出下面程序的执行结果。voidchange(intx,inty){intz;z=x;x=y;y=z;}main(){inta=2,b=3;change(a,b);printf(%d,%d,a,b);}原因:在函数调用时,将实参的值赋给形参。此后,形参与实参没有任何关系。即:形参与实参的参数传递是单向的,也称值传送。程执行结果为:2,3例:写出下列程序的执行结果fun2(inta,intb){intc;c=a*b%3;returnc;}fun1(inta,intb){intc;a+=a;b+=b;c=fun2(a,b);returnc*c;}main(){intx=11,y=19;printf(%d\n,fun1(x,y));}程序的执行结果为:4对于不需要提供返回值的函数可以直接用void作为函数类型定义,以表明此函数返回值为无类型或空类型。3、void函数voidprint_star(intn){inti;for(i=1;i=n;i++)printf(******************\n);}例如,下面的函数定义:4、函数原型(函数的声明)C语言规定:除返回值为int型的函数外,函数定义应在函数调用之前。main(){floata=2,b=3,c;c=add(a,b);printf(%f\n,c);}floatadd(x,y)floatx,y;{floatz;z=x+y;returnz;}floatadd(x,y)floatx,y;{floatz;z=x+y;returnz;}main(){floata=2,b=3,c;c=add(a,b);printf(%f\n,c);}左边的程序存在编译错误。如果函数的返回值不是int型,而且函数的定义写在函数调用之后,则应该在函数调用之前写出函数的原型(也叫函数说明)。格式:类型符函数名(参数类型1,···);或:类型符函数名(类型符形参1,···);main(){floata=2,b=3,c;floatadd(float,float);c=add(a,b);printf(%f\n,c);}floatadd(x,y)floatx,y;{floatz;z=x+y;returnz;}前面的程序可以改为:实例:判定素数。#includestdio.h#includemath.hintisprime(int);voidmain(){intx=35;if(isprime(x))printf(%d是素数。\n,x);elseprintf(%d不是素数。\n,x);}intisprime(inta){inti;for(i=2;i=(int)sqrt(a);i++)if(a%i==0)return0;return1;}数组作为函数参数分两种情况:一、数组元素作为实参(传值,传一个值)二、数组名作为实参和形参(传地址、传整个数组)一、数组元素作为实参由于数组元素与相同类型的简单变量地位完全一样;因此,数组元素作函数参数也和简单变量一样,也是值的单向传递,即“值传送”。二、数组名作实、形参注意:1.用数组名作函数参数,应该在主调函数和被调用函数分别定义数组。2.实参数组与形参数组类型应一致。3.实参数组和形参数组大小可以不一致,但要求形参数组得到实参数组全部元素的值,则应当指定形参数组与实参数组大小一样。4.数组名作函数参数时,不是“值传递”,不是单向传递,而是把实参数组的起始地址传递给形参数组,这样两个数组就共占同一段内存单元。例:用选择法对数组中10个元素按由小到大排序。Voidsort(intarray[],intn){inti,j,k,t;for(i=0;in-1;i++){k=i;for(j=i+1;jn;j++)if(array[j]array[k])k=j;t=array[k];array[k]=array[j];array[j]=t;}}main(){inta[10],i;for(i=0;i10;i++)scanf(“%d”,&a[i]);printf(“\n”);sort(a,10);for(i=0;i10;i++)printf(“%d”,a[i]);printf(“\n”);}例:有一个3*4矩阵,示其中最大元素。maxvalue(intarray[][4]){int,i,j,k;max;max=array[0][0];for(i=0;i3;i++)for(j=0;j4;j++)if(array[i][j]max)max=array[i][j];return(max);}main(){staticinta[3][4]={{1,3,5,7},{2,4,6,8},{0,2,4,7}};printf(“maxvalueis%d”,maxvalue(a));}