函数调用函数原型_第1页
函数调用函数原型_第2页
函数调用函数原型_第3页
函数调用函数原型_第4页
函数调用函数原型_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

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

文档简介

1、函数调用函数原型内容提要函数定义、函数调用、函数原型、函数返回值难点:函数的参数传递与返回值 程序调试代码风格变量的作用域与存储类型 模块化程序设计 Skill:用函数编程求解问题的能力程序排错与调试的能力数学中的函数自变量因变量函数名说明自变量与因变量的映射关系程序设计中的函数程序设计中的函数不局限于计算计算类,如打印阶乘表的程序判断推理类,如排序、查找请问读多少行的程序能让你不头疼?假设系统提供的函数printf()由10行代码替换,那么你编过的程序会成什么样子?实际上一个printf()有上千行代码main()中能放多少行代码?如果所有代码都在main()中,怎么团队合作?如果代码都在一

2、个文件中,怎么团队合作?程序设计的艺术“事无巨细,“事必躬亲 管理学的观点是极其排斥这种做法的,认为工作必须分工,各司其职其中的思想,在程序设计里也适用 分而治之(Divide and Conquer,Wirth, 1971)函数把较大的任务分解成假设干个较小的任务,并提炼出公用任务程序设计的艺术信息隐藏Information Hiding, Parnas, 1972设计得当的函数可以把具体操作细节对程序中不需要知道它们的那些局部隐藏掉,从而使整个程序构造清楚使用函数时,不用知道这个函数内部是如何运作的,只按照我们的需要和它的参数形式调用它即可函数是C语言中模块化编程的最小单位可以把每个函数看

3、作一个模块如把编程比做制造一台机器,函数就好比其零部件可将这些“零部件单独设计、调试、测试好,用时拿出来装配,再总体调试。这些“零部件可以是自己设计制造/别人设计制造/现成的标准产品函数function和模块module函数function和模块module假设干相关的函数可以合并成一个“模块一个源程序文件由一个或多个函数组成一个C程序由一个或多个源程序文件组成C程序结构函数的分类函数生来都是平等的,互相独立的,没有上下贵贱和附属之分main()稍微特殊一点点C程序的执行从main函数开场调用其他函数后流程回到main函数在main函数中完毕整个程序运行函数的分类库函数ANSI/ISO C定义

4、的标准库函数符合标准的C语言编译器必须提供这些函数函数的行为也要符合ANSI/ISO C的定义第三方库函数由其它厂商自行开发的C语言函数库不在标准范围内,能扩大C语言的功能图形、网络、数据库等自定义函数自己编写的函数包装后,也可成为函数库,供别人使用函数定义definition类型 函数名(类型 参数1, 类型 参数2, )函数体;return 表达式;返回值类型函数名标识符说明运算规那么参数表相当于运算的操作数返回值是运算的结果函数出口函数定义definition类型 函数名(类型 参数1, 类型 参数2, )函数体;return 表达式;函数体的定界符参数表里的变量叫形式参数,parame

5、ter也是内部变量例5.1a 计算两个整数的平均数/* 函数功能: 计算平均数 函数入口参数: 整型x,存储第一个运算数 整型y,存储第二个运算数 函数返回值: 平均数*/int Average(int x, int y)int result;result = (x + y) / 2;return result;返回值类型函数名说明函数的功能返回值作为函数调用表达式的值形参表,函数入口函数内部可以定义只能自己使用的变量,称内部变量函数定义Function definitionvoid 函数名(void)函数体;return ;函数没有运算结果,无返回值,用void定义返回值类型用void定义参

