课件程序ch7函数_第1页
课件程序ch7函数_第2页
课件程序ch7函数_第3页
课件程序ch7函数_第4页
课件程序ch7函数_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

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

文档简介

第7章用函数实现模块化程序设计7.1为什么要用函数

7.2怎样定义函数7.3调用函数7.4对被调用函数的声明和函数原型7.5函数应用举例7.6

函数的嵌套、递归调用7.7数组作为函数参数

7.8局部变量和全局变量*7.9变量的存储方式和生存期*7.10内部函数和外部函数7.1为什么要用函数问题:如果程序的功能比较多,规模比较大,把所有代码都写在main函数中,就会使主函数变得庞杂、头绪不清,阅读和维护变得困难有时程序中要多次实现某一功能,就需要多次重复编写实现此功能的程序代码,这使程序冗长,不精炼

一个c程序可由一个主函数和若干个函数构成。 由主函数调用其他函数,其他函数也可互相调用。 同一个函数可以被一个或多个函数调用任意多次。例如:7.1为什么要用函数例:voidprintstar(){printf(“******************\n”);}

voidprint_message(){printf(“Howdoyoudo!\n”);}voidmain(){print_message();printstar();}6点说明:1、一个源程序文件由一个或多个函数组成。一个源程序文件是一个编译单位。2、一个c程序由一个或多个源程序文件组成。3、c程序的执行从main函数开始,调用其他函数后,流程回到main函数,在main函数结束整个函数的运行。4、所有函数在定义时都是互相独立的,一个函数并不从属于另一函数,即不能嵌套定义,函数间可以互相调用,但不能调用main函数。5、从用户角度看,函数分为两种:(1)标准函数,即库函数。由系统提供。(2)用户自定义函数,用来解决用户的专门需要。6、从函数形式看,函数分为两种:(1)无参函数。(2)有参函数。1、无参函数的定义形式

类型标识符函数名()

{声明部分语句}2、有参函数定义的一般形式

类型标识符函数名(形参表列)

{声明部分语句}7.2怎样定义函数无参函数:voidprintstar(){printf(“******************\n”);}voidprint_message(){printf(“Howdoyoudo!\n”);}voidmain(){print_message();printstar();}voidmain(){inta,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);printf(“c=%d\n”,c);

}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}实参形参有参函数:7.3.1函数调用形式

格式:

函数名(实参表列);说明:各实参间用逗号格开。实参与形参的个数应相同,类型应一致。7.3调用函数按出现的位置分,有如下三种函数调用方式:

1、函数语句。

如:“printstar();”。函数不带回值,只完成一定的操作。

2、函数表达式。

如:“c=2*max(a,b);”。要求函数带回确定值,参加表达式运算。

3、函数参数。

如:“m=max(c,max(a,b));”

又如:

“printf(“%d”,max(a,b));”

其中函数max(a,b)作为一个参数。1、形参只在调用时分配内存单元,调用结束,被释放。2、形参、实参个数、类型、顺序必须一致。关于形参与实参的5点说明:7.3.2函数参数和返回值3、参数传递单向,值传递。实参形参,不能由形参传回来给实参。

(一)形式参数与实际参数4、实参可以是常量、变量或表达式,必须有确定的值。在调用时,将实参的值赋给形参变量。例:max(3,a+b);5、在被定义的函数中,必须指定形参类型。(二)函数的返回值

对函数值的说明:

1、函数返回值是通过函数中的return语句获得的。若不需要从被调用函数带回函数值,可以不要return语句。

2、定义函数时要指定函数的类型。一般应与return语句中的表达式类型一致。如:intmax(x,y) 函数值为整型

charletter(c1,c2) 函数值为字符型 凡不加说明的函数,自动按整型处理。

3、为了明确表示“不带回值”,可以用“void”定义“无类型”(或称“空类型”)。如

voidprintstar(){……}

这样,系统就保证不使函数带回任何值。此时使用:“a=printstar();”就是错的。7.4对被调用函数的声明和函数原型在一个函数中调用另一个函数需要具备如下条件:(1)被调用函数必须是已经定义的函数(是库函数或用户自己定义的函数)(2)如果使用库函数,应该在本文件开头加相应的#include指令(3)如果使用自己定义的函数,而该函数的位置在调用它的函数后面,应该声明。(即向编译系统声明将要调用此函数,并将有关信息通知编译系统。)例:voidmain(){floatadd(floatx,floaty);//对被调函数声明*/

floata,b,c;scanf(“%f,%f”,&a,&b);c=add(a,b);printf(“Sumis%f\n”,c);}floatadd(floatx,floaty)//add函数首部{floatz;//函数体

z=x+y;return(z);}在函数声明中也可以不写形参名,只写形参的类型。如:

floatadd(float,float);

以上的函数声明称为函数原型(functionprototype)。

函数原型的一般形式为:

函数类型函数名(参数类型1,参数类型,…...);7.5函数应用举例

例1:打印:****************************hello!****************************voidprintstar(){printf(“******************\n”);}

voidprint_message(){printf(“****hello!****\n”);}voidmain(){printstar();print_message();printstar();}例2:求n!

LI8_N!.Cdoublejie(intx){inti;doublek=1;for(i=1;i<=x;i++)k=k*i;return(k);}voidmain(){doublejie(intx);intn;doublejc;scanf("%d",&n);jc=jie(n);printf("jc=%e\n",jc);}

练习:求Cnmdoublefac(intn) {inti;doublek=1;for(i=1;i<=n;i++)k*=i;return(k);}voidmain(){intn=5,m=3;doublecnm;

cnm=fac(n)*fac(m)/fac(n-m);printf(“\n%d\n”,cnm);}练习:求1!+2!+3!+…+n!

li8_nhe.cdoublejch(intx){inti;doublek=1;for(i=1;i<=x;i++){k=k*i;}return(sum);}voidmain(){intn;doublejc;scanf("%d",&n);jc=jch(n);printf("jc=%e\n",jc);},sum=0sum=sum+k;?

prime(?){inti;for(i=2;i<m;i++)if(m%i==0)return0;return1;}intmint例3:判断一个数是否素数。voidmain(){intn,k;scanf(“%d”,&n);k=prime(n)if(k==1)printf(“%d是素数。\n”,n);elseprintf(“%d不是素数。\n”,n);}(一)函数的嵌套调用

C语言不能嵌套定义函数,但可以嵌套调用函数,即允许在调用一个函数的过程中,又调用另一个函数。例如:main函数a函数b函数①②③④调用a函数调用b函数⑤⑨⑧⑦⑥结束7.6函数的嵌套、递归调用(二)函数的递归调用

在调用一个函数的过程中,又出现直接或间接地调用该函数本身,称为函数的递归调用。如下是直接调用本身:

intf(x) intx; {inty,z;

….. z=f(y);

….. return(2*z); }间接调用本身:intf1(x)intf2(t)intx;intt;{inty,z;{inta,c;

……

……z=f2(y);c=f1(c);

……

……return(2*z);return(3+c);}}voidage(intn){intc;

if(n==1)c=10;elsec=age(n-1)+2;return(c);}voidmain(){printf(“%d”,age(5));}例4:age(5)=?依次比前一个人大2岁,第1个人2岁。age(n)=10(n=1)C8_7.c

age(n)=age(n-1)+2(n>1)例5:用递归法求n!C8_8.cfloatfac(intn){floatf;if(n==0||n==1)f=1;elsef=fac(n-1)*n;return(f);}voidmain(){intn;floaty;scanf(“%d”,&n);y=fac(n);rintf(“%d!=%15.0f”,n,y);}

(一)数组元素作为函数实参

数组元素作为函数实参,与变量作实参一样,是单向传递,即值传递方式。

(二)数组名作为函数实参

说明:(1)形参数组与实参数组类型一致。(2)把实参数组首地址传给形参。7.7数组作为函数参数例6:求10个学生的平均成绩。C8_11.cfloataverage(floatarray[10]){inti;floataver,sum=array[0];for(i=1;i<10;i++) sum=sum+array[i];aver=sum/10;return(aver);}

例6:求10个学生的平均成绩。C8_11.cvoidmain(){floatscore[10],aver;inti;printf(“input10score:\n”);for(i=0;i<10;i++)scanf(“%f”,&score[i]);printf(“\n”);aver=average(score);printf(“averagescoreis%5.2f”,aver);}说明:1、数组名做函数参数时,不是“值传送”,而是把实参数组的起始地址传递给形参数组,两个数组共占同一段内存单元。这种传递方式叫“地址传送”。当形参数组中元素值变化时,实参数组的对应元素值也要发生相同变化。 这与变量做函数参数时不同。

