版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第八章函数(很主要)第1页第1页主要内容
8.
1
概述
8.2函数定义普通形式
8.3函数参数和函数值
8.4函数调用
8.5函数嵌套调用
8.6函数递归调用
8.7数组作为函数参数
8.
8局部变量和全局变量
8.9变量存储类别
8.10内部函数和外部函数练习8函数概念函数定义与调用函数递归调用变量作用域函数作用域第2页第2页按功效划分模块●可读性和可理解性都比较好●可验证性比较好●可重组性比较好模块化程序设计基本概念模块化程序设计是指把一个大程序按人们能理解大小规模进行分解。8.1概述第3页第3页C是模块化程序设计语言C程序结构第4页第4页一个较大程序可分为若干个程序模块,每一个模块用来实现一个特定功效在高级语言中用子程序实现模块功效。子程序由函数来完毕一个C程序可由一个主函数和若干个其它函数构成函数是C语言程序中最小结构化模块一个函数将实现一个功效,函数是通过调用被执行函数间调用关系由主函数调用其它函数,其它函数也能够互相调用。同一个函数能够被一个或多个函数调用任意多次一个函数在调用之前,必须先定义,有时还要对已定义函数进行阐明一个C程序必须有且只能有一个名为main主函数C程序执行总是从main函数开始,在main中结束第5页第5页函数间调用第6页第6页例8.1函数调用简朴例子#include<stdio.h>voidmain(){
voidprintstar();/*对printstar函数申明*/
voidprint_message();/*对print_message函数申明*/
printstar();/*调用printstar函数*/
print_message();/*调用print_message函数*/
printstar();/*调用printstar函数*/}第7页第7页voidprintstar()/*定义printstar函数*/{
printf("****************\n");}voidprint_message()/*定义print_message函数*/{
printf("Howdoyoudo!\n");}运营情况下列:****************Howdoyoudo!****************第8页第8页阐明(1)一个C程序由一个或多个程序模块构成,每一个程序模块作为一个源程序文献。对于较大程序,通常将程序内容分别放在若干个源文献中,再由若干源程序文献构成一个C程序。这样便于分别编写、分别编译,提高调试效率。一个源程序文献可认为多个C程序公用。(2)一个源程序文献由一个或多个函数以及其他有关内容(如命令行、数据定义等)构成。一个源程序文献是一个编译单位,在程序编译时是以源程序文献为单位进行编译,而不是以函数为单位进行编译。(3)C程序执行是从main函数开始,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序运营。第9页第9页(4)全部函数都是平行,即在定义函数时是分别进行,是相互独立。一个函数并不从属于另一函数,即函数不能嵌套定义。函数间能够相互调用,但不能调用main函数。main函数是系统调用。(5)从用户使用角度看,函数有两种:①标准函数,即库函数。这是由系统提供,用户无须自己定义这些函数,能够直接使用它们。不同C系统提供库函数数量和功效会有一些不同,但许多基本函数是共同。②用户自己定义函数。用以处理用户专门需要。第10页第10页(6)从函数形式看,函数分两类:①无参函数。无参函数普通用来执行指定一组操作。在调用无参函数时,主调函数不向被调用函数传递数据。②有参函数。主调函数在调用被调用函数时,通过参数向被调用函数传递数据。第11页第11页8.2函数定义普通形式函数头函数体函数类型函数名(){
申明部分 语句部分}合法标识符存储类和数据类型8.2.1无参函数定义普通格式数据类型:
指该函数返回值类型,函数无返回值时用void第12页第12页8.2.2有参函数定义普通形式函数类型函数名(形式参数表列){
阐明部分 语句部分}办法1:intmax(intx,inty){……}办法2:intmax(x,y)intx,y;{……}第13页第13页8.2.3空函数定义空函数普通形式为:类型标识符函数名(){}主调函数调用空函数时,只表明这里要调用一个函数,但函数本身什么工作也不做,以后扩充函数功效时补充上第14页第14页函数定义举例例1有参函数
intmax(intx,inty){
intz;
z=x>y?x:y;
return(z);}或doublemax(x,y)doublex,y;{doubled;d=x>y?x:y;returnd;}例2无参函数
voidprintstar(){
printf(“**********\n”);}或
voidprintstar(void){
printf(“**********\n”);}例空函数
dummy(){}函数体为空,最简朴函数函数名下行给出参数数据类型在括号内函数参数名前给出参数数据类型第15页第15页8.3函数参数和函数值
8.3.1形式参数和实际参数大多数情况下,主调函数和被调用函数之间有数据传递关系形式参数定义函数时函数名后面括号中变量名称为“形式参数”(简称“形参”)实际参数主调函数中调用一个函数时,函数名后面括号中参数(能够是一个表示式)称为“实际参数”(简称“实参”)函数返回值return后面括号中值作为函数带回值(称函数返回值)第16页第16页c=max(a,b);(main函数)(max函数)max(intx,inty){intz;z=x>y?x:y;return(z);}#include<stdio.h>voidmain(){intmax(intx,inty);inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis%d",c);}intmax(intx,inty){intz;z=x>y?x:y;return(z);}形参实参例8.2调用函数时数据传递:比较两个数并输出大者运营情况下列:7,8↙Max
is
8
通过函数调用,可使两个函数中数据发生联系。第17页第17页关于形参与实参阐明:(1)在定义函数中指定形参,在未出现函数调用时,它们并不占内存中存储单元。只有在发生函数调用时,函数max中形参才被分派内存单元。在调用结束后,形参所占内存单元也被释放。(2)实参能够是常量、变量或表示式,比如:
max(3,a+b);但要求它们有拟定值。在调用时将实参值赋给形参。第18页第18页(3)在被定义函数中,必须指定形参类型。(4)实参与形参类型应相同或赋值兼容。(5)值传递:实参向形参数据传递是单向“值传递”,只能由实参传给形参,而不能由形参传回来给实参。
在调用函数时,给形参分派存储单元,并将实参相应值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。第19页第19页8.3.2函数返回值函数返回值是通过函数调用使主调函数得到确实定值比如:例8.2中,max(2,3)值是3,max(5,2)值是5。赋值语句将这个函数值赋给变量c第20页第20页C语言中,函数返回值是通过带有表示式返回语句来实现,函数返回值是函数之间信息互换一个手段。普通格式:return<表示式>;
或
return(<表示式>);
或
return;带有表示式返回语句详细实现过程下列:(1)先计算return语句中<表示式>值。(2)依据函数数据类型对<表示式>类型进行转换,将<表示式>类型转换为函数数据类型。(3)将<表示式>转换后值和类型返回给调用函数。(4)将程序流控制权交给调用函数,执行其后语句。不带有表示式返回语句,只执行环节(4),其它环节将不执行。比如:
max(intx,inty){return(x>y?x:y);}第21页第21页阐明:(1)函数返回值是通过函数中return语句取得。一个函数中能够有一个以上return语句,执行到哪一个return语句,哪一个语句起作用。假如一个函数中无return语句,该函数体右花括号含有return语句作用。(2)函数返回值应当属于某一个拟定类型,在定义函数时指定函数返回值类型。比如:下面是3个函数首行:intmax(floatx,floaty)/*函数值为整型*/charletter(charc1,charc2)//函数值为字符型doublemin(intx,inty)//函数值为双精度型
注意:凡不加类型阐明函数,自动按整型处理。第22页第22页(3)在定义函数时指定函数类型普通应当和return语句中表示式类型一致。假如函数值类型和return语句中表示式值不一致,则以函数类型为准。(切记!)对数值型数据,能够自动进行类型转换。即函数类型决定返回值类型。(4)对于不带回值函数,应当用“void”定义函数为“无类型”(或称“空类型”)。此时在函数体中不得出现return语句。
第23页第23页例有返回值函数
intmax(intx,inty){
intz;
z=x>y?x:y;
return(z);}例无返回值函数
voidswap(intx,inty){
inttemp;
temp=x;
x=y;
y=temp;}无return语句第24页第24页例A8.1一个没有返回值函数#include<stdio.h>voidprintstart(int,char);voidmain(){intn;charch;printf("Inputn:");scanf("%d",&n);printf("Inputchar:");scanf("%c",&ch);printf("\n");printstart(n,ch);}voidprintstart(intn,charc){inti,j;for(i=1;i<=n;i++){for(j=n-1;j>=i;j--)printf("");for(j=1;j<=2*i-1;j++)printf("%c",c);printf("\n");}return;}运营结果:分析、思考?!第25页第25页8.4函数调用8.4.1函数调用普通形式概念C语言程序事实上是函数串一个完整C程序能够由若干个函数构成,其中必须有一个且只能有一个主函数main()。C程序总是从主函数开始执行(无论它在程序中什么位置),而其它函数只能被调用一个完整C程序中所有函数能够放在一个文献中,也能够放在多个文献中C语言中函数没有从属关系,各函数之间互相独立,能够互相调用。C函数不能嵌套定义第26页第26页函数调用普通形式阐明:(1)假如是调用无参函数,则“实参表列”能够没有,但括弧不能省略。(2)假如实参表列包括多个实参,则各参数间用逗号隔开。实参与形参个数应相等,类型应匹配。实参与形参按顺序相应,一一传递数据。(3)假如实参表列包括多个实参,对实参求值顺序并不是拟定,有系统按自左至右顺序求实参值,有系统则按自右至左顺序。函数名(实参表);注意:实参与形参个数相等,类型一致,按顺序一一相应第27页第27页例8.4实参求值顺序#include<stdio.h>voidmain(){intf(inta,intb);/*函数申明*/inti=2,p;p=f(i,++i);/*函数调用*/printf("%d\n",p);}
intf(inta,intb)/*函数定义*/{intc;if(a>b)c=1;elseif(a==b)c=0;elsec=-1;return(c);}
第28页第28页假如按自左至右顺序求实参值,则函数调用相称于f(2,3)
假如按自右至左顺序求实参值,则函数调用相称于f(3,3)
对于函数调用
inti=2,p;p=f(i,++i);注意:尽也许避免容易引发歧义写法第29页第29页8.4.2函数调用方式1.函数语句把函数调用作为一个语句。这时不要求函数带回值,只要求函数完毕一定操作。
例printstar();printf(“Hello,World!\n”);2.函数表示式函数出现在一个表示式中,这种表示式称为函数表示式。这时要求函数带回一个拟定值以参与表示式运算。比如:c=2*max(a,b);第30页第30页3.函数参数函数调用作为一个函数实参。比如:m=max(a,max(b,c));其中max(b,c)是一次函数调用,它值作为max另一次调用实参。m值是a、b、c三者中最大者。第31页第31页8.4.3对被调用函数申明和函数原型1.首先被调用函数必须是已经存在函数(是库函数或用户自己定义函数)。但光有这一条件还不够。3.假如使用用户自己定义函数,而该函数位置在调用它函数(即主调函数)后面,应当在主调函数中对被调用函数作申明。2.假如使用库函数,还应当在本文献开头用#include命令将调用相关库函数时所需用到信息“包括”到本文献中来。第32页第32页函数原型普通形式为:1.函数类型函数名(参数类型1,参数类型2……);2.函数类型函数名(参数类型1参数名1,参数类型2参数名2……);
申明作用是把函数名、函数参数个数和参数类型等信息告知编译系统,以便在碰到函数调用时,编译系统能正确辨认函数并检查调用是否合法。第33页第33页注意:
函数“定义”和“申明”区别:函数定义是指对函数功效确实立,包括指定函数名,函数值类型、形参及其类型、函数体等,它是一个完整、独立函数单位。函数申明作用则是把函数名字、函数类型以及形参类型、个数和顺序告知编译系统,以便在调用该函数时系统按此进行对照检查。第34页第34页函数申明方法在程序中,要调用函数先要定义好(编程者或系统已定义),定义好函数,在调用前通常还需要说明。作用:告诉编译系统函数类型、参数个数及类型,方便检验关于函数说明分为以下3种情况:必须说明:函数定义在后,调用在前,而且函数定义时有数据类型说明时无须说明:当函数在定义时省略了数据类型说明可说明也可不说明:函数定义在前,调用在后,通常不说明函数定义与函数说明不同函数说明位置:程序数听说明部分(函数内或外)第35页第35页两种函数阐明办法简朴阐明办法<类型>
<函数名>();类型:包括存储类和数据类型阐明符,与定义时同不必给出函数参数及其类型比如:doublemax();
…
doublemax(x,y)
doublex,y;
{
doubled;
d=x>y?x:y;
returnd;
}简朴阐明第36页第36页原型阐明办法(VC++6.0要求)<类型>
<函数名>(<参数类型阐明表>);类型:包括存储类和数据类型阐明符,与定义时同参数类型阐明表给出所有参数类型和名称,多个参数用逗号分隔也可省略参数名称,但要用参数类型表示出参数个数比如:doublemax(double
x,doubley);//doublemax(double,double);…doublemax(x,y)doublex,y;{doubled;d=x>y?x:y;returnd;}原型阐明函数阐明能够放在调用函数函数体内,也可放在调用函数函数体外,函数阐明语句中还能够会有相同类型变量,即可一起阐明第37页第37页例函数阐明举例#include<stdio.h>voidmain(){
;/*functiondeclaration*/floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);}floatadd(floatx,floaty){floatz;z=x+y;return(z);}floatadd(float,float)floatadd(float
x,
float
y)
可不能够?第38页第38页#include<stdio.h>floatadd(floatx,floaty){floatz;z=x+y;return(z);}voidmain(){floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);}被调函数出现在主调函数之前,不必函数阐明第39页第39页上节小结第40页第40页B8.1.1.c:#include<stdio.h>voidmain(){
printf(“area=%lf\n“,3.24*3.24*3.14);
printf(“area=%lf\n“,2.137*2.137*3.14);
printf(“area=%lf\n“,0.865*0.865*3.14);
printf(“area=%lf\n“,12.64*12.64*3.14);}B8.1
(B8.1.c)假设有一批圆盘,需要求它们面积。这些圆盘半径分别是:3.24、2.137、0.865、12.64。编程要求(用2种方式):用一个主函数实现(B8.1.1.c)写一个求面积函数供主函数调用(B8.1.2.c)或者:……doublex,area;for
(i=1;i<=4;i++)
scanf(“%lf”,&x);area=x*x*3.14;printf(“area=%lf\n“,area);}{
}思考:对吗?
问题:重复代码、易错、难复用
----引入软件构件思想第41页第41页B8.1.2.c:#include<stdio.h>doublec_area(doublex){returnx*x*3.14;}voidmain(){
printf(“area=%lf\n“,c_area(3.24);
printf(“area=%lf\n“,c_area(2.137);
printf(“area=%lf\n“,c_area(0.865);
printf(“area=%lf\n“,c_area(12.64);}或者:#include<stdio.h>doublec_area(doublex){returnx*x*3.14;}voidmain(){
doublex,area;
for
(i=1;i<=4;i++)
{
area=c_area(x);
printf(“area=%lf\n“,area);
}}自定义函数,功效:求圆面积函数调用第42页第42页#include<stdio.h>voidmain(){intx=7,y=11;printf("x=%d,\ty=%d\n",x,y);printf("swapped:\n");
swap(x,y);printf("x=%d,\ty=%d\n",x,y);}swap(inta,intb){inttemp;temp=a;a=b;b=temp;}711x:y:调用前:调用结束:711x:y:调用:711a:b:711x:y:swap:711x:y:117a:b:temp例A8.2互换两个数,用函数调用思考?第43页第43页概念指在被调函数中还可调用另外一个函数C语言中不限制嵌套调用级别,但嵌套次数越多,执行效率越低main()调用函数a结束a函数b函数调用函数b⑵⑴⑶⑷⑸⑺⑻⑼调用函数cc函数⑹⑽⑾⑿⒀嵌套调用过程8.5函数嵌套调用第44页第44页例A8.3分析下列程序输出结果,从输出信息中掌握函数嵌套调用执行过程#include<stdio.h>voidA();voidB();voidC();voidmain(){printf("I'minmain().\n");A();printf("I'mfinallybackinmain().\n");}
voidC(){ printf("Andnow,I'minC().\n");}voidA(){printf("Now,I'minA().\n");B();printf("Here,I'mbackinA().\n");}voidB(){printf("Now,I'minB().\n");C();printf("backinb().\n");}运营结果:第45页第45页例A8.4求三个数中最大数和最小数差值#include<stdio.h>
intdif(intx,inty,intz);intmax(intx,inty,intz);intmin(intx,inty,intz);voidmain(){inta,b,c,d;scanf("%d%d%d",&a,&b,&c);
d=dif(a,b,c);printf("Max-Min=%d\n",d);}intdif(intx,inty,intz){returnmax(x,y,z)-min(x,y,z);}intmax(intx,inty,intz){intr;r=x>y?x:y;return(r>z?r:z);}intmin(intx,inty,intz){intr;r=x<y?x:y;return(r<z?r:z);}main()调用函数dif输出结束dif函数max函数调用函数max调用函数minmin函数第46页第46页例A8.5要求编写计算x立方函数供主函数调用#include<stdio.h>floata,product;printf("Pleaseinputvalueofa:");scanf("%f",&a);product=cube(a);printf(”Cubeof%.4fis%.4f\n",a,product);return(x*x*x);floatxxaproduct××××1.21.21.728
voidmain(){}
floatcube(){}
注意函数调用编写形式第47页第47页例A8.6编程求出下式值。1k+2k+3k+……+nk(假定k=3,n=5)#include<stdio.h>#defineK3#defineN5voidmain(){
intsum(int,int);printf("Sumof%dthpowersofintegersfrom1to%d=",K,N);printf("%d\n",sum(K,N));}intsum(intk,intn){intpower(int,int);inti,s=0;for(i=1;i<=n;i++)s+=power(i,k);returns;}intpower(intm,intn){inti,p=1;for(i=1;i<=n;i++)p*=m;returnp;}第48页第48页
8.6函数递归调用定义:在调用一个函数过程中出现直接或间接调用该函数本身叫函数递归调用f()调f调f2调f1f1()f2()intf(intx){inty,z;……
z=f(y);…….return(2*z);}intf1(intx){inty,z;……z=f2(y);…….return(2*z);}intf2(intt){inta,c;……c=f1(a);…….return(3+c);}直接调用间接调用第49页第49页能够使用递归两个条件:原问题能够化为新问题,并且新问题与原问题处理办法相同。通过有限次化分,最后问题是已知。举例:使用递归算法典型例子----求5!5!能够化为5*4!4!能够化为4*3!3!能够化为3*2!2!能够化为2*1!1!能够化为1*0!0!=15!=5*4*3*2*1,即120递归算法特点:1、使用递归算法编写程序简练清楚,可读性强。2、使用递归算法编写程序运营起来开销比较大。第50页第50页递归调用过程5!=5*4!4!=4*3!3!=3*2!2!=2*1!1!=1*0!2!=2*1!=23!=3*2!=64!=4*3!=245!=5*4!=120第一阶段:“递推”第二阶段:“回归”0!=11!=1*0!=1递推①递推②递推③递推④递推⑤回归①回归②回归③回归④回归⑤已知递归过程是递推过程和回归过程合成第51页第51页例8.8用递归算法编程求某个正整数阶乘。P173
intfac(intn){intf;if(n<0)printf("n<0,dataerror!");elseif(n==0)f=1;elsef=fac(n-1)*n;return(f);}#include<stdio.h>intfac(intn);voidmain(){intn,y;printf("Inputaintegernumber:");scanf("%d",&n);
y=fac(n);printf("%d!=%15d",n,y);}第52页第52页例A8.7用递归算法编程输出打印下列所表示图案#include<stdio.h>voidfun(charc1,charc2){if(c1>=c2){printf("%c",c1);return;}else{printf("%c",c1);fun(c1+1,c2);printf("%c",c1);}}voidmain(){inti,j,n=5;for(i=1;i<=n;i++){for(j=1;j<=n+5-i;j++)printf("");fun('A','A'+i-1);printf("\n");}}递归调用题目要求会分析第53页第53页8.7数组作为函数参数函数参数几种形式(不全,尚有)变量可作函数实参和形参数组元素可作函数实参数组名可作函数实参和形参,传递是数组元素首地址
8.7.1数组元素作函数实参由于实参能够是表示式,而数组元素能够是表示式构成部分,因此数组元素能够作为函数实参,与用变量作实参同样,是单向传递,即“值传送”方式。第54页第54页例8.10有两个数组a和b,各有10个元素,将它们对应地逐一相比(即a[0]与b[0]比,a[1]与b[1]比……)。假如a数组中元素大于b数组中对应元素数目多于b数组中元素大于a数组中对应元素数目(比如,a[i]>b[i]6次,b[i]>a[i]3次,其中i每次为不同值),则认为a数组大于b数组,并分别统计出两个数组对应元素大于、等于、小于次数。第55页第55页#include<stdio.h>voidmain(){
intlarge(intx,inty);/*函数申明*/inta[10],b[10],i,n=0,m=0,k=0;
printf(″enterarraya∶\n″);
for(i=0;i<10;i++)scanf(″%d″,&a[i]);
printf(″\n″);
printf(″enterarrayb∶\n″);
for(i=0;i<10;i++)scanf(″%d″,&b[i]);
printf(″\n″);
for(i=0;i<10;i++){
if(large(a[i],b[i])==1)n=n+1;
elseif(large(a[i],b[i])==0)m=m+1;
elsek=k+1;}数组元素作函数实参第56页第56页printf("a[i]>b[i]%dtimes\na[i]=b[i]%dtimes\na[i]<b[i]%dtimes\n",n,m,k);if(n>k)printf("arrayaislargerthanarrayb\n");elseif(n<k)printf("arrayaissmallerthanarrayb\n");
elseprintf("arrayaisequaltoarrayb\n");}large(intx,inty){intflag;
if(x>y)flag=1;
elseif(x<y)flag=-1;
elseflag=0;
return(flag);}第57页第57页运营情况下列:
enterarraya:
1357986420↙enterarrayb∶
5389135604↙
a[i]>b[i]4timesa[i]=b[i]1timesa[i]<b[i]5times
arrayaissmallerthanarrayb第58页第58页8.7.2数组名作函数参数用数组名作函数参数时,此时形参应该用数组名或用指针变量。(见第十章)把实参数组首元素地址传递给形参,两个数组共占用同一段内存单元,不是把数组元素值传递给形参(注意与变量作函数参数情况不同)在主调函数与被调函数分别定义数组,且类型应一致一维形参数组大小(多维数组第一维)可不指定形参数组名是地址变量第59页第59页#include<stdio.h>voidmain(){
floataverage(floatarray[10]);//函数申明floatscore[10],aver;inti;
printf(″input10scores:\n″);
for(i=0;i<10;i++)
scanf(″%f″,&score[i]);
printf(″\n″);
aver=average(score);
printf(″averagescoreis%5.2f\n″);ver);}实参用数组名例8.11有一个一维数组score,内放10个学生成绩,求平均成绩。floataverage(float
array[10]){
inti;floataver,sum=array[0];
for(i=1;i<10;i++)sum=sum+array[i];aver=sum/10;
return(aver);}运营情况下列:
input10scores:
100567898.576879967.57597↙
averagescoreis83.40
..2109score562312….….88array形参用数组定义,floatarray[]第60页第60页#include<stdio.h>voidmain(){
floataverage(floatarray[],intn);
floatscore_1[5]={98.5,97,91.5,60,55};
floatscore_2[10]={67.5,89.5,99,69.5,
77,89.5,76.5,54,60,99.5};
printf(“theaverageofclassAis%6.2f\n”,
average(score_1,5));printf(“theaverageofclassBis%6.2f\n”,
average(score_2,10));}floataverage(floatarray[],intn){
inti;floataver,sum=array[0];
for(i=1;i<n;i++)sum=sum+array[i];
aver=sum/n;
return(aver);}例8.12形参数组不定义长度第61页第61页例8.13用选择法对数组中10个整数按由小到大排序。
所谓选择法就是先将10个数中最小数与a[0]对换;再将a[1]到a[9]中最小数与a[1]对换……每比较一轮,找出一个未经排序数中最小一个。共比较9轮。未排序时情况:a[0]a[1]a[2]a[3]a[4]36194将5个数中最小数1与a[0]对换:16394将余下4个数中最小数3与a[1]对换
13694将余下3个数中最小数4与a[2]对换
13496将余下2个数中最小数6与a[3]对换
13469第62页第62页#include<stdio.h>voidmain(){voidsort(intarray[],intn);inta[10],i;
printf(″enterthearray\n″);
for(i=0;i<10;i++)scanf(″%d″,&a[i]);
sort(a,10);
printf(″thesortedarray∶\n″);
for(i=0;i<10;i++)printf(″%d″,a[i]);
printf(″\n″);}voidsort(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;
}}第63页第63页
8.7.3.多维数组名作函数参数用多维数组名作为函数实参和形参。在被调函数中对形参数组定义时能够指定每一维大小,也可不指定第一维大小。第64页第64页例8.14有一个3*4矩阵,求所有元素中最大值#include<stdio.h>voidmain(){
max_value(intarray[][4]);
int[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}};
printf(″maxvalueis%d\n″,max_value(a));}max_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);}运营结果下列:Maxvalueis34第65页第65页8.8局部变量和全局变量8.8.1局部变量是在一个函数内部定义变量,是内部变量,它只在本函数范围内有效举比如右floatf1(inta)//函数f1{Intb,c;…}floatf2(intx,inty)//函数f2{Inti,j;…}voidmain()//主函数{Intm,n;…}a,b,c有效x,y,i,j有效m,n有效第66页第66页说明主函数中定义变量也只在主函数中有效不同函数中能够使用相同名字变量,代表不同对象形式参数也是局部变量在一个函数内部,能够在复合语句(分程序或程序块)中定义变量,这些变量只在本复合语句中有效voidmain()//主函数{Inta,b;… { Intc; c=a+b; … } …}c在此范围有效a,b在此范围有效第67页第67页在相关作用域中定义同名变量作用域要求在同一个作用域内不能定义同名变量在不同作用域内能够定义同名变量小作用域变量将屏蔽大作用域同名变量程序分析{
inta=9;
{inta;
a=6;
printf(“a=%d\n”,a);
}
printf(“a=%d\n”,a);}a=6a=9第68页第68页#include<stdio.h>voidmain(){inta,b;a=5;b=10;printf(“%d,%d\n”,a,b);{doublea=1.5;b=20;printf(“%lf,%d\n”,a,b);{chara=‘k’;b=30;
printf(“%c,%d\n”,a,b);}
printf(“%lf,%d\n”,a,b);}b=40;
printf(“%d,%d”,a,b);}例A8.8分析下列程序输出结果,考察静态局部变量值。运营结果下列:5,101.500000,20K,301.500000,305,40第69页第69页8.8.2全局变量是在函数之外定义变量,也称为外部变量有效范围为从定义变量位置开始到本源文献结束在同一个源文件中,若外部变量与局部变量同名,则在局部变量作用范围内外部变量不起作用intp=1,q=5;floatf1(inta){…….}charc1,c2;charf2(intx,inty){……}voidmain(){…….}c1,c2作用范围p,q作用范围普通商定全局变量名第一个字母用大写字母。第70页第70页例8.16外部变量与局部变量#include<stdio.h>inta=3,b=5;int
max(inta,intb){
intc;c=a>b?a:b;return(c);}void
main(){inta=8;
printf("max=%d",max(a,b));}运营结果:max=8#include<stdio.h>inta=4,b=5;voidfunprint(intx,inty){
printf(“%d,%d\n”,x+a,y+b);return;}voidmain(){inta,x;
a=2;
x=3;
b=1;
funprint(a,x);}自己分析结果?第71页第71页例8.15有一个一维数组,内放10个学生成绩,写一个函数,求出平均分、最高分和最低分。#include<stdio.h>floatMax=0,Min=0;/*全局变量*/voidmain(){
floataverage(floatarray[],intn);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);
}函数调用只能带回一个返回值,可利用全局变量增长函数间联系渠道,通过函数调用得到一个以上值,另见练习8.9
第72页第72页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);}运营情况下列:9945789710067.589926643↙max=100.00min=43.00average=77.65
改为:floatMax=Min=array[0];能够吗?第73页第73页第74页第74页提议:不必要时不要使用全局变量,原因下列①全局变量在程序所有执行过程中都占用存储单元,而不是仅在需要时才开辟单元②使用全局变量过多,会减少程序清楚性。在各个函数执行时都也许改变外部变量值,程序容易犯错。因此,要限制使用全局变量③减少函数通用性由于函数在执行时要依赖于其所在外部变量。假如将一个函数移到另一个文献中,还要将相关外部变量及其值一起移过去。但若该外部变量与其它文献变量同名时,就会出现问题,减少了程序可靠性和通用性。普通要求把C程序中函数做成一个封闭体,除了能够通过“实参——形参”渠道与外界发生联系外,没有其它渠道。第75页第75页8.9变量存储类别8.9.1动态存储方式与静态存储方式每一个变量和函数有两个属性:数据类型和数据存储类别存储类别指是数据在内存中存储办法,分为两大类:静态存储类和动态存储类,详细包括四种:自动类(auto)静态类(static)存储器类(register)外部类(extern)变量有作用域和生存期两方面性质作用域:可见性生存期:存在性从变量作用域(即从空间)角度来分,可分为局部变量和全局变量从变量存在时间来分,有静态存储和动态存储方式静态存储:在程序运营期间分派固定存储空间动态存储:在程序运营期间依据需要进行动态分派存储空间回顾第76页第76页程序区静态存储区动态存储区外部变量、局部静态变量形参变量局部动态变量(auto,register)函数调用现场保护和返回地址等存储空间分为三部分用户区第77页第77页
8.9.2auto变量自动类使用auto阐明,能够省略变量缺省为auto作用域:函数体或分程序内调用该函数时系统会给它们分派存储空间,在函数调用结束时就自动释放这些存储空间在函数体中autointb,c=3;intb,c=3;两者等价第78页第78页在函数开始定义,在整个函数内可访问定义在分程序开始,只能在{}内起作用第79页第79页8.9.3用static申明局部变量静态类使用static关键字阐明变量作用域与auto类型相同作用域:函数体或分程序内但是其生存期从程序开始执行到程序结束阐明静态局部变量属于静态存储类别,在静态存储区内分派存储单元,在整个运营期间都不释放静态局部变量在编译时赋初值,且只赋一次,以后每次调用函数时不再重新赋初值而保留上次函数调用结束时值若定义局部变量时不赋初值,则编译时静态局部变量自动赋初值0(对数值型变量)或空字符(对字符变量)即使静态局部变量在函数调用结束后仍然存在,但其它函数不能引用第80页第80页获取故意义变量值办法变量默认值变量被初始化定义或阐明变量时,对变量赋初值类型默认值外部类和静态类整型变量0浮点型变量0.0字符型变量空字符自动类和存储器类无默认值未赋初值时无意义无意义值不能被引用第81页第81页编译程序依据变量定义为其分派指定字节内存单元地址1000inta=1,b;staticintc;abc4字节4字节4字节地址1004地址4000…...内存10随机数……变量在内存中表示在函数内第82页第82页例A8.9局部静态变量值含有可继承性main(){voidincrement(void);increment();increment();increment();}voidincrement(void){intx=0;x++;printf(“%d\n”,x);}main(){voidincrement(void);increment();increment();increment();}voidincrement(void){staticintx=0;x++;printf(“%d\n”,x);}运营结果:111运营结果:123第83页第83页#include<stdio.h>intf(inta){ autob=0; staticc=3; b=b+1; c=c+1; return(a+b+c);}voidmain(){inta=2,i;for(i=0;i<3;i++)printf(“%d”,f(a));}例8.17分析下列程序输出结果,考察静态局部变量值。运营结果下列:789第几次调用调用时初值调用结束时值bcbca+b+c103147204158305169第几次调用调用时初值调用结束时值bcbca+b+c103147204158305169第84页第84页8.9.4
register变量存储器类用关键字register作申明假如有一些变量使用频繁,则为存取变量值要花费不少时间。为提升执行效率,C语言允许将局部变量值放在CPU中存储器中,需要用时直接从存储器取出参与运算,不必再到内存中去存取。由于对存储器存取速度远高于对内存存取速度,因此这样做能够提升执行效率。变量作用域与auto类型相同作用域:函数体或分程序内但是能够放入CPU通用存储器中,快速存取只有局部自动变量和形式参数能够作为存储器变量例:
registerintm;第85页第85页8.9.5用extern声明外部变量定义位置在函数体外面(extern可以缺省)变量作用域定义位置后整个程序阐明外部变量时,必须用extern在一个文献中使用了另一个文献定义变量在此作用域内,全局变量可认为程序中各个函数所引用。编译时将外部变量分派在静态存储区。用extern来声明外部变量,以扩展外部变量作用域。第86页第86页inta,b;voidchang();main(){
a=4;b=5;
chang();
pritnf(“%d,%d”,a,b);}voidchang(){
intt;
t=a;a=b;b=t;
return;}外部变量,在定义后整个程序可访问第87页第87页1.在一个文献内申明外部变量例8.20用extern申明外部变量,扩展它在程序文献中作用域#include<stdio.h>voidmain(){
intmax(int,int);/*外部变量申明*/
externA,B;
printf("%d\n",max(A,B));}intA=13,B=-8;/*定义外部变量*/intmax(intx,inty)/*定义max函数*/{
intz;
z=x>y?x:y;
return(z);}声明前声明后第88页第88页2.在多文献程序中申明外部变量例8.21用extern将外部变量作用域扩展到其它文献。本程序作用是给定b值,输入A和m,求A×b和Am值。文献file1.c中内容为:#include<stdio.h>intA;/*定义外部变量*/voidmain(){intpower(int);/*函数申明*/intb=3,c,d,m;
printf(″enterthenumberaanditspowerm:\n″);
scanf(″%d,%d″,&A,&m);c=A*b;
printf(″%d*%d=%d\n″,A,b,c);d=power(m);
printf(″%d**%d=%d\n″,A,m,d);}第89页第89页文献file2.c中内容为:externA;/*申明A为一个已定义外部变量*/intpower(intn);{
inti,y=1;
for(i=1;i<=n;i++)y*=A;
return(y);}第90页第90页8.9.6用static申明外部变量在程序设计中,一些外部变量只限于被本文献引用,而不能被其它文献引用。这时能够在定义外部变量时加一个staitic申明。比如:
file1.cfile2.c
staticintA;externintA;
voidmain()voidfun(intn)
{{…
…A=A*n;
}第91页第91页8.9.7关于变量申明和定义定义性申明:需要建立存储空间(如:inta;)申明。引用性申明:不需建立存储空间申明(externa;)。注意:申明包括定义,但并非所有申明都是定义。对“inta;”而言,它既是申明,又是定义。而对“externa;”而言,它是申明而不是定义。第92页第92页
8.9.8存储类别小结(1)从作用域角度分,有局部变量和全局变量。它们采用存储类别下列:局部变量包括:自动变量、静态局部变量、存储器变量。形式参数能够定义为自动变量或存储器变量。全局变量包括:静态外部变量、外部变量。(2)从变量存在时间来区别,有动态存储和静态存储两种类型。静态存储是程序整个运营时间都存在,而动态存储则是在调用函数时暂时分派单元。动态存储:自动变量、存储器变量、形式参数。静态存储:态局部变量、静态外部变量、外部变量。第93页第93页(3)从变量值存储位置来区别,可分为:内存中静态存储区:静态局部变量、静态外部变量、外部变量。内存中动态存储区:自动变量和形式参数。CPU中存储器:存储器变量。(4)作用域和生存期作用域可见性:在某个文献或函数内有效生存期存在性:在某一时刻存在
第94页第94页例文献file1.cinta;main(){…….…….f2;…….f1;…….}f1(){autointb;………f2;……..}f2(){staticintc;………}C作用域b作用域a作用域mainf2f1mainf1f2mainb生存期:c生存期:a生存期:第95
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 通信设备制作协议
- 劳动合同主体变更的合同格式
- 特色农副产品销售合同
- 琴行老师聘用协议
- 品质服务项目采购合同
- 材质保证书样本格式
- 果树种植苗木采购合同合同
- 电器购销合同格式
- 防排烟系统施工劳务分包合同
- 房屋买卖协议更名指南
- 2024年公司股权转让中介的协议范本
- 2024秋期国家开放大学《建筑工程项目管理》一平台在线形考(作业1至4)试题及答案
- 护理质控组长岗位竞聘
- 苏教版六年级上册数学期中考试试题带答案
- 北京市海淀区九年级(上)期中数学试卷-
- 吉祥物的设计 课件 2024-2025学年人教版(2024)初中美术七年级上册
- 2024年中国电动卷帘电机市场调查研究报告
- “四史”(改革开放史)学习通超星期末考试答案章节答案2024年
- 东莞市房屋建筑和市政基础设施工程施工招标文件
- 2024粤东西粤北地区教师全员轮训校长领导培训心得
- 人教版(2024)一年级道德与法治上册第二单元第8课《课余生活真丰富》教学课件
评论
0/150
提交评论