




已阅读5页,还剩47页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2019/11/26,1,第7章函数与预处理命令,北京科技大学计算机系,C语言程序设计,2019/11/26,2,第7章函数与预处理命令,7.1概述7.2函数的定义与调用7.3数组作函数参数7.4函数的嵌套调用和递归调用7.5局部变量和全局变量及其作用域7.6变量的存储类别及变量的生存期7.7函数的存储分类7.8编译预处理7.9多文件程序的调试方法,2019/11/26,3,7.1概述,程序结构清晰,可读性好。减少重复编码的工作量。可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。,使用函数的好处,2019/11/26,4,【例7.1】求一个整数的立方。,intcube(intx)/*函数定义*/return(x*x*x);main()intf,a;printf(nEnteranintegernumber:);scanf(%d,程序运行情况如下:Enteranintegernumber:22*2*2=8,函数调用,程序的执行总是从main函数开始,2019/11/26,5,一个C源程序可以由一个或多个源程序文件组成。C编译系统在对C源程序进行编译时是以文件为单位进行的。一个C源程序文件可以由一个或多个函数组成。所有函数都是独立的。主函数可以调用其它函数,其它函数可以相互调用。在一个C程序中,有且仅有一个主函数main。C程序的执行总是从main函数开始,调用其它函数后最终回到main函数,在main函数中结束整个程序的运行。,说明,2019/11/26,6,函数的种类,从函数定义形式分:有参函数:在主调(用)函数和被调(用)函数之间通过参数进行数据传递,如:intcube(intx)无参函数:如:getchar()在调用无参函数时,主调函数不需要将数据传递给无参函数。,从使用的角度看:标准函数(库函数)库函数是由系统提供的。如:getchar()、sin(x)等。在程序中可以直接调用它们。附录A列出了C的部分库函数。用户自定义函数。如:例7.1中的cube函数。,2019/11/26,7,【例7.2】无参函数的定义与调用。,voidwelcome()printf(*n);printf(WelcometoChinan);printf(*n);main()welcome();,程序的输出结果如下:*WelcometoChina*,2019/11/26,8,7.2.1函数的定义,函数定义的一般形式,函数类型函数名(类型名形式参数1,)说明语句执行语句,例如:求两个数的最大值。intmax(intx,inty)intz;z=xy?x:y;return(z);,类型省略时默认为int类型,2019/11/26,9,intmax(x,y)intx,y;intz;z=xy?x:y;return(z);,intmax(x,y)intx,y;或intmax(intx,y),或intmax(x,y)intx,y,z;z=xy?x:y;return(z);,花括号中也可以为空,这种函数叫空函数。不能在函数体内定义其他函数,即函数不能嵌套定义。,形参也可以这样定义,2019/11/26,10,函数名(实参表列),在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。例如:welcome();if(iabs(a)max)max=iabs(a);m=max(c,max(a,b);,7.2.2函数的调用,函数调用的一般形式:,2019/11/26,11,intsum100()inti,t=0;for(i=1;i=100;i+)t+=i;return(t);main()ints;s=sum100();printf(%dn,s);,程序输出结果:5050,intsum(intx)inti,t=0;for(i=1;iy?x:y;return(z);/*返回z的值*/main()inta,b,c;scanf(%d,%d,2019/11/26,16,函数的返回值是通过return语句带回到主调函数的,功能:终止函数的运行,返回主调函数,若有返回值,将返回值带回主调函数。,说明:若函数没有返回值,return语句可以省略。return语句中的表达式类型一般应和函数的类型一致,如果不一致,系统自动将表达式类型转换为函数类型。,函数的返回值,return语句格式:,return(表达式);或return表达式;或return;,2019/11/26,17,【例7.8】计算并输出圆的面积。,s(intr)return3.14*r*r;main()intr,area;scanf(%d,自动转换为int型,思考:若要得到单精度实型的圆面积,程序应如何修改,程序运行情况如下:212,?,2019/11/26,18,7.2.4对被调函数的声明和函数原型,变量要先定义后使用,函数也如此。即被调函数的定义要出现在主调函数的定义之前。如swap函数:允许整型函数(且参数也是整型)的定义出现在主调函数之后。如max函数:如果非整型函数在主调函数之后定义,则应在主调函数中或主调函数之前对被调函数进行声明。,voidswap(intx,inty)main()swap(a,b);,main()c=max(a,b);max(intx,inty),2019/11/26,19,对被调函数进行声明的一般形式,函数类型函数名(参数类型1参数名1,);或函数类型函数名(参数类型1,参数类型2,);,思考:以下哪种情况需要在主调函数中对被调函数声明被调函数定义在前,主调函数定义在后。主调函数定义在前,被调函数定义在后,且被调函数的类型不是整型的。被调函数定义在后,但被调函数的类型是整型。,第二种形式省略了参数名,此种形式也称为函数的原型。,?,2019/11/26,20,main()voidcalc(floatx,floaty,charopr);floata,b;charopr;printf(nInputexpression:);scanf(%f%c%f,对被调函数的声明,【例7.9】计算并输出两个数的和、差、积、商。,2019/11/26,21,图7.2验证哥德巴赫猜想,【例7.10】哥德巴赫猜想之一是任何一个大于5的偶数都可以表示为两个素数之和。验证这一论断。,2019/11/26,22,#includemath.hintprime(intn);main()inta,b,c,n;scanf(%d,/*穷举法判断素数*/intprime(intn)inti;for(i=2;i=sqrt(n);i+)if(n%i=0)return0;return1;,可以在main函数的前面对prime函数进行声明。实际上,该声明可以省略,为什么?,程序如下:,2019/11/26,23,7.3数组作函数参数,7.3.1一维数组元素作函数参数,main()inta5,i,m;for(i=0;i5;i+)scanf(%d,【例7.11】求5个数中的最小值。,intmin(intx,inty)return(xy?x:y);,用打擂台方法求最小值。m相当于擂主,2019/11/26,24,7.3.2一维数组名作函数参数,数组名表示数组在内存中的起始地址。例如:数组a在内存中从2000地址开始存放,则a的值为2000。2000是地址值,是指针类型的数据(第8中将介绍指针类型),不能把它看成是整型或其他类型数据。实参是数组名,形参也应定义为数组形式,形参数组的长度可以省略,但不能省,否则就不是数组形式了。【例7.12】用冒泡法将10个整数排序。,2019/11/26,25,voidsort(intb,intn);voidprintarr(intb);main()inta10=11,22,63,97,58,80,45,32,73,36;printf(Beforesort:n);printarr(a);sort(a,10);printf(Aftersort:n);printarr(a);,voidprintarr(intb10)inti;for(i=0;i10;i+)printf(%5d,bi);printf(n);,voidsort(intb,intn)inti,j,t;for(i=1;ibj+1)t=bj;bj=bj+1;bj+1=t;,2019/11/26,26,图7.3调用sort函数,2000,b,形参b实际是一个可以存放地址的变量,a:2000,实参赋给形参,2019/11/26,27,#includestdio.hmain()voidscat(charstr1,charstr2);chars150,s250;inti,k;printf(Inputs1:);gets(s1);printf(Inputs2:);gets(s2);scat(s1,s2);printf(Outputs1:%sn,s1);printf(Outputs2:%sn,s2);,voidscat(charstr1,charstr2)inti=0,k=0;while(str1i!=0)i+;while(str2k!=0)str1i=str2k;i+;k+;str1i=0;,scat函数还可简化为:voidscat(charstr1,charstr2)inti=0,k=0;while(str1i)i+;while(str1i+=str2k+);,【例7.13】编程序,实现字符串连接。,2019/11/26,28,以二维数组为例。二维数组名作实参时,对应的形参也应该定义为一个二维数组形式。对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。【例7.14】编程序,将矩阵转置。设转置前为a矩阵,转置后为b矩阵,如下所示:,思路:将a00b00,a01b10,a02b20,a10b01,aijbji,。,7.3.3多维数组作函数参数,2019/11/26,29,voidturn();main()inta34=1,2,3,4,5,6,7,8,9,10,11,12;inti,j,b43;turn(a,b);printf(arrayb:n);for(i=0;i4;i+)for(j=0;j3;j+)printf(%5d,bij);printf(n);,/*矩阵转置函数*/voidturn(intarra4,intarrb3)intr,c;for(r=0;r3;r+)for(c=0;c0;i-)a+=sub2(i);returna;,sub2(intn)returnn+1;,程序输出结果:9,2019/11/26,32,7.4.2函数的递归调用,不要求!,2019/11/26,33,7.5局部变量和全局变量及其作用域,7.5.1变量的作用域,7.5.2局部变量及其作用域,变量的作用域:变量在程序中可以被使用的范围。根据变量的作用域可以将变量分为局部变量和全局变量。,局部变量(内部变量):在函数内或复合语句内定义的变量以及形参。作用域:函数内或复合语句内。,【例7.19】分析下面程序的运行结果及变量的作用域。,问题:一个变量在程序的哪个函数中都能使用吗?,2019/11/26,34,voidsub(inta,intb)intc;a=a+b;b=b+a;c=b-a;printf(sub:ta=%db=%dc=%dn,a,b,c);,main()inta=1,b=1,c=1;printf(main:ta=%db=%dc=%dn,a,b,c);sub(a,b);printf(main:ta=%db=%dc=%dn,a,b,c);inta=2,b=2;printf(comp:ta=%db=%dc=%dn,a,b,c);printf(main:ta=%db=%dc=%dn,a,b,c);,“分程序”或“程序块”,程序输出结果:main:a=1b=1c=1sub:a=2b=3c=1main:a=1b=1c=1comp:a=2b=2c=1main:a=1b=1c=1,2019/11/26,35,7.5.3全局变量及其作用域,全局变量(外部变量):在函数外部定义的变量。作用域:从定义变量的位置开始到本源文件结束。如在其作用域内的函数或分程序中定义了同名局部变量,则在局部变量的作用域内,同名全局变量暂时不起作用。,【例7.20】全局变量和局部变量的作用域。,2019/11/26,36,inta=5;voidf(intx,inty)intb,c;b=a+x;c=a-y;printf(%dt%dt%dn,a,b,c);,程序输出结果:511-2567987981098105610,全局变量,2019/11/26,37,7.6变量的存储类别及变量的生存期,7.6.1变量的生存期与变量的存储分类,变量的生存期:变量在内存中占据存储空间的时间。,思考:1.何时为变量分配内存单元?2.将变量分配在内存的什么区域?3.变量占据内存的时间(生存期)?,动态存储变量,静态存储变量,2019/11/26,38,7.6.2变量的存储类别,变量的属性,数据类型:决定为变量分配内存单元的长度,数据的存放形式,数的范围。,存储类别:决定了变量的生存期,给它分配在哪个存储区。,2019/11/26,39,变量定义语句的一般形式,存储类别数据类型变量名1,变量名n;,auto(自动的)register(寄存器的)static(静态的)extern(外部的),1自动变量(auto类别)局部变量可以定义为自动变量。,2019/11/26,40,main()inta,b,c;printf(“Entera,b:n”);scanf(“%d%d”,printf(“Entera,b:n”);,scanf(“%d%d”,c=sum(a,b);,c=a+b;,return(c);,printf(“Sum=%dn”,c);,main(),Entera,b:,内存用户区,静态存储区,12,sum(inta,intb),Sum=3,程序,程序区,动态存储区,观察下列程序运行时变量的存储情况,单击开始运行,运行结束,cm=3,2019/11/26,41,内存分配调用函数或执行分程序时在动态存储区为其分配存储单元,函数或分程序执行结束,所占内存空间即刻释放。变量的初值定义变量时若没赋初值,变量的初值不确定;如果赋初值则每次函数被调用时执行一次赋值操作。生存期在函数或分程序执行期间。作用域自动变量所在的函数内或分程序内。,自动变量,2019/11/26,42,2静态变量(static类别),除形参外,局部变量和全局变量都可以定义为静态变量。,2019/11/26,43,staticintb=0;main()inta=2,i;for(i=0;i2;i+)printf(%4d,f(a);printf(n);intf(inta)staticintc=3;b+;c+;return(a+b+c);,内存用户区,静态存储区,程序区,动态存储区,【例7.22】静态变量的使用。,b=0,c=3,main(),程序,am=2,i不定,for(i=0;i2;i+),i=0,printf(%4d,f(a);,intf(inta),af=2,c=4,b+;c+;,b=1,return(a+b+c);,7,for(i=0;i2;i+),i=1,printf(%4d,f(a);,intf(inta),af=2,b+;c+;,b=2,c=5,return(a+b+c);,9,i=2,printf(n);,单击开始运行,运行结束,for(i=0;i2;i+),2019/11/26,44,内存分配编译时,将其分配在内存的静态存储区中,程序运行结束释放该单元。静态变量的初值若定义时未赋初值,在编译时,系统自动赋初值为0;若定义时赋初值,则仅在编译时赋初值一次,程序运行后不再给变量赋初值。生存期整个程序的执行期间。作用域局部静态变量的作用域是它所在的函数或分程序。全局静态变量的作用域是从定义处开始到本源文件结束。,静态变量,2019/11/26,45,intc;staticinta;main()floatx,y;chars;f()staticintb=1;,3.外部变量(extern类别),在函数外定义的变量若没有用static说明,则是外部变量。外部变量只能隐式定义为extern类别,不能显式定义。,2019/11/26,46,内存分配编译时,将其分配在静态存储区,程序运行结束释放该单元。变量的初值若定义变量时未赋初值,在编译时,系统自动赋初值为0。生存期整个程序的执行期间。作用域从定义处开始到本源文件结束。此外,还可以用extern进行声明,以使其作用域扩大到该程序的其它文件中。,外部变量,问题:全局静态变量的作用域可以扩展到本程序的其它文件吗?,2019/11/26,47,外部变量声明的一般格式,extern数据类型变量名1,变量名n;或extern变量名1,变量名n;,注意:外部变量声明用关键字extern,而外部变量的定义不能用extern,只能隐式定义。定义外部变量时,系统要给变量分配存储空间,而对外部变量声明时,系统不分配存储空间,只是让编译系统知道该变量是一个已经定义过的外部变量,与函数声明的作用类似。,2019/11/26,48,intp=1,q=5;floatf1(inta)externcharc1,c2;cha
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 商场装修合同
- 三水杨酸胆碱镁销售合同3篇
- (翼人2024版)科学一年级上册2.5 简单工具 课件(新教材)
- 瑞典简介课件
- 安全方面培训班名称大全课件
- 理财实战课件
- 改造工程加固方案咨询(3篇)
- 安全教训培训课件
- 房屋工程规划方案(3篇)
- 地铁工程复工方案(3篇)
- 公司级新员工安全培训正式版
- 大桥施工图审查报告
- YY/T 0719.10-2022眼科光学接触镜护理产品第10部分:保湿润滑剂测定方法
- YC/T 320-2009烟草商业企业管理体系规范
- GB/T 12755-1991建筑用压型钢板
- 燃气轮机介绍课件
- 2023年南京江宁交通建设集团有限公司招聘笔试模拟试题及答案解析
- 消防安全检查申报表
- 海飞丝销售策划书模板
- 工程技术研究中心(重点实验室)可行性研究报告
- 城市轨道交通综合监控系统整套课件汇总完整版电子教案(全)
评论
0/150
提交评论