2、形参数组可以不指定大小,可另设一个参数,传递数组元素个数。例6:求10个学生的平均成绩。floataverage(floatarray[],intn){inti;floataver,sum=array[0];for(i=1;i<n;i++) sum=sum+array[i];aver=sum/n;return(aver);}例6:求10个学生的平均成绩。voidmain(){floatscore[10],aver;inti;printf(“input10score:\n”);for(i=0;i<10;i++)scanf(“%f”,&score[i]);printf(“\n”);

//此处调用函数

printf(“averagescoreis%5.2f”,aver);}aver=average(score,10);练习:数组排序C8_13.cvoidsort(intarray[],intn){}inti,j,k,t;for(i=0;i<n-1;i++) {k=i; for(j=i+1;j<n;j++)if(array[j]<array[k])k=j; t=array[k];array[k]=array[i];array[i]=t;}练习:数组排序C8_13.cvoidmain(){inta[10],i;printf(“enterthearray:\n”);for(i=0;i<10;i++)scanf(“%d”,&a[i]);

//此处调用函数printf(“thesortedarray:\n”);for(i=0;i<10;i++)printf(“%d”,a[i]);printf(“\n”);}sort(a,10);(三)用多维数组作函数参数

说明:可以用多维数组元素作实参。可以用多维数组元素名作实参和形参。在被调函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小,如:

intarray[3][10];写为intarray[][10];注意:第二维及其它高维的大小,不能省略。

练习:有3×4的矩阵,求其中的最大元素。C8_14.cintmax_value(intarray[][4]){}inti,j,k,max;max=array[0][0];for(i=0;i<3;i++)for(j=0;j<4;j++)if(array[i][j]>max)max=array[i][j];return(max);练习:有3×4的矩阵,求其中的最大元素。C8_14.cvoidmain(){int[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}};printf(“Maxvalueis%d\n”,);}max_value(a)局部变量:函数内部定义的变量,只在本函数内部有效。内部变量全局变量:在函数之外定义的变量,也叫外部变量。有效范围:从定义变量位置开始到本源文件结束。外部变量7.8局部变量和全局变量intp=1,q=5;floatf1(inta){intb,c;┊}charc1,c2;charf2(intx,inty){inti,j;┊}voidmain(){intm,n;┊}全局变量c1,c2的作用范围

全局变量p,q的作用范围

例7:求两个数最大值。C1_3.cvoidmain(){inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf(“c=%d\n",c);

}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}

如果在同一源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量被“屏蔽”,不起作用。C8_16.cinta=3,b=5; /*a,b为外部变量*/intmax(inta,intb)/*a,b为形参(局部变量)*/{intc;c=a>b?a:b;return(c);}voidmain(){inta=8;/*a为局部变量*/printf(“%d”,max(a,b));}形参a、b的作用范围运行结果为8

说明:1、使用全局变量可减少形参和实参的个数,减少内存空间。

2、全局变量会使函数通用性降低,会降低程序的清晰性。

3、全局变量在程序的全部执行过程中都占用存储单元。

4、同一源文件中,全局变量与局部变量重名,则在局部变量范围内,全局变量不起作用。floatMax,Min; /*定义两个全局变量*/floataverage(floatarray[],intn){inti;floataver,sum=array[0];Max=Min=array[0];for(i=1;i<n;i++) {if(array[i]>Max)Max=array[i];elseif(array[i]<Min)Min=array[i];sum=sum+array[i]; }aver=sum/n;return(aver);}例8:10个学生成绩,求平均分、最高分、最低分。C8_15.c

voidmain(){floatave,score[10];inti;for(i=0;i<10;i++) scanf(“%f”,&score[i]);

ave=average(score,10);

printf(“max=%6.2f\nmin=%6.2f\naverage=%6.2f\n”,Max,Min,ave);}思考:用全局变量实现求1!+2!+3!+…+n!的和。

li8_nhe.c练习:编程两个函数,分别求两个正整数的最大公约数与最小公倍数,用主函数调用这两个函数,并输出结果,两个正整数由键盘输入。

要求:(1)不用全局变量,用函数值返回求最大公约数与最小公倍数。Gygbj.c

(2)用全局变量的方法,分别用两个函数求出最大公约数与最小公倍数,其值不用函数值带回。将最大公约数与最小公倍数定义为全局变量,再主函数中输出它们的值。Gygbq.c

1、动态存储方式和静态存储方式

静态存储方式:在程序运行期间分配固定存储单元的方式。动态存储方式:在程序运行期间根据需要动态分配存储单元的方式。

变量动态存储方式变量静态存储方式变量生存期角度7.9变量的存储方式和生存期程序区

静态存储区

动态存储区

用户区主要存放全局变量和静态局部变量.程序开始运行时分配空间,运行结束时释放。主要存放(1)函数形参变量(2)自动变量(未加static说明的局部变量)。(3)函数调用时的现场保护和返回地址。在函数调用开始时分配动态存储空间,函数调用结束时释放这些空间。

2、局部变量的存储方式

每个局部变量在定义时可以指定其存储方式,即对每个局部变量的定义除定义其数据类型外,还应定义其存储方式。定义存储方式用auto(自动的)static(静态的)。如:

intf1()intf2(){autointa=1;{staticintb=1;┊┊}}

缺省时为auto

动态局部变量在函数调用时分配、赋初值,调用结束时释放。

静态局部变量在第一次调用时分配、赋初值,调用结束时不释放,其单元及其值仍保留,下次调用时不重新分配,不重新赋初值。在实际应用中,如果希望在函数调用结束后仍保留某个局部变量的值给下次调用时使用,则可定义该变量为静态的。

intf(inta){autointb=0;staticintc=3;b=b+1;c=c+1; return(a+b+c);}voidmain(){inta=2,i;for(i=0;i<3;i++)printf(“%d”

温馨提示

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

评论

0/150

提交评论