版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
内容提要函数定义、函数调用、函数原型、函数返回值难点:函数的参数传递与返回值程序调试代码风格变量的作用域与存储类型模块化程序设计Skill:用函数编程求解问题的能力程序排错与调试的能力第一页第二页,共63页。数学中的函数自变量因变量函数名说明自变量与因变量的映射关系第二页第三页,共63页。程序设计中的函数程序设计中的函数不局限于计算计算类,如打印阶乘表的程序……判断推理类,如排序、查找……第三页第四页,共63页。请问读多少行的程序能让你不头疼?假如系统提供的函数printf()由10行代码替换,那么你编过的程序会成什么样子?实际上一个printf()有上千行代码main()中能放多少行代码?如果所有代码都在main()中,怎么团队合作?如果代码都在一个文件中,怎么团队合作?第四页第五页,共63页。程序设计的艺术“事无巨细”,“事必躬亲”管理学的观点是极其排斥这种做法的,认为工作必须分工,各司其职其中的思想,在程序设计里也适用分而治之(DivideandConquer,Wirth,1971)函数把较大的任务分解成若干个较小的任务,并提炼出公用任务第五页第六页,共63页。程序设计的艺术信息隐藏(InformationHiding,Parnas,1972)设计得当的函数可以把具体操作细节对程序中不需要知道它们的那些部分隐藏掉,从而使整个程序结构清楚使用函数时,不用知道这个函数内部是如何运作的,只按照我们的需要和它的参数形式调用它即可第六页第七页,共63页。函数是C语言中模块化编程的最小单位可以把每个函数看作一个模块如把编程比做制造一台机器,函数就好比其零部件可将这些“零部件”单独设计、调试、测试好,用时拿出来装配,再总体调试。这些“零部件”可以是自己设计制造/别人设计制造/现成的标准产品函数(function)和模块(module)第七页第八页,共63页。函数(function)和模块(module)若干相关的函数可以合并成一个“模块”一个源程序文件由一个或多个函数组成一个C程序由一个或多个源程序文件组成C程序结构第八页第九页,共63页。函数的分类函数生来都是平等的,互相独立的,没有高低贵贱和从属之分main()稍微特殊一点点C程序的执行从main函数开始调用其他函数后流程回到main函数在main函数中结束整个程序运行第九页第十页,共63页。函数的分类库函数ANSI/ISOC定义的标准库函数符合标准的C语言编译器必须提供这些函数函数的行为也要符合ANSI/ISOC的定义第三方库函数由其它厂商自行开发的C语言函数库不在标准范围内,能扩充C语言的功能(图形、网络、数据库等)自定义函数自己编写的函数包装后,也可成为函数库,供别人使用第十页第十一页,共63页。函数定义(definition)类型函数名(类型参数1,类型参数2,……)
{
函数体;
return
表达式;
}返回值类型函数名标识符说明运算规则参数表相当于运算的操作数返回值是运算的结果函数出口第十一页第十二页,共63页。函数定义(definition)类型函数名(类型参数1,类型参数2,……)
{
函数体;
return
表达式;
}函数体的定界符参数表里的变量(叫形式参数,parameter)也是内部变量第十二页第十三页,共63页。例5.1a计算两个整数的平均数/*
函数功能:计算平均数函数入口参数:整型x,存储第一个运算数整型y,存储第二个运算数函数返回值:平均数*/intAverage(intx,inty){
intresult; result=(x+y)/2;
returnresult;}返回值类型函数名说明函数的功能返回值作为函数调用表达式的值形参表,函数入口函数内部可以定义只能自己使用的变量,称内部变量第十三页第十四页,共63页。函数定义(Functiondefinition)void
函数名(void)
{
函数体;
return;
}函数没有运算结果,无返回值,用void定义返回值类型用void定义参数,表示没有参数return语句后不需要任何表达式第十四页第十五页,共63页。函数调用(Functioncall)函数名(表达式1,表达式2,……);调用函数时,提供的表达式叫实际参数(argument)有返回值时放到一个数值表达式中
c=max(a,b);作为另一个函数调用的参数
c=max(max(a,b),c);printf("%d\n",max(a,b));无返回值时函数调用表达式display(a,b);返回值=函数名(实参表列);函数名(实参表列);第十五页第十六页,共63页。函数的每次执行都会建立一个全新的独立的环境在“栈”中为函数的每个变量(包括形式参数)分配内存把实参值复制给形参开始执行函数内的第一条语句main(){inta=12,b=24,ave;…ave=Average(a,b);
……}intAverage(intx,inty){intresult;result=(x+y)/2;returnresult;}①函数调用的过程y?x?result?b24a12ave?1224第十六页第十七页,共63页。函数内的代码在这个独立的环境内工作当函数执行到return语句或}时函数退出程序从当次调用函数的地方继续执行函数可有多个return,但最好只有一个且是最后一行main(){inta=12,b=24,ave;…ave=Average(a,b);
……}intAverage(intx,inty){intresult;result=(x+y)/2;returnresult;}③②函数调用的过程y?x?result?b24a12ave?122418第十七页第十八页,共63页。函数退出时求出返回值,存入一个可被调用者访问的地方收回分配给所有变量(包括形式参数)的内存程序控制权交给调用者,调用者拿到返回值,将其作为函数调用表达式的结果main(){inta=12,b=24,ave;…ave=Average(a,b);
……}intAverage(intx,inty){intresult;result=(x+y)/2;returnresult;}函数调用的过程y24x12result18b24a12ave?18第十八页第十九页,共63页。函数参数传递从实参到形参是单向值传递形参值的改变不会影响对应的实参实参和形参必须匹配数目一致类型一一对应(会发生自动类型转换)第十九页第二十页,共63页。函数的嵌套调用嵌套调用在调用一个函数的过程中,又调用另一个函数C语言规定函数不能嵌套定义,但可以嵌套调用函数是相互平行的main(){……a();}a
函数{b();…return;}b函数{……return;}①③④⑤⑥⑦②第二十页第二十一页,共63页。递归(Recursion)函数直接或间接调用自己为递归 unsigned
long
func(unsigned
intn)
{
if(n==0)
return1;
else
returnn*func(n-1);
}第二十一页第二十二页,共63页。用递归的方法求n!
n!=n*(n-1)!..(n-1)!=(n-1)*(n-2)!..(n-2)!..(n-3)!4!:3!=3*2!:2!=2*1!:1!=1*0!0!=1回推过程递推过程每个递归函数必须至少有一个基线条件一般情况必须最终能简化为基线条件递归层数太多易导致栈空间溢出后果很严重,程序被异常中止第二十二页第二十三页,共63页。递归与迭代迭代即循环方法来编写的阶乘函数unsignedlongfactorial(unsigned
intn){
unsignedlongfact=1;
unsignedinti;
for(i=1;i<=n;i++)fact*=i;
returnfact;}递归程序遵循了数学中对阶乘的定义因此递归方法编写程序具有更清晰、可读性更好的优点第二十三页第二十四页,共63页。递归与迭代优点:从编程角度来看,比较直观、精炼,逻辑清楚符合人的思维习惯,逼近数学公式的表示尤其适合非数值计算领域hanoi塔,骑士游历、八皇后问题(回溯法)缺点:增加了函数调用的开销,每次调用都需要进行参数传递、现场保护等从程序运行效率来看,大量重复计算,时空效率低应尽量用迭代形式替代递归形式第二十四页第二十五页,共63页。函数原型(Functionprototype)在调用一个函数之前要先对其返回值类型、函数名和参数进行声明(declaration)函数声明,也称函数原型有助于编译器进行类型检查不对函数进行声明是非常危险的第二十五页第二十六页,共63页。例5.1b使用了Average函数的main()
#include<stdio.h>intAverage(intx,inty);main(){
inta=12;
intb=24;
intave; ave=Average(a,b);
printf("Averageof%dand%dis%d.\n",a,b,ave);}函数声明(函数原型),声明时不要省略形参和返回值的类型函数调用第二十六页第二十七页,共63页。#include<stdio.h>/*
函数功能:计算平均数函数入口参数:整型x,存储第一个运算数整型y,存储第二个运算数函数返回值:平均数*/intAverage(intx,inty){
intresult; result=(x+y)/2;
returnresult;}main(){
inta=12;
intb=24;
intave=Average(a,b);
printf("Averageof%dand%dis%d.\n",a,b,ave);}例5.1函数定义也有声明函数的效果当返回值为整型或者函数定义在函数调用前面时,可以省略原型第二十七页第二十八页,共63页。函数定义与函数声明的区别函数定义指函数功能的确立包括指定函数名、函数类型、形参及其类型、函数体等是完整独立的单位
函数声明是对函数名、函数返回值类型、形参类型的说明不包括函数体是一条语句,以分号结束,只起一个声明作用第二十八页第二十九页,共63页。循序渐进式编程
实验4:小学生加法考试题通过输入两个加数给学生出一道加法运算题输入答案正确:right错误:Notcorrect!Tryagain!第二十九页第三十页,共63页。只答1次直到做对为止最多给3次机会随机出题连续做10道题统计分数循序渐进式编程
实验4:小学生加法考试题第三十页第三十一页,共63页。voidPrint(intflag){if(flag)printf("Right!\n");else printf("Notcorrect!\n");}实验4:小学生加法考试题/*函数功能:计算两整型数之和,如果与用户输入的答案相同,则返回1,否则返回0
函数参数:整型变量a和b,分别代表被加数和加数函数返回值:当a加b的结果与用户输入的答案相同时,返回1,否则返回0*/intAddTest(inta,intb){
intanswer; printf("%d+%d=",a,b); scanf("%d",&answer);
if(a+b==answer)
return1;
else
return0;}只答1次第三十一页第三十二页,共63页。main(){inta,b,answer;printf("Inputa,b:");scanf("%d,%d",&a,&b); answer=AddTest(a,b); Print(answer);}do{
}while(answer==0);实验4:小学生加法考试题直到做对为止第三十二页第三十三页,共63页。main(){……
answer=AddTest(a,b);
Print(answer,chance);
}chance=0;
do{
chance++;}while(answer==0&&chance<3);实验4:小学生加法考试题最多给3次机会第三十三页第三十四页,共63页。
srand(time(NULL));error=0;score=0;
for(i=0;i<10;i++){
a=rand()%10+1;b=rand()%10+1;answer=AddTest(a,b);Print(answer);
if(answer==1)score=score+10;
elseerror++;
}实验4:小学生加法考试题随机出题连续做10道题统计分数第三十四页第三十五页,共63页。程序调试实例#include<stdio.h>#include<stdlib.h>intFactorial(intx);main(){
intx;
printf("Pleaseinputx(>=0):");
scanf("%d",&x);
if(x==-1) exit(0); /*退出程序*/
else
printf("Thefactorialof%dis%d.\n",x,Factorial(x)); }存在一处错误!第三十五页第三十六页,共63页。程序调试实例#include<stdio.h>intFactorial(intx);main(){
intx;
do{
printf("Pleaseinputx(>=0):");
scanf("%d",&x); }while(x<0);printf("Thefactorialof%dis%d.\n",x,Factorial(x));}更好的编程方法!第三十六页第三十七页,共63页。程序调试实例/*
函数功能:计算x的阶乘
函数入口参数:整型x
函数返回值:阶乘运算结果*/intFactorial(intx){
inti,result;
for(i=1;i<=x;i++) result*=i;
returnresult;}存在两个问题!输入17或者在TC下(或将int改成short)输入8试一试第三十七页第三十八页,共63页。程序调试实例/*
函数功能:计算x的阶乘
函数入口参数:无符号长整型x
函数返回值:阶乘运算结果*/unsigned
longFactorial(unsignedintx){
unsignedlongi,result=1;
for(i=2;i<=x;i++) result*=i;
returnresult;}同时需修改函数原型和主函数中的打印格式第三十八页第三十九页,共63页。assert()名唤:断言#include<assert.h>
voidassert(intexpression);expression为真,无声无息;
为假,中断程序。用来测试某种不可能发生的状况确实不会发生Debug版有效Release版失效只为调试程序用,不可作为程序的功能第三十九页第四十页,共63页。assert()#include<assert.h>
unsigned
longFactorial(unsignedintx);......unsigned
longFactorial(unsignedintx){
unsignedlongi,result=1;
assert(x>=0);
for(i=2;i<=x;i++) result*=i;
returnresult;}这里的断言有意义吗?第四十页第四十一页,共63页。assert()加入断言检查函数的入口参数#include<assert.h>第四十一页第四十二页,共63页。软件测试测试的主要方式给定特定的输入,运行被测软件检查软件的输出是否与预期结果一致测试用例的选取方法尽量覆盖所有分支,减少重复覆盖测试的目的通过运行测试用例找出软件中的Bug成功的测试在于发现迄今为止尚未发现的Bug测试人员的主要任务是站在使用者的角度,通过不断使用和攻击,尽可能多的找出Bug测试的过程就像黑客的攻击过程,专门找软件漏洞第四十二页第四十三页,共63页。软件测试采用测试用例,通过运行程序查找程序错误的方法实质是一种抽样检查,彻底的测试是不可能的彻底的测试不现实,要考虑时间费用等限制,不允许无休止的测试测试只能证明程序有错,不能证明程序无错——E.W.Dijkstra测试能提高软件质量,但提高软件质量不能依赖于测试第四十三页第四十四页,共63页。软件测试方法的分类从代码和用户使用的角度分类覆盖性测试从代码特性的角度(即内部)出发的测试单元测试,功能测试,提交测试,基本验证测试,回归测试使用测试从用户的角度(即外部)出发的测试配置测试,兼容性测试,性能测试,Alpha和Beta测试,强力测试,文档和帮助文件测试第四十四页第四十五页,共63页。软件测试方法的分类第2种分类方法白盒测试(结构测试)在完全了解程序的结构和处理过程的情况下,按照程序内部的逻辑测试程序,检验程序中的每条逻辑路径是否都能按预定要求正确工作主要用于测试的早期黑盒测试(功能测试)把系统看成一个黑盒子,不考虑程序内部的逻辑结构和处理过程,只根据需求规格说明书的要求,设计测试用例,检查程序的功能是否符合它的功能说明主要用于测试的后期通常结合使用选择有限数量的重要路径进行白盒测试对重要的功能需求进行黑盒测试第四十五页第四十六页,共63页。软件测试方法的分类第3种分类方法手工测试依靠人力来查找Bug自动测试编写一些测试工具,让他们自动运行来查找Bug优点:快,广泛缺点:只能检查一些最重要的问题,如内存泄漏、死机等,无法发现一般性的日常错误,而且编写测试工具的工作量很大第四十六页第四十七页,共63页。软件测试方法的分类案例1:微软开发ExchangeServer时常常要做强力测试需要几万个甚至几十万个用户同时把E-mail发送到服务器,以保证Server不会死机只能利用测试工具,自动产生几万个账号,同一时间从不同机器上同时发送E-mail第四十七页第四十八页,共63页。软件测试方法的分类案例2:测试Web页面浏览器时要求50000个用户同时浏览一个web页面,以保证网站的服务器不会死机通过测试工具很容易做到,而且工具可以自动判断浏览结果是否正确第四十八页第四十九页,共63页。程序改错是个大悲大喜的过程,一天之内可以让人在悲伤的低谷和喜悦的巅峰之间跌宕起伏。如果改过了成千上万个错误,……第四十九页第五十页,共63页。程序改错改错的第一步是找出错误的根源,然后对症下药调试寻找错误根源的过程改错很像侦破案件,有坏事发生了,而仅有的信息是它的确发生了。必须从结果出发,逆向思考第五十页第五十一页,共63页。程序改错难点在于症状和根源可能相隔很远有人问阿凡提:“我肚子疼,该用什么药?”症状可能在另一个错误被纠正后暂时消失症状并不是某个程序错误引发的,如误差累积症状可能时隐时现,如“内存泄露”很难产生完全一样的输入条件,难以恢复“错误的现场”第五十一页第五十二页,共63页。程序中常见的错误编译错误指在编译过程中发现的错误,通常属于语法错误即编写的语句不符合C语言的语法规则Undefinedsymbol‘xxx’标识符xxx未定义Expressionsyntaxerror表达式语法错误Toofewparameterincall函数调用时的实参少于函数的形参第五十二页第五十三页,共63页。运行时错误指在程序运行时发生的错误往往是由于语义上的错误造成的即语句虽然合乎语法,但要求计算机去做不该做或做不到的事情。当用0做除数时,运行后将显示“Divisionbyzero”错误提示信息,并立即返回编辑屏幕程序中常见的错误第五十三页第五十四页,共63页。逻辑错误不影响程序运行,但运行结果不正确比较隐蔽,出错后不易查找变量未初始化,数组下标越界,数据类型溢出,运算符写错,......例如,关系运算符==错写成赋值运算符=if(a=b)printf("yes");/*导致运行结果错误*/Warning:Possiblyincorrectassignmentinfunctionmain程序中常见的错误第五十四页第五十五页,共63页。错误案例判断字符是大写字符或者小写字符('a'<=ch<='z')||('A'<=ch<='Z')/*不提示任何错误,但导致运行结果错误*/(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')/*正确*/判断字符是数字字符'0'<=ch<='9'/*不提示任何错误,但导致运行结果错误*/ch>='0'&&ch<='9'/*正确*/第五十五页第五十六页,共63页。错误案例数据类型由高向低赋值时,进行类型转换后导致信息丢失doublea,b;intsum;sum=a+b;TC下编译,不提示任何错误VC下编译warningC4244:'=':conversionfrom'double'to'int',possiblelossofdata第五十六页第五十七页,共63页。错误案例函数声明时的返回值类型与实际返回的数据类型不一致,导致自动类型转换doubleAdd(doublea,doubleb){
intsum;……returnsum;}//不提示warningintAdd(doublea,doubleb){doublesum;……returnsum;}warningC4244:'return':conversionfrom'double'to'int',possiblelossofdata第五十七页第五十八页,共63页。程序调试的基本方法利用调试工具单步运行,逐条语句跟踪观察变量值的变化调试的基本方法粗分细找,定位大致的范围归纳、推理、二分、排除世界上最好的调试工具是那些有经验的人没有任何语言和工具能防止我们犯错误第五十八页第五十九页,共63页。程序调试的基本方法粗分细找
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025河南省中考历史真题(原卷版)
- 2026年物流行业工作总结及计划
- 2026年国际课程数字化教材的版权保护与开发
- 2026年秋季呼吸道疾病预防知识海报
- 2026年医疗器械内审员远程办公与数字化审核能力培养
- 2025陕西省中考历史真题(原卷版)
- 2026年转基因食品营养与安全评价
- 2026年跨境直邮进口清关与国内派送
- 2026年商业综合体二次装修施工安全监管要点
- 上海立达学院《安装工程结构与施工》2025-2026学年第一学期期末试卷(B卷)
- 关节镜腘窝囊肿课件
- 八年级数学下册《一次函数》第一课时:从生活到模型的初步探索
- 航空运输专业毕业论文
- 2026年中国化工经济技术发展中心招聘备考题库及1套参考答案详解
- 2026届福建省厦门一中语文高三第一学期期末复习检测模拟试题含解析
- 全球价值链课件
- 化工事故应急处理培训
- 2025年纪检监察笔试题及答案
- 酒醉驾交通安全宣传课件
- 国网电力通信课件
- 备战2026年高考地理考试易错题(新高考)人文地理选择题50题专练(原卷版)
评论
0/150
提交评论