6、数,表示没有参数return语句后不需要任何表达式函数调用Function call 函数名(表达式1, 表达式2, );调用函数时,提供的表达式叫实际参数(argument)有返回值时放到一个数值表达式中 c = max(a,b);作为另一个函数调用的参数 c = max(max(a,b),c); printf(%dn, max(a,b);无返回值时函数调用表达式 display(a,b); 返回值 = 函数名(实参表列); 函数名(实参表列);函数的每次执行都会建立一个全新的独立的环境在“栈中为函数的每个变量包括形式参数分配内存把实参值复制给形参开场执行函数内的第一条语句main() in

7、t a=12, b=24,ave; ave = Average(a,b); int Average(int x, int y) int result; result = (x + y) / 2; return result;函数调用的过程 y? x?result? b24 a12ave?1224函数内的代码在这个独立的环境内工作当函数执行到return语句或时函数退出程序从当次调用函数的地方继续执行函数可有多个return,但最好只有一个且是最后一行main() int a=12, b=24,ave; ave = Average(a,b); int Average(int x, int y)

8、int result; result = (x + y) / 2; return result;函数调用的过程 y? x?result? b24 a12ave?122418函数退出时求出返回值,存入一个可被调用者访问的地方收回分配给所有变量包括形式参数的内存程序控制权交给调用者,调用者拿到返回值,将其作为函数调用表达式的结果main() int a=12, b=24,ave; ave = Average(a,b); int Average(int x, int y) int result; result = (x + y) / 2; return result;函数调用的过程 y24 x12r

9、esult18 b24 a12ave?18函数参数传递从实参到形参是单向值传递形参值的改变不会影响对应的实参实参和形参必须匹配数目一致类型一一对应会发生自动类型转换函数的嵌套调用嵌套调用在调用一个函数的过程中,又调用另一个函数C语言规定函数不能嵌套定义,但可以嵌套调用函数是相互平行的 main()a();a 函数b();return;b函数return;递归Recursion函数直接或间接调用自己为递归unsigned long func(unsigned int n) if (n = 0) return 1;else return n * func(n-1); 用递归的方法求n! n! =n

10、*(n-1)! . (n-1)! =(n-1)*(n-2)! . (n-2)! . (n-3)! 4! : 3! =3*2! : 2! =2*1! : 1! =1*0! 0! =1回推过程递推过程每个递归函数必须至少有一个基线条件一般情况必须最终能简化为基线条件 递归层数太多易导致栈空间溢出后果很严重,程序被异常中止递归与迭代迭代即循环方法来编写的阶乘函数unsigned long factorial(unsigned int n) unsigned long fact = 1 ; unsigned int i ; for (i = 1; i = n ; i+) fact *= i ; ret

11、urn fact ;递归程序遵循了数学中对阶乘的定义因此递归方法编写程序具有更清晰、可读性更好的优点 递归与迭代优点:从编程角度来看,比较直观、精炼,逻辑清楚符合人的思维习惯,逼近数学公式的表示尤其适合非数值计算领域hanoi塔,骑士游历、八皇后问题回溯法缺点:增加了函数调用的开销,每次调用都需要进展参数传递、现场保护等从程序运行效率来看,大量重复计算,时空效率低应尽量用迭代形式替代递归形式函数原型Function prototype在调用一个函数之前要先对其返回值类型、函数名和参数进展声明declaration函数声明,也称函数原型有助于编译器进展类型检查不对函数进展声明是非常危险的例5.1

12、b 使用了Average函数的main() #include int Average(int x, int y);main()int a = 12;int b = 24;int ave;ave = Average(a, b);printf(Average of %d and %d is %d.n, a, b, ave);函数声明函数原型,声明时不要省略形参和返回值的类型函数调用#include /* 函数功能: 计算平均数 函数入口参数: 整型x,存储第一个运算数 整型y,存储第二个运算数 函数返回值: 平均数*/int Average(int x, int y)int result;resu

13、lt = (x + y) / 2;return result;main()int a = 12;int b = 24;int ave = Average(a, b);printf(Average of %d and %d is %d.n, a, b, ave);例5.1 函数定义也有声明函数的效果当返回值为整型或者函数定义在函数调用前面时,可以省略原型函数定义与函数声明的区别函数定义指函数功能确实立包括指定函数名、函数类型、形参及其类型、函数体等是完整独立的单位 函数声明是对函数名、函数返回值类型、形参类型的说明不包括函数体是一条语句,以分号完毕,只起一个声明作用循序渐进式编程实验4:小学生加

14、法考试题 通过输入两个加数给学生出一道加法运算题输入答案正确: right错误: Not correct! Try again!只答1次直到做对为止最多给3次机会随机出题连续做10道题统计分数循序渐进式编程实验4:小学生加法考试题 void Print(int flag) if (flag) printf(Right!n); else printf(Not correct!n);实验4:小学生加法考试题/* 函数功能: 计算两整型数之和,如果与用户输入的答案一样,那么返回1,否那么返回0 函数参数: 整型变量a和b,分别代表被加数和加数 函数返回值:当a加b的结果与用户输入的答案一样时,返回1

15、,否那么返回0*/int AddTest(int a, int b)int answer;printf(%d+%d=, a, b);scanf(%d, &answer);if (a+b = answer) return 1;else return 0;只答1次main() int a, b, answer; printf(Input a,b:); scanf(%d,%d, &a, &b); answer = AddTest(a, b); Print(answer);do while (answer = 0);实验4:小学生加法考试题 直到做对为止main() answer = AddTest(

16、a, b); Print(answer, chance); chance = 0; do chance+; while (answer = 0 & chance 3);实验4:小学生加法考试题 最多给3次机会 srand(time(NULL); error = 0; score = 0; for (i=0; i10; i+) a = rand()%10 + 1; b = rand()%10 + 1; answer = AddTest(a, b); Print(answer); if (answer = 1) score = score + 10; else error+; 实验4:小学生加法考

17、试题 随机出题连续做10道题统计分数程序调试实例#include #include int Factorial(int x);main()int x;printf(Please input x(=0):);scanf(%d, &x);if (x = -1) exit(0);/*退出程序*/else printf(The factorial of %d is %d.n, x, Factorial(x);存在一处错误!程序调试实例#include int Factorial(int x);main()int x;doprintf(Please input x(=0):);scanf(%d, &x)

18、;while (x0); printf(The factorial of %d is %d.n, x, Factorial(x);更好的编程方法!程序调试实例/* 函数功能: 计算x的阶乘 函数入口参数: 整型x 函数返回值: 阶乘运算结果*/int Factorial(int x)int i, result;for (i=1; i=x; i+)result *= i;return result;存在两个问题!输入17或者在TC下或将int改成short输入8试一试程序调试实例/* 函数功能: 计算x的阶乘 函数入口参数: 无符号长整型x 函数返回值: 阶乘运算结果*/unsigned lon

19、g Factorial(unsigned int x)unsigned long i, result = 1;for (i=2; i=x; i+)result *= i;return result;同时需修改函数原型和主函数中的打印格式assert()名唤:断言 #include void assert(int expression);expression为真,无声无息; 为假,中断程序。用来测试某种不可能发生的状况确实不会发生Debug版有效Release版失效只为调试程序用,不可作为程序的功能assert()#include unsigned long Factorial(unsigned

20、 int x);.unsigned long Factorial(unsigned int x)unsigned long i, result = 1;assert(x=0);for (i=2; i=x; i+)result *= i;return result;这里的断言有意义吗?assert()参加断言检查函数的入口参数#include 软件测试测试的主要方式给定特定的输入,运行被测软件检查软件的输出是否与预期结果一致测试用例的选取方法尽量覆盖所有分支,减少重复覆盖测试的目的通过运行测试用例找出软件中的Bug成功的测试在于发现迄今为止尚未发现的Bug测试人员的主要任务是站在使用者的角度,通

21、过不断使用和攻击,尽可能多的找出Bug测试的过程就像黑客的攻击过程,专门找软件漏洞软件测试采用测试用例,通过运行程序查找程序错误的方法实质是一种抽样检查,彻底的测试是不可能的彻底的测试不现实,要考虑时间费用等限制,不允许无休止的测试测试只能证明程序有错,不能证明程序无错测试能提高软件质量,但提高软件质量不能依赖于测试软件测试方法的分类从代码和用户使用的角度分类覆盖性测试从代码特性的角度即内部出发的测试单元测试,功能测试,提交测试,根本验证测试,回归测试使用测试从用户的角度即外部出发的测试配置测试,兼容性测试,性能测试,Alpha和Beta测试,强力测试,文档和帮助文件测试软件测试方法的分类第2

22、种分类方法白盒测试构造测试在完全了解程序的构造和处理过程的情况下,按照程序内部的逻辑测试程序,检验程序中的每条逻辑路径是否都能按预定要求正确工作主要用于测试的早期黑盒测试功能测试把系统看成一个黑盒子,不考虑程序内部的逻辑构造和处理过程,只根据需求规格说明书的要求,设计测试用例,检查程序的功能是否符合它的功能说明主要用于测试的后期通常结合使用选择有限数量的重要路径进展白盒测试对重要的功能需求进展黑盒测试软件测试方法的分类第3种分类方法手工测试依靠人力来查找Bug自动测试编写一些测试工具,让他们自动运行来查找Bug优点:快,广泛缺点:只能检查一些最重要的问题,如内存泄漏、死机等,无法发现一般性的日

23、常错误,而且编写测试工具的工作量很大软件测试方法的分类案例1:微软开发Exchange Server时常常要做强力测试需要几万个甚至几十万个用户同时把 E-mail发送到效劳器,以保证Server不会死机只能利用测试工具,自动产生几万个账号,同一时间从不同机器上同时发送E-mail软件测试方法的分类案例2:测试Web页面浏览器时要求50000个用户同时浏览一个web页面,以保证网站的效劳器不会死机通过测试工具很容易做到,而且工具可以自动判断浏览结果是否正确程序改错是个大悲大喜的过程,一天之内可以让人在悲伤的低谷和喜悦的巅峰之间跌宕起伏。如果改正了成千上万个错误,程序改错改错的第一步是找出错误的

24、根源,然后对症下药调试寻找错误根源的过程改错很像侦破案件,有坏事发生了,而仅有的信息是它确实发生了。必须从结果出发,逆向思考程序改错难点在于病症和根源可能相隔很远有人问阿凡提:“我肚子疼,该用什么药?病症可能在另一个错误被纠正后暂时消失病症并不是某个程序错误引发的,如误差累积病症可能时隐时现,如“内存泄露很难产生完全一样的输入条件,难以恢复“错误的现场程序中常见的错误编译错误指在编译过程中发现的错误,通常属于语法错误即编写的语句不符合C语言的语法规那么Undefined symbol xxx 标识符xxx未定义Expression syntax error 表达式语法错误Too few par

25、ameter in call 函数调用时的实参少于函数的形参运行时错误指在程序运行时发生的错误往往是由于语义上的错误造成的即语句虽然符合语法,但要求计算机去做不该做或做不到的事情。当用0做除数时,运行后将显示“Division by zero错误提示信息,并立即返回编辑屏幕程序中常见的错误逻辑错误不影响程序运行,但运行结果不正确比较隐蔽,出错后不易查找变量未初始化,数组下标越界,数据类型溢出,运算符写错,.例如,关系运算符= 错写成 赋值运算符=if (a = b) printf(yes); /*导致运行结果错误*/Warning:Possibly incorrect assignment i

26、n function main程序中常见的错误错误案例判断字符是大写字符或者小写字符(a = ch = z) | (A = ch =a&ch=A&ch=Z)/*正确*/判断字符是数字字符0 = ch = 0 & ch = 9 /*正确*/错误案例数据类型由高向低赋值时,进展类型转换后导致信息丧失double a, b;int sum;sum = a + b;TC下编译,不提示任何错误VC下编译warning C4244: = : conversion from double to int , possible loss of data错误案例函数声明时的返回值类型与实际返回的数据类型不一致,导致自动类型转换double Add(double a, double b) int sum; return sum; /不提示warning int Add(double a, double b) double sum; return sum; warning C4244: return : conversion from double to int , possible loss of data程序调试的根本方法利用调试工具单步运行,逐条语句跟

温馨提示

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

评论

0/150

提交评论