资源预览内容
第1页 / 共91页
第2页 / 共91页
第3页 / 共91页
第4页 / 共91页
第5页 / 共91页
第6页 / 共91页
第7页 / 共91页
第8页 / 共91页
第9页 / 共91页
第10页 / 共91页
亲,该文档总共91页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第六章第六章 函函 数数结构化程序设计基础结构化程序设计基础6.1函数的概念 结构化程序设计要求一种自顶向下的设计方法,也就是将复杂结构化程序设计要求一种自顶向下的设计方法,也就是将复杂的系统划分为相对独立的,功能较为单一的子系统的组合。的系统划分为相对独立的,功能较为单一的子系统的组合。 每个子系统称为模块,在每个子系统称为模块,在C语言中表现为函数。语言中表现为函数。复杂问题main()abca1a2b1b2c1c2各模块之间的关系称之为接口。各模块之间的关系称之为接口。优点:优点: 函数实现的功能单一函数实现的功能单一完整,可以独立设计,单完整,可以独立设计,单独调试。易于维护,通用独调试。易于维护,通用性强。性强。【例【例6-1】通过函数求两个数的最大值。】通过函数求两个数的最大值。/*example6-1通过函数求最大值通过函数求最大值*/#includeintGetMax(int,int);/*函数的原型声明函数的原型声明*/voidmain(void)inta,b,c,d;/*说明变量说明变量*/scanf(%d,%d,%d,&a,&b,&c);d=GetMax(a,b);/*调用函数调用函数GetMax求求a、b的较大值赋给的较大值赋给d*/d=GetMax(d,c);/*调用函数调用函数GetMax求求d、c的较大值赋给的较大值赋给d*/printf(TheMaximumofa,b,cis%dn,d);intGetMax(intx,inty)intmax;if(xy)max=x;/*xy成立,成立,x为较大值为较大值*/elsemax=y;/*xy不成立,不成立,y为较大值为较大值*/returnmax;函数的分类及调用过程函数的分类及调用过程 函数可分为标准库函数和用户自定义函数。标准库函数是C语言系统提供的一系列的实现特定功能的模块,如已经学习过的输入输出函数、数学函数、字符串处理函数等等。 对于用户自定义函数,用户必须完整地定义函数的接口以及函数的实现细节,然后通过数据接口调用函数以实现所需的功能 用户自定函数的使用,应包括两个过程: 函数的定义:函数定义的作用就是确定函数的名称、接口、以及内部的实现细节。 函数的调用: 函数的调用是根据数据接口的定义,将实际数据传递给函数,函数执行其功能得到所需结果的过程。【例例6-2】通通过过标标准准函函数数及及用用户户定定义义函函数数实实现现求求字字符符串串中中含含有有的的实际字符的数量,输出结果。实际字符的数量,输出结果。/*example6-2通过函数输出字符串的实际长度通过函数输出字符串的实际长度*/#include#includeintGetStringLength(char*p);/*用户函数原型声明用户函数原型声明*/voidmain(void)charpszStr80;intiStrLen;gets(pszStr);/*调用字符输入函数输入字符串调用字符输入函数输入字符串*/iStrLen=strlen(pszStr);/*调用标准库函数求字符串长度调用标准库函数求字符串长度*/printf(Thestringlengthis%dn,iStrLen);gets(pszStr);iStrLen=GetStringLength(pszStr);/*调用用户定义函数求字符调用用户定义函数求字符串长度串长度*/printf(Thestringlengthis%dn,iStrLen);/*用户定义求字符串长度函数用户定义求字符串长度函数*/*函数名函数名GetStringLength*/*参数参数指向字符的指针指向字符的指针p*/*返回值字符个数,整型返回值字符个数,整型*/intGetStringLength(char*p)intiCount;iCount=0;while(*p!=0)iCount+;p+;returniCount;6.2函数函数的定义和调用的定义和调用函数的基本结构函数的基本结构#includevoidmain(void)inta,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);printf(“%d”c);intmax(intx,inty)intz;z=x=y?x:y;return(z);主主函函数数函函数数体体函数的类型,返回值的类型。函数的类型,返回值的类型。函数名(用标识符命名),函数名(用标识符命名),引用函数的标志,并得到结果。引用函数的标志,并得到结果。函数参数说明表。函数参数说明表。定义!定义!引用!引用!(1)函数的名称(2)函数的类型(3)函数的形式参数(4)函数体函数定义的目的函数定义是要确定如下四点:函数定义是要确定如下四点:名称名称函数的类型函数的类型函数的参数函数的参数函数的功能函数的功能函数的定义函数的定义格式:格式: type函数名函数名(参数说明表参数说明表)内部说明语句内部说明语句;功能语句功能语句;如果函数有返回值,应含如果函数有返回值,应含有有return语句。语句。intmax(intx,inty)intz;z=x=y?x:y;return(z);说明:说明:函数不能嵌套定义,但可以嵌套引用,包括引用自己。函数不能嵌套定义,但可以嵌套引用,包括引用自己。intmax(intx,inty)intcx(intc,intd)/*Error!*/函数如果无返回值,函数如果无返回值,type应说明为空类型应说明为空类型void。函数无参。函数无参数应定义成数应定义成void。void Bell(void) printf(“007”);函数的调用函数的调用调用形式:调用形式: 函数名函数名( (实参表实参表) ) 一般引用方式有三种:一般引用方式有三种:v语语句句形形式:式:max(a,b);v表达式形式:表达式形式:c=max(a,b)*2;v函函数数参参数:数:c=max(a,max(b,d);【例例6-3】函函数数调调用用举举例例,通通过过函函数数求求xn,在在主主函函数数中中输输入入x及及n,并调用该函数,输出结果。,并调用该函数,输出结果。/*example6-3函数调用举例函数调用举例*/#includefloatGetPow(float,int);/*函数原型声明函数原型声明*/voidmain(void)floatx,y;intn;printf(Pleaseinputx,n:);scanf(%f,%d,&x,&n);/*输入输入x,n*/y=GetPow(x,n);/*给出实参列表给出实参列表,调用函数调用函数*/printf(“xn=%fn”,y);/*将函数的返回值赋给将函数的返回值赋给y*/floatGetPow(floatx,intn)/*函数定义函数定义,名称:名称:GetPow*/floatz;inti;z=1;for(i=1;iy?x:y;return(z); 先计算实参的值,从右向左向函数传递调赋值给形参。先计算实参的值,从右向左向函数传递调赋值给形参。23abXy23转移在函数中运行,执行到一个转移在函数中运行,执行到一个return语句,将返回表达式语句,将返回表达式的值。由函数名带回给调用函数。的值。由函数名带回给调用函数。z3函数如果没有函数如果没有return语句,由最后一个语句,由最后一个返回一个不确定的值!返回一个不确定的值!【例例6-4】定定义义返返回回两两个个浮浮点点数数之之和和的的函函数数,在在主主函函数数中中输输入入数数据,并调用函数,输出结果。据,并调用函数,输出结果。/*example6-4通过函数求两个浮点数之和通过函数求两个浮点数之和*/#includefloatfAdd(float,float);/*函数原型声明函数原型声明*/voidmain(void)floata,b,c;printf(Pleaesinputtwonumbera,b:);scanf(%f,%f,&a,&b);c=fAdd(a,b);/*调用函数调用函数*/printf(a+b=%fn,c);/*-*/*函数名函数名fAdd*/*参数:参数:x,y,float型型*/*返回值:返回值:x+y*/*-*/floatfAdd(floatx,floaty)floatz;z=x+y;returnz;关于返回值的几点说明:关于返回值的几点说明:函数可以通过一个函数可以通过一个return语句返回一个值,也可以不返回值,语句返回一个值,也可以不返回值,此时应在定义函数时用此时应在定义函数时用void类型加以说明。类型加以说明。函数中可以出现多个函数中可以出现多个return语句,遇到一个语句,遇到一个return语句,则语句,则返回值,且返回调用函数,继续执行。返回值,且返回调用函数,继续执行。intmax(intx,inty)if(x=y)returnx;returny; 返回值的类型应与函数的类型一致,如不一致,以函数类型返回值的类型应与函数的类型一致,如不一致,以函数类型为准,为准,先转换为函数类型后,先转换为函数类型后,再返回。再返回。intmax(void)floatz;returnz;/*z先转化为整型先转化为整型*/ 为了确保参数和返回值类型正确,一般须在函数调用前对其为了确保参数和返回值类型正确,一般须在函数调用前对其类型和参数的类型加以说明,该说明称之为类型和参数的类型加以说明,该说明称之为原型声明原型声明。intimax(int,int);voidmain(void)intx,y,z;z=imax(x,y);原型声明语句,加;原型声明语句,加;举例:通过函数求举例:通过函数求xn。#includedoublepow(float,int);voidmain(void)inti;for(i=1;i=9;i+)printf(“%d,%fn”,i,pow(2.5,i);doublepow(floatx,intn)inti;doublep=1;for(i=1;i=n;i+)p=p*x;return(p);原型声明。原型声明。定定义义函函数数调用函数。调用函数。专题:函数间的数据传递专题:函数间的数据传递函数在调用的过程中,调用函数和被调函数存在数据的相互传函数在调用的过程中,调用函数和被调函数存在数据的相互传递。数据的传递包括两个方面:递。数据的传递包括两个方面:将值传递给被调函数;将值传递给被调函数;将被调函数的结果返回给调用函数。将被调函数的结果返回给调用函数。调用函数调用函数被调函数被调函数向被调函数传递值。向被调函数传递值。将结果返回给调用函数。将结果返回给调用函数。函数间数据传递方式函数间数据传递方式通过函数参数传值或传地址;通过函数参数传值或传地址;通过返回值传递结果通过返回值传递结果;通过通过全局变量全局变量传递参数或结果。传递参数或结果。传值方式传值方式 通过实参与形参的结合,将通过实参与形参的结合,将数据值传递给形参数据值传递给形参,形参的改变不,形参的改变不影响实参。影响实参。#includeintsplus(int,int);voidmain(void)inta,b,c;scanf(“%d,%d”,&a,&b);c=splus(a,b);printf(“a*b=%dn”,c);intsplus(intx,inty)intz;z=x*y;return(z);调调用用函函数数被被调调函函数数x、y形参。形参。a、b实参变量的值。实参变量的值。传递参数传递参数a:2b:3y:x:32z:6返回值返回值【例【例6-5】参数值传递方式说明举例。】参数值传递方式说明举例。/*example6-5函数参数值传递实例函数参数值传递实例*/#includevoidExamFun(int,int);/*函数原型声明函数原型声明*/voidmain(void)inta,b;printf(请输入两个整数请输入两个整数a,b:);scanf(%d,%d,&a,&b);ExamFun(a,b);/*以实参以实参a、b值传递方式调用函数值传递方式调用函数*/printf(函数调用后函数调用后a的值的值%d,b的值的值%dn,a,b);voidExamFun(intx,inty)/*函数定义函数定义*/intt;t=x;x=y;y=t;/*形参变量形参变量x,y交换交换*/printf(x的值的值%d,y的值的值%dn,x,y);传地址方式传地址方式形参定义为指针,实参为变量的地址,被调函数通过地址可以形参定义为指针,实参为变量的地址,被调函数通过地址可以修改地址对应的变量。修改地址对应的变量。#includevoidswap(int*,int*);voidmain(void)inta,b;scanf(“%d,%d”,&a,&b);if(ab)swap(&a,&b);printf(“n%d,%dn”,a,b);voidswap(int*x,int*y)intt;t=*x;*x=*y;*y=t;用用函函数数实实现现两两个个变变量量a、b值值的的交交换换46ab2000H2400Hxy2400H2000H参数变量是否可以实现交换?参数变量是否可以实现交换?【例【例6-6】采用传递地址方式,通过函数实现变量值的交换。】采用传递地址方式,通过函数实现变量值的交换。/*example6-6,函数参数采用地址传递方式函数参数采用地址传递方式*/*通过函数实现调用函数变量的交换通过函数实现调用函数变量的交换*/#includevoidExchange(int*,int*);/*函数原型声明,参数为指向整型的指针函数原型声明,参数为指向整型的指针*/voidmain(void)inta,b;printf(请输入请输入a,b:);scanf(%d,%d,&a,&b);if(ab)/*如果如果ab调用函数实现调用函数实现a、b的交换的交换*/Exchange(&a,&b);/*调用函数,实参为变量调用函数,实参为变量a,b的地址的地址*/printf(a=%dnb=%dn,a,b);voidExchange(int*x,int*y)/*函数定义函数定义*/intt;t=*x;*x=*y;*y=t;/*通过间接运算,实现形参通过间接运算,实现形参x、y指向对象的交换指向对象的交换*/函数的原型声明如果被调函数是以下三种情况,必须声明。如果被调函数是以下三种情况,必须声明。(1 1)被调函数定义在调用函数之后;)被调函数定义在调用函数之后;(2 2)被调函数是标准库函数;)被调函数是标准库函数;(3 3)被调函数从其他文件连接加入。)被调函数从其他文件连接加入。函数的原型声明语句可以取两种形式:函数的原型声明语句可以取两种形式: 只有参数类型而不带参数名的形式只有参数类型而不带参数名的形式 带有参数名的形式带有参数名的形式函数的原型声明的说明 函数原型声明最好写在主函数之外的程序开始处,如果函数原型声明最好写在主函数之外的程序开始处,如果程序较大,并有自己的头文件时,函数原型声明应统一写在程序较大,并有自己的头文件时,函数原型声明应统一写在头文件中头文件中 。 原则上整型函数、定义在调用语句函数之前的函数可不原则上整型函数、定义在调用语句函数之前的函数可不加原型声明,加原型声明, 标标准准库库函函数数的的原原型型声声明明都都包包含含于于函函数数对对应应的的头头文文件件中中,因因此此,使使用用标标准准库库函函数数时时,应应在在程程序序的的开开始始包包含含对对应应的的头头文件文件 。6.3变量的作用域与生存期变量的作用域与生存期变量是内存数据的抽象,即将内存地址、数据表示变量是内存数据的抽象,即将内存地址、数据表示抽象成一个抽象成一个符号。符号。此外,变量还有此外,变量还有存储类型存储类型,存储类型确定了变量在,存储类型确定了变量在时间上的时间上的生存期和空间上的作用域。生存期和空间上的作用域。按空间的作用域可分为:按空间的作用域可分为:全局变量全局变量局部变量局部变量按时间的生存期可分为:按时间的生存期可分为:静态存储变量静态存储变量动态存储变量动态存储变量变量的四种存储类型变量的四种存储类型自动类型自动类型auto寄存器类型寄存器类型register静态类型静态类型static外部类型外部类型extern变量的说明格式变量的说明格式:存储类型存储类型 类型类型 变量名表;变量名表;确定变量在内存中的表示方法。确定变量在内存中的表示方法。确定变量的生存期和作用域。确定变量的生存期和作用域。该项省略表示该项省略表示auto存储类型。存储类型。auto存储类型存储类型(局部变量局部变量)定义在复合语句的开始处。块内生存、块内有效。定义在复合语句的开始处。块内生存、块内有效。#includevoidmain(void)autointa,b;scanf(“%d,%d”,&a,&b);if(ba)intiTemp;iTemp=a;a=b;b=iTemp;printf(“Max=%d”,a);ab的的作作用用域域iTemp的作用域。的作用域。生存期:生存期:执行到复合语句建立内存执行到复合语句建立内存变量。执行出复合语句变量消变量。执行出复合语句变量消亡。亡。iTempregister存储类型存储类型(局部变量局部变量)作用域和生存期和作用域和生存期和auto相同,相同,差别在于,如果差别在于,如果CPU内部的寄存内部的寄存器空闲,器空闲,则使用寄存器作为变量则使用寄存器作为变量的存储单元,以提高速度。主要的存储单元,以提高速度。主要用于循环变量,且应该是整型和用于循环变量,且应该是整型和字符型。字符型。【例【例6-7】通过函数求两个数的较小值。】通过函数求两个数的较小值。/*example6-7通过函数求两个数的较小值通过函数求两个数的较小值*/#includeintiGetMin(int,int);/*函数原型声明函数原型声明*/voidmain(void)inta,b,c;printf(Pleaseinputtwonumbera,b:);scanf(%d,%d,&a,&b);c=iGetMin(a,b);/*调用调用iGetMin函数函数*/printf(Theminis=%dn,c);intiGetMin(intx,inty)/*函数定义函数定义*/intz;z=xy?x:y;/*取取x、y的最小值赋给的最小值赋给z*/returnz;局部局部static(静态静态)存储类型存储类型作用域:作用域:在说明的复合语句内引用,出了复合语句不可见。在说明的复合语句内引用,出了复合语句不可见。生存期:生存期:从程序开始运行直到程序结束,执行出从程序开始运行直到程序结束,执行出时,原值时,原值并不消失,只是不能引用。并不消失,只是不能引用。voidrow(void);voidmain(void)intb;for(b=1;b=9;b+)row();voidrow(void)inta=1;intb;for(b=1;b=9;b+)printf(“%5d”,a*b);printf(“n”);a+;CHAP6EX6staticCHAP6EX5说明静态变量。说明静态变量。a的的作作用用域域生生存存期期从从编编译译开开始始到到程程序序结结束束。外部变量(外部变量(extern存储类型、全局变量)存储类型、全局变量)外部变量是定义在任何模块之外的变量。也称为外部变量是定义在任何模块之外的变量。也称为全局变量。全局变量。作用域:作用域:从说明变量开始直到文件结束。从说明变量开始直到文件结束。 生存期:生存期:在程序的整个执行过程中。任何函数对外部变量的修在程序的整个执行过程中。任何函数对外部变量的修改都会影响其他函数对外部变量引用时的值。改都会影响其他函数对外部变量引用时的值。#includevoidadd(void);inta,b,c;voidmain(void)scanf(“%d,%d”,&a,&b);add();printf(“%d”,c);voidadd(void)c=a+b;全局变量。全局变量。作作用用域域关于全局变量的几点说明:关于全局变量的几点说明:全局变量可以通过说明改变其作用域。全局变量可以通过说明改变其作用域。voidmain()inti;/*i为全局变量为全局变量*/voidmax(inta,intb)作作用用域域externi;新新的的作作用用域域全局变量可以被不同的文件共享。全局变量可以被不同的文件共享。file1.cfile2.cinta;externinta;文件文件1定义的外部变量。定义的外部变量。文件文件2通过说明使用通过说明使用文件文件1的外部变量。的外部变量。如果只希望在本文件中使用,可以加如果只希望在本文件中使用,可以加static说明。说明。static关于全局变量的几点说明:关于全局变量的几点说明:模块设计的原则:内聚性强,耦合性弱。全局变量的使用占模块设计的原则:内聚性强,耦合性弱。全局变量的使用占用内存资源且增加模块的耦合性,因此,用内存资源且增加模块的耦合性,因此,应尽量不使用全局变量。应尽量不使用全局变量。当模块中出现和全局变量同名的局部变量时,局部变量在模当模块中出现和全局变量同名的局部变量时,局部变量在模块中优先。块中优先。inta;voidmain(void)a=5;voidfun()inta;a=6;全局变量应用举例:用函数交换两个全局变量的值。全局变量应用举例:用函数交换两个全局变量的值。#includeinta,b;voidmain(void)scanf(“%d,%d”,&a,&b);fun();printf(“a=%d,b=%dn”,a,b);voidfun(void)intc;c=a;a=b;b=c;a、b外部变量。外部变量。ab全局变量的副作用全局变量的副作用#includeinti;voidprt(void);voidmain(void)for(i=0;i5;i+)prt();voidprt(void)for(i=0;i5;i+)printf(“%c”,*);printf(“n”);函数的作用:打印五个函数的作用:打印五个* *,再回车。,再回车。几次调用函数?几次调用函数?i=0i=0i=0i=0i=0i=1i=2i=3i=4i=5i=5i=5i=5i=5全局变量传递参数全局变量传递参数全局变量可以被调用函数和被调函数全局变量可以被调用函数和被调函数共享共享,任何函数对全局变,任何函数对全局变量的修改都会量的修改都会影响到其他函数所见的全局变量的值。影响到其他函数所见的全局变量的值。#includeintc;voidmain(void)inta,b;scanf(“%d,%d”,&a,&b);splus(a,b);printf(“a*b=%dn”,c);voidsplus(intx,inty)c=x*y;说明全局变量说明全局变量c6 说明:说明:应尽量少用全局变量,应使函数内部的内聚性强,函数应尽量少用全局变量,应使函数内部的内聚性强,函数之间的偶合性弱。之间的偶合性弱。【例【例6-8】使用全局变量,通过函数求两个浮点数的积。】使用全局变量,通过函数求两个浮点数的积。/*example6-8使用全局变量通过函数求两个浮点数的积使用全局变量通过函数求两个浮点数的积*/#includefloatMul(void);/*函数原型声明函数原型声明*/floata,b;/*在所有函数之外说明,在所有函数之外说明,a、b为全局变量为全局变量*/voidmain(void)floatc;printf(Pleaseinputtwonumbera,b:);scanf(%f,%f,&a,&b);c=Mul();/*调用调用Mul函数函数*/printf(Thea*bis=%fn,c);printf(a=%fnb=%fn,a,b);floatMul(void)/*函数定义函数定义*/floatz;z=a*b;/*通过全局变量通过全局变量a、b求积求积*/a=3.0;b=4.0;returnz;【例【例6-9】函数中的】函数中的auto存储类别变量的性质示例。存储类别变量的性质示例。/*example6-9函数中函数中auto存储类别变量的性质存储类别变量的性质*/#includevoidMul(void);/*函数原型声明函数原型声明*/voidmain(void)intb;for(b=1;b=9;b+)Mul();/*循环循环9次调用次调用Mul函数函数*/voidMul(void)/*函数定义函数定义*/inta=1;/*具有具有auto存储类别的变量存储类别的变量*/inti;for(i=1;i=9;i+)printf(%5d,a*i);printf(n);a+;【例【例6-10】在函数中使用】在函数中使用register存储类别以提高效率。存储类别以提高效率。/*example6-10函数中使用函数中使用register存储类别求级数存储类别求级数1+2+.+n*/#includeintSer(int);/*函数原型声明函数原型声明*/voidmain(void)intn,sum;printf(Pleaseinputn:);scanf(%d,&n);sum=Ser(n);/*调用函数求级数之和调用函数求级数之和*/printf(1+2+.+%d=%dn,n,sum);intSer(intx)/*函数定义函数定义*/registerinti;/*说明说明register存储类别变量存储类别变量*/ints;s=0;for(i=1;i=x;i+)s+=i;/*i用于循环控制变量以提高速度用于循环控制变量以提高速度*/returns;【例【例6-11】在函数中使用】在函数中使用static存储类别实现输出存储类别实现输出99的乘法表。的乘法表。/*example6-11函数中函数中static存储类别变量的性质存储类别变量的性质*/#includevoidMul(void);/*函数原型声明函数原型声明*/voidmain(void)intb;for(b=1;b=9;b+)Mul();/*循环循环9次调用次调用Mul函数函数*/voidMul(void)/*函数定义函数定义*/staticinta=1;/*具有具有static存储类别的变量存储类别的变量*/inti;for(i=1;i=a;i+)printf(%5d,a*i);printf(n);a+;/*静态局部变量本次调用递增,下次调用维持静态局部变量本次调用递增,下次调用维持*/【例【例6-12】动态存储及静态存储变量的初值案例。】动态存储及静态存储变量的初值案例。/*example6-12动态存储与静态存储的初值动态存储与静态存储的初值*/#includeinta;/*全局变量为静态存储,初值为全局变量为静态存储,初值为0*/voidmain(void)autointb;registerintc;/*动态存储变量初值随机动态存储变量初值随机*/staticintd;/*静态存储初值为静态存储初值为0*/printf(a=%dnb=%dnc=%dnd=%dn,a,b,c,d);【例【例6-13】全局变量与局部变量同名的处理。】全局变量与局部变量同名的处理。/*example6-13全局变量与局部变量同名的处理方式示例全局变量与局部变量同名的处理方式示例*/#includeintFun(int);inta=2;/*说明全局变量说明全局变量*/voidmain(void)intc,a=6;/*局部变量局部变量a与全局变量同名,局部变量优先与全局变量同名,局部变量优先*/printf(Thisaislocation=%dn,a);c=Fun(a);/*a是本函数说明的局部变量,初值为是本函数说明的局部变量,初值为6*/printf(c=%dn,c);intFun(intx);/*函数定义函数定义*/printf(Thisaisextern=%dn,a);/*本函数本函数a为全局变量为全局变量*/returna+x;【例【例6-14】全局变量在程序中的副作用。】全局变量在程序中的副作用。/*example6-14全局变量的副作用全局变量的副作用*/#includeinti;/*说明全局变量说明全局变量*/voidPrt(void);/*函数原型声明函数原型声明*/voidmain(void);for(i=0;i5;i+)Prt();printf(-End-n);voidPrt(void)/*定义函数定义函数*/for(i=0;i5;i+)printf(“%c”,#);/*循环循环5次,打印次,打印5个个#*/printf(“n”);/*换行换行*/6.4数组与函数参数数组与函数参数 问题:问题:引用数组时只能引用数组元素。如果用参数传递数组元引用数组时只能引用数组元素。如果用参数传递数组元素,则函数需要参数的量太多。为了解决此问题,可以素,则函数需要参数的量太多。为了解决此问题,可以通过指针传通过指针传递数组的地址。递数组的地址。一维数组作为函数参数定义有三种方式:一维数组作为函数参数定义有三种方式:形参为指针;形参为指针;intave(int*p)形参为无下标数组;形参为无下标数组;intave(inta)形参为有下标数组。形参为有下标数组。intave(inta10)3种数组作为函数参数:种数组作为函数参数:一维数组作为函数参数一维数组作为函数参数;二维数组作为函数参数;二维数组作为函数参数;字符数组作为函数参数字符数组作为函数参数举例:通过函数求数组元素的平均值。举例:通过函数求数组元素的平均值。#includefloatmean(int*,int);voidmain(void)intarray10=1,2,3,4,5,6,7,8,9,10;floatav;av=mean(array,10);printf(“av=%fn%d”,av,array0);floatmean(int*data,intnum)inti;floatavg=0;for(i=0;inum;i+)avg+=*data+;avg/=num;return(avg);指针法;指针法;指针法。指针法。形参为无下标数组;形参为无下标数组;无下标数组。无下标数组。intdatadata0=-1;datai;intdata10形参为有下标数组。形参为有下标数组。形参为有下标数组。形参为有下标数组。说明:说明: 三种方法的实质都是传递地址,三种方法的实质都是传递地址,可以混用。可以混用。形参的任何改变都影响实参。形参的任何改变都影响实参。 函数中对数组的操作,下标不要函数中对数组的操作,下标不要超过数组的下标范围。超过数组的下标范围。chp6ex2举例:通过函数将字符串中的大写字母转换为小写字母。举例:通过函数将字符串中的大写字母转换为小写字母。#include void StrLow(char *ps);void main(void)char szStr80;gets(szStr);StrLow(szStr);puts(szStr);void StrLow(char *ps)int i;for(i = 0; psi !=0; i+)if(psi = a & psi = z)psi -= 32;/*End of if*/*End of for*/【例【例6-15】通过函数求数组的最大值,主函数调用并输出结果。】通过函数求数组的最大值,主函数调用并输出结果。/*example6-15通过函数求数组的最大值一维数组作为函数参数通过函数求数组的最大值一维数组作为函数参数*/#includeintGetMax(int*,int);/*函数原型声明函数原型声明*/voidmain(void)inta10=51,99,80,75,66,30,95,86,74,68;intiMax;iMax=GetMax(a,10);printf(nMaxofais%dn,iMax);/*函数定义函数定义*/*参数参数1:p指向整型的指针,用于传递数组的首地址指向整型的指针,用于传递数组的首地址*/*参数参数2:num表示数组元素的个数表示数组元素的个数*/*返回值:数组元素的最大值返回值:数组元素的最大值*/intGetMax(int*p,intnum)intmax,i;max=*p;/*假定第一个元素为最大值假定第一个元素为最大值*/for(i=1;imax)max=*(p+i);returnmax;【例【例6-16】通过函数将数组按升序排序,主函数调用并输出结果。】通过函数将数组按升序排序,主函数调用并输出结果。/*example6-16通过函数对数组排序一维数组作为函数参数通过函数对数组排序一维数组作为函数参数*/#includevoidSort(int*,int);/*函数原型声明函数原型声明*/voidmain(void)inti;inta10=51,99,80,75,66,30,95,86,74,68;for(i=0;i10;i+)printf(%4d,ai);/*输出原始数据输出原始数据*/printf(n);Sort(a,10);/*调用函数对数组排序调用函数对数组排序*/for(i=0;i10;i+)printf(%4d,ai);/*输出排序结果输出排序结果*/printf(n);/*函数定义函数定义*/*参数参数1:x无下标数组,用于传递数组的首地址无下标数组,用于传递数组的首地址*/*参数参数2:num数组元素的个数数组元素的个数*/*返回值:无返回值:无*/voidSort(intx,intnum)inti,j;for(i=0;inum-1;i+)for(j=i+1;jxj)inttemp;/*说明局部临时变量,用于交换说明局部临时变量,用于交换*/temp=xi;xi=xj;xj=temp;【例例6-17】通通过过函函数数求求3行行4列列二二维维数数组组所所有有元元素素的的累累加加和和,在在主主函数调用并输出结果。函数调用并输出结果。/*example6-17*/*通过函数求二维数组所有元素的累加和通过函数求二维数组所有元素的累加和,二维数组作为函数二维数组作为函数参数参数*/#includeintAcc(intx4);/*函数原型声明函数原型声明*/voidmain(void)inti,j;inta34=1,2,3,4,5,6,7,8,9,10,11,12;intsum;for(i=0;i3;i+)for(j=0;j4;j+)printf(%3d,aij);printf(n);sum=Acc(a);/*调用函数,二维数组数组名作为实参传递调用函数,二维数组数组名作为实参传递首地址首地址*/printf(Sum=%4dn,sum);/*输出结果输出结果*/*函数定义函数定义*/*参数:参数:x省略行数的二维数组,用于传递数组的首地址省略行数的二维数组,用于传递数组的首地址*/*返回值:所有元素的累加和返回值:所有元素的累加和*/intAcc(intx4)/*形参形参x为指针为指针*/inti,j;intsum;sum=0;for(i=0;i3;i+)for(j=0;j4;j+)sum+=xij;/*通过形参表示的通过形参表示的aij*/returnsum;【例例6-18】通通过过函函数数将将字字符符串串中中的的所所有有小小写写字字母母转转换换成成对对应应的的大大写字母,在主函数调用并输出结果。写字母,在主函数调用并输出结果。/*example6-18*/*通过函数将字符串中的所有小写字母转换成对应的大写字母通过函数将字符串中的所有小写字母转换成对应的大写字母*/*字符数组作为函数参数字符数组作为函数参数*/#includevoidStrUpr(char*);/*函数原型声明,参数为指向字符的指针函数原型声明,参数为指向字符的指针*/voidmain(void)charstr80;printf(InputSourceString:);gets(str);StrUpr(str);/*调用函数,字符数组名作为实参,传递数组的调用函数,字符数组名作为实参,传递数组的首地址首地址*/printf(TransformedString:);puts(str);/*函数定义函数定义*/*函数功能函数功能:将字符串中的小写字母转换成对应的大写字母将字符串中的小写字母转换成对应的大写字母*/*函数名函数名:StrUpr*/*函数参数:函数参数:s用于传递数组的首地址用于传递数组的首地址*/voidStrUpr(char*s)while(*s!=0)if(*s=a&*s=z)*s-=32;/*如果是小写字母,转换为对应的大写如果是小写字母,转换为对应的大写*/s+;/*指针指向下一字符指针指向下一字符*/6.5返回指针的函数返回指针的函数 概念:概念:函数可以返回一个值,也可以返回一个地址(指针),函数可以返回一个值,也可以返回一个地址(指针),如果函数返回地址,该函数称为如果函数返回地址,该函数称为返回指针的函数。返回指针的函数。定义:定义:type*函数名(形参表)函数名(形参表)int*max(int*a,int*b)例:通过返回最大值的地址求最大值例:通过返回最大值的地址求最大值#include int *pMax(int *,int *);void main(void)int a,b,*p;scanf(%d,%d,&a,&b); p = pMax(&a,&b);printf(最大值是 = %dn,*p);int *pMax(int *x,int *y)return *x *y ? x:y;例:通过函数在某字符串中搜索一个特定的字符第一次出现的地例:通过函数在某字符串中搜索一个特定的字符第一次出现的地址,在主函数调用并输出结果。址,在主函数调用并输出结果。 /* example6-19 */ /* 在字符串中查找给定的字符第一次出现的位置,返回其地址 */ #include #include char *Search( char * , char ) ; /* 函数原型声明 */ void main ( void) char c , *p , str80; gets(str ); scanf( %c , &c); p = Search(str ,c ); /* 调用函数 */ if (p=NULL ) printf (char %c not foundn, c ) ; else printf (The position is: %dn ,p-str ) ; 续例:续例: /* 函数名: Search */ /* 函数参数1: p指向字符的指针,用于传递字符串的首地址 */ /* 函数参数2: ch字符变量,用于传递待查找的字符 */ /* 函数返回值:找到,返回其地址; 否则,返回NULL */ char *Search(char *s , char ch) char *p=NULL ; while (*s!=0) if (*s=ch)p = s ; /* 找到,保留地址 */break ; else s+; /* 继续,指针后移 */ return p ; 【例例6-19】通通过过函函数数在在某某字字符符串串中中搜搜索索一一个个特特定定的的字字符符第第一一次次出出现的地址,在主函数调用并输出结果。现的地址,在主函数调用并输出结果。/*example6-19*/*通过函数在字符串中查找给定的字符第一次出现的位置,返通过函数在字符串中查找给定的字符第一次出现的位置,返回其地址回其地址*/#include#includechar*Search(char*,char);/*函数原型声明函数原型声明*/voidmain(void)charc,*p,str80;gets(str);scanf(%c,&c);p=Search(str,c);/*调用函数调用函数*/if(p=NULL)printf(char%cnotfoundn,c);elseprintf(Thepositionis:%dn,p-str);/*函数名函数名:Search*/*函数参数函数参数1:s指向字符的指针,用于传递字符串的首地址指向字符的指针,用于传递字符串的首地址*/*函数参数函数参数2:ch字符变量,用于传递待查找的字符字符变量,用于传递待查找的字符*/*函数返回值:找到,返回其地址函数返回值:找到,返回其地址;否则,返回否则,返回NULL*/char*Search(char*s,charch)char*p=NULL;while(*s!=0)if(*s=ch)p=s;/*找到,保存地址找到,保存地址*/break;elses+;/*继续,指针后移继续,指针后移*/returnp;6.6指向函数的指针指向函数的指针概念:概念:函数为程序模块,函数要装载到内存中,函数在内存中函数为程序模块,函数要装载到内存中,函数在内存中其首地址称为函数的入口地址,用函数名表示。其首地址称为函数的入口地址,用函数名表示。C语言可以通过指语言可以通过指针指向函数的入口地址,从而实现通过指针对函数的调用。针指向函数的入口地址,从而实现通过指针对函数的调用。c=max(a,b);int max(int x,int y) return (x=y?x:y);2400指向函数指针的定义:指向函数指针的定义:type(*p)();函数的类型。函数的类型。指针指针函数函数使用过程:使用过程:定义函数和指向函数的指针;定义函数和指向函数的指针;指针指向函数;指针指向函数;p=funname;通过指针引用函数。格式:通过指针引用函数。格式:(*p)(实参表实参表);举例:求举例:求a、b的最大值。的最大值。#includeintlmax(int,int);voidmain(void)inta,b,c;int(*funp)();funp=lmax;scanf(“%d,%d”,&a,&b)c=(*funp)(a,b);printf(“Max.is%dn”,c);intlmax(intx,inty)return(xy?x:y);说明指向函数的指针。说明指向函数的指针。指针指向函数。指针指向函数。funplmax通过指针引用函数。通过指针引用函数。lmax举例:通过参数传递,求举例:通过参数传递,求a、b之和、之差。之和、之差。#includeintplus(int,int);intsub(int,int);intfuna(int,int,int(*)(int,int);voidmain(void)inta,b,c;scanf(“%d,%d”,&a,&b);c=funa(a,b,plus);printf(“na+b=%d”,c);c=funa(a,b,sub);printf(“na-b=%d”,c);intfuna(intx,inty,int(*funp)(int,int)return(*funp)(x,y);intplus(intx,inty)return(x+y);intsub(intx,inty)return(x-y);【例例6-20】通通过过指指向向函函数数的的指指针针调调用用,求求两两个个数数较较大大值值的的函函数数,在主函数中调用并输出结果。在主函数中调用并输出结果。/*example6-20通过指向函数的指针调用求两个数较大值的函数通过指向函数的指针调用求两个数较大值的函数*/#includeintGetMax(int,int);/*函数原型声明函数原型声明*/voidmain(void)inta,b,c;int(*funp)();/*说明指向函数的指针说明指向函数的指针*/funp=GetMax;/*指针指向函数指针指向函数*/printf(Pleaseinputtwonumbera,b:);scanf(%d,%d,&a,&b);c=(*funp)(a,b);/*通过指针调用函数通过指针调用函数*/printf(Max.is%dn,c);/*函数名:函数名:GetMax*/*功功能:计算两个整型数的较大值能:计算两个整型数的较大值*/*参参数:数:x、y*/*返回值:返回值:x,y的较大值的较大值*/intGetMax(intx,inty)return(xy?x:y);【例例6-21】指指向向函函数数的的指指针针作作为为函函数数参参数数,通通过过参参数数传传递递不不同同的的函函数数入入口口地地址址,实实现现求求两两个个浮浮点点数数的的四四则则运运算算,在在主主函函数数调调用用并并输出结果。输出结果。/*example6-21*/*将函数的指针作为函数的参数,实现对多个函数的调用将函数的指针作为函数的参数,实现对多个函数的调用*/#includefloatGenFun(float(*p)(float,float),floatx,floaty);floatGetAdd(floatx,floaty);floatGetSub(floatx,floaty);floatGetMul(floatx,floaty);floatGetDiv(floatx,floaty);/*函数原型声明函数原型声明*/voidmain(void)floata,b,c;printf(Pleaseinputtwofloatnumbera,b:);scanf(%f,%f,&a,&b);/*分别调用分别调用GenFun,并将各函数的函数名和参数传递给,并将各函数的函数名和参数传递给GenFun*/c=GenFun(GetAdd,a,b);/*通过通过GenFun调用求和函数调用求和函数*/printf(a+b=%fn,c);c=GenFun(GetSub,a,b);/*通过通过GenFun调用求差函数调用求差函数*/printf(a-b=%fn,c);c=GenFun(GetMul,a,b);/*通过通过GenFun调用求积函数调用求积函数*/printf(a*b=%fn,c);c=GenFun(GetDiv,a,b);/*通过通过GenFun调用求商函数调用求商函数*/printf(a/b=%fn,c);/*函数名:函数名:GenFun*/*功功能:通过参数传递函数的入口地址,实现多个函数调用能:通过参数传递函数的入口地址,实现多个函数调用*/*参参数:数:p指向函数的指针,指向函数的指针,x,y浮点型浮点型*/floatGenFun(float(*p)(float,float),floatx,floaty)floatz;z=(*p)(x,y);/*调用调用p指向的函数指向的函数*/returnz;floatGetAdd(floatx,floaty)/*两个浮点数求和函数两个浮点数求和函数*/return(x+y);floatGetSub(floatx,floaty)/*两个浮点数求差函数两个浮点数求差函数*/return(xy);floatGetMul(floatx,floaty)/*两个浮点数求积函数两个浮点数求积函数*/return(x*y);floatGetDiv(floatx,floaty)/*两个浮点数求商函数两个浮点数求商函数*/return(x/y);6.7递归函数递归函数概念:概念:函数直接或间接地自我调用称为递归函数。函数直接或间接地自我调用称为递归函数。intfun1(intx)z=fun1(y);intfun1(intx)intfun2(intt)z=fun2(y);c=fun1(a);直接引用自身。直接引用自身。间接引用自身。间接引用自身。递归在没有控制条件的情况下是无穷的递归。递归在没有控制条件的情况下是无穷的递归。voidmain(void)printf(“*n”);main();只有通过控制条件,使递归调用终止,才具有应用价值只有通过控制条件,使递归调用终止,才具有应用价值。voidmain(void)printf(“*n”);ch=getchar();if(ch!=9)main();递归举例:求递归举例:求n!。n!=1n=0或或n=1n(n-1)!n1f(n)=1n=0或或n=1nf(n-1)n1#include long lfac(long);void main(void)long i,x; scanf(“%ld”,&i); x=lfac(i); printf(“n%ld”,x);long lfac(long n) if (n=0|n=1) return 1; else return(n*lfac(n-1);lfac(4)4*lfac(3)3*lfac(2)2*flac(1)2*13*2*14*3*2*1递推递推回归回归chp6ex7例:通过递归求斐波那契数列例:通过递归求斐波那契数列 /* example 6-23 通过递归函数求斐波那契数列 */ #include long f(int n); /* 函数原型声明 */ void main(void) long lValue;int n;printf(Please input a number: );do scanf(%d,&n); if(n 0) printf(Data error! ); while(n 0); /* 如果输入n0,打印提示并重新输入 */ lValue = f(n); /* 调用函数 */printf(f(%d) = %ldn,n,lValue); 续例:续例: /* 函数名:f */ /* 功 能:递归求斐波那契数列 */ /* 参 数:n(整型) */ /* 返回值:项序为n的递归求斐波那契数列值(长整型) */ long f(int n) long y;if(n = 0) y = 0; else if(n = 1) y = 1;else y = f(n-1) + f(n-2);return y; 【例例6-22】通通过过递递归归实实现现求求n!的的函函数数,在在主主函函数数中中输输入入n,并并输输出结果。出结果。/*example6-22通过递归函数求通过递归函数求n!*/#includelongGetFact(intn);/*函数原型声明函数原型声明*/voidmain(void)longlFacValue;intn;printf(Pleaseinputanumber:);doscanf(%d,&n);if(n0)printf(Dataerror!,retry:);while(n0);/*如果输入如果输入n1)y=n*GetFact(n-1);/*递归调用递归调用*/returny;【例【例6-23】通过递归求斐波那契数列,斐波那契数列定义为:】通过递归求斐波那契数列,斐波那契数列定义为:/*example6-23通过递归函数求斐波那契数列通过递归函数求斐波那契数列*/#includelongf(intn);/*函数原型声明函数原型声明*/voidmain(void)longlValue;intn;printf(Pleaseinputanumber:);doscanf(%d,&n);if(n0)printf(Dataerror!);while(n0);/*如果输入如果输入n0,打印提示并重新输入打印提示并重新输入*/lValue=f(n);/*调用函数调用函数*/printf(f(%d)=%ldn,n,lValue);/*函数名:函数名:f*/*功功能:递归求斐波那契数列能:递归求斐波那契数列*/*参参数:数:n(整型整型)*/*返回值:项序为返回值:项序为n的递归求斐波那契数列值的递归求斐波那契数列值(长整型长整型)*/longf(intn)longy;if(n=0)y=0;elseif(n=1)y=1;elsey=f(n-1)+f(n-2);returny;6.8主函数参数主函数参数如如DOS命令:命令:COPYA:S.DOCC:命令。命令。命令对象,命令参数。命令对象,命令参数。C支持由主函数支持由主函数main(),在程序执行时,从操作系统接收传递的在程序执行时,从操作系统接收传递的参数。并记录参数供程序处理。主函数一般有两个参数。参数。并记录参数供程序处理。主函数一般有两个参数。voidmain(intargc,char*argv)整型变量,记录包括命整型变量,记录包括命令行在内的字符串个数。令行在内的字符串个数。指向字符的指向字符的指针数组。记录指针数组。记录所有参数字符串所有参数字符串的地址。的地址。举例:回显命令行参数。举例:回显命令行参数。#includevoidmain(intargc,char*argv)inti;for(i=1;iargc;i+)printf(“%s%c”,argvi,(iargc 4argv0argv1argv2argv3test0How0are0you?0【例【例6-24】按行输出主函数参数中字符串的内容。】按行输出主函数参数中字符串的内容。/*example6-24主函数参数应用主函数参数应用*/#includevoidmain(intargc,char*argv)inti;for(i=1;iargc;i+)puts(argvi);6.9编译预处理编译预处理C语言除了说明语句、执行语句及控制语句外,还有一类语言除了说明语句、执行语句及控制语句外,还有一类编译编译预处理语句预处理语句。该类语句的作用是。该类语句的作用是在编译时对程序作一定的处理在编译时对程序作一定的处理,满,满足特定的处理要求。编译预处理是足特定的处理要求。编译预处理是C语言的重要特征。语言的重要特征。编译预处理语句的语法形式:编译预处理语句的语法形式:#关键词关键词参数表参数表编译预处理语句不用;作为结束标志!编译预处理语句不用;作为结束标志!宏定义预处理宏定义预处理不带参数的宏定义不带参数的宏定义作用:作用:定义常量名,提高程序的可读性,便于修改。定义常量名,提高程序的可读性,便于修改。格式:格式:#define宏名宏名字符串字符串#definePI3.1415926voidmain(void)floatr;scanf(“%f”,&r)printf(“%fn”,PI*r*r);编译时用字符串替代宏名。编译时用字符串替代宏名。3.1415926说明:说明:宏名一般用大写;宏名一般用大写;编译时用字符串无条件替代宏名;编译时用字符串无条件替代宏名;#definePI3.1415926;PI*r*r3.1415926;*r*r宏名的有效范围,从定义到程序尾。也可以通过宏名的有效范围,从定义到程序尾。也可以通过#undef修改修改定义范围。定义范围。#defineG9.8voidmain(void)#undefGG的的范范围围可以在宏定义的字符串中使用已定义的宏名。可以在宏定义的字符串中使用已定义的宏名。”字符串中的宏名不替换。字符串中的宏名不替换。#defineR3.0#definePI3.14159#defineSPI*R*Rprintf(“S=%f”,S);不替换。不替换。带参数的宏定义带参数的宏定义格式:格式:#define宏名宏名(参数表参数表)含参数的字符串含参数的字符串#defineS(a,b)a*barea=S(4,3);替换过程:替换过程:将实际参数替换宏定义的参数。将实际参数替换宏定义的参数。替换字符串中的参数。替换字符串中的参数。替换整个宏。替换整个宏。4*3带参的宏与函数的区别:带参的宏与函数的区别:带参宏不分配内存单元,不返回值,只是在编译时按规则替换。带参宏不分配内存单元,不返回值,只是在编译时按规则替换。关于带参宏的说明:关于带参宏的说明:要严格按格式书写,否则会造成错误。要严格按格式书写,否则会造成错误。#defineS(a,b)a*bS(3,4)被替换成:被替换成:(a,b)a*b(3,4)参数有可能用到表达式时,参数字符要加()。参数有可能用到表达式时,参数字符要加()。#defineS(r)PI*r*rS(a+b)替换为:替换为:PI*a+b*a+b#defineS(r)PI*(r)*(r)S(a+b)替换为:替换为:PI*(a+b)*(a+b)【例例6-25】通通过过宏宏定定义义将将圆圆周周率率定定义义成成宏宏名名PI,输输入入一一个个圆圆柱柱体体的半径和高,输出其体积和底面积。的半径和高,输出其体积和底面积。/*example6-25无参数的宏的应用无参数的宏的应用*/#include#definePI3.1415926/*定义圆周率为定义圆周率为PI*/voidmain(void)doubler,h;/*r为底半径,为底半径,h为高为高*/doublefArea,fV;/*fArea为底面积,为底面积,fV为体积为体积*/printf(Pleaseinputthecolumnsradius,height:);scanf(%lf,%lf,&r,&h);/*输入半径和高输入半径和高*/fArea=PI*r*r;fV=fArea*h;printf(Thecolumnsbottomareais=%lfn,fArea);printf(Thecolumnsvolumeis=%lfn,fV);【例例6-26】定定义义带带参参的的宏宏,以以实实现现求求圆圆锥锥体体的的体体积积,输输入入一一个个圆圆锥体的半径和高作为宏的参数,输出其体积。锥体的半径和高作为宏的参数,输出其体积。/*example6-26定义带参的宏实现求圆锥体的体积定义带参的宏实现求圆锥体的体积*/#include#definePI3.1415926/*定义无参宏定义无参宏*/#defineVTAPER(r,h)(PI)*(r)*(r)*(h)/3)/*定义有参宏定义有参宏*/voidmain(void)doubler,h,fV;printf(Plraseinputr,hofataper:);scanf(%lf,%lf,&r,&h);fV=VTAPER(r,h);/*引用带参的宏引用带参的宏*/printf(Thevolumnoftaper=%lfn,fV);文件包含文件包含格式:格式:#include#include”被包含的文件名被包含的文件名”表示编译系统定义路径;表示编译系统定义路径;“”表示用户指明路径。表示用户指明路径。作用:作用:将指定的文件的内容和当前文件一起编译。将指定的文件的内容和当前文件一起编译。说明:说明:一个一个#include只能包含一个文件。只能包含一个文件。被包含文件可以嵌套包含文件。被包含文件可以嵌套包含文件。一般将宏定义及函数的原型声明放在包含文件中。一般将宏定义及函数的原型声明放在包含文件中。被包含的文件一般扩展名为被包含的文件一般扩展名为.h,称为头文件。称为头文件。文件包含举例:求半径为文件包含举例:求半径为r的园面积、园周长。的园面积、园周长。#include“my.h”voidmain(void)floatr,fArea,fLen;scanf(“%f”,&r);fArea=S(r);fLen=L(r);printf(“Area=%f,Len=%f”,fArea,fLen);floatS(floatr)returnPI*r*r;floatL(floatr)return2*PI*r;#include#definePI3.1415926floatS(float);floatL(float);【例例6-27】文文件件包包含含举举例例。通通过过两两个个函函数数分分别别计计算算一一个个半半径径为为r,高高为为h的的圆圆柱柱体体的的体体积积和和表表面面积积,在在主主函函数数输输入入r、h,调调用用函函数数输输出结果。出结果。/*example6-27文件包含举例文件包含举例*/#includemy.h/*包含包含my.h*/voidmain(void)doubler,h,fArea,fV;printf(Pleaseinputr,h:);scanf(%lf,%lf,&r,&h);fArea=ColArea(r,h);fV=ColVol(r,h);printf(Area=%lfnVol=%lfn,fArea,fV);/*函数定义函数定义*/*参参数:数:r圆柱体的底半径,圆柱体的底半径,h圆柱体的高圆柱体的高*/*功功能:返回圆柱体的表面积能:返回圆柱体的表面积*/doubleColArea(doubler,doubleh)return2.*PI*r*r+2.*PI*r*h;/*函数定义函数定义*/*参参数:数:r圆柱的底半径,圆柱的底半径,h圆柱的高圆柱的高*/*功功能:返回圆柱体的体积能:返回圆柱体的体积*/doubleColVol(doubler,doubleh)returnPI*r*r*h;条件编译条件编译C语言可以通过条件控制,让编译系统编译不同的程序段,从语言可以通过条件控制,让编译系统编译不同的程序段,从而提高程序的移植性并方便调试。而提高程序的移植性并方便调试。条件编译有三种形式:条件编译有三种形式:#ifdef标识符标识符programseg1#elseprogramseg2#endif#ifndef标识符标识符programseg1#elseprogramseg2#endif123#if表达式表达式programseg1#elseprogramseg2#endif条件?条件?满足满足编译程序段编译程序段1不满足不满足编译程序段编译程序段2举例:通过条件编译选择求最大值或最小值举例:通过条件编译选择求最大值或最小值#includevoidmain(void)inta,b;scanf(“%d,%d”,&a,&b);#ifdefMAXprintf(“%d”,a=b?a:b);#elseprintf(“%d”,a=b?a:b);#endif#defineMAX#includevoidmain(void)inta,b;scanf(“%d,%d”,&a,&b);printf(“%d”,a=b?a:b);【例例6-28】利利用用条条件件编编译译,实实现现两两个个数数求求最最小小值值或或求求最最大大值值的的程程序。序。/*example6-28条件编译条件编译*/#include#defineMAX/*定义宏定义宏*/voidmain(void)inta,b;printf(Pleaseinputtwointegera,b:);scanf(%d,%d,&a,&b);#ifdefMAXprintf(Themaxis%dn,a=b?a:b);#elseprintf(Theminis%dn,a=b?a:b);#endif6.10 模块化程序设计方法 模块化程序设计是结构化程序设计方法的重要组成部分。所谓的模块化就是通过函数将一个大而复杂的问题分解成小而简单的问题的组合。解决每个小而简单的问题相对容易,从而使整个系统的复杂度降低。模块是指实现某个特定功能的一个或几个程序单位,在C语言中表现为函数。函数可以独立设计,单独调试,从而简化了系统的实现。 由于模块可以单独设计,独立编译,因此,便于调试和工程化编程。模块可以实现信息隐蔽,将模块实现的功能封闭于模块之中,对于用户只关心其与外部的接口。同时模块化也可以将错误封闭于模块之中,不至于在整个程序中扩散。模块分解的重要原则 1.提高模块的内聚性,减少模块的耦合性。 通俗地说就是模块设计要尽量保证模块与模块之间除了调用之外的联系尽可能少,模块之间的联系越少,模块自身的独立性越好 。2.每个模块实现的功能要单一完整,模块的规模要适度。每个模块最好只实现一个功能,不要在模块中实现复合功能。 3.函数模块的规模不宜过大一般认为在50条语句以内比较适宜分解后的每个模块应含有以下几个主要的属性1.输入输出:反映模块与外部的数据联系,是模块的接口 。2.逻辑功能:反映模块的功能,如何实现将输入数据转化为结果数据 。 3. 内部数据:内部属性,即模块内部所需的局部数据
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号