好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

c语言(谭浩强)第4章模块化程序设计.ppt

60页
  • 卖家[上传人]:tian****1990
  • 文档编号:75153156
  • 上传时间:2019-01-30
  • 文档格式:PPT
  • 文档大小:462.31KB
  • / 60 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 第4章 模块化程序设计,●函 数 ●变量的存储属性 ● 模块的编译和链接 ● 宏定义与宏替换,第4章 模块化程序设计,C语言是一种较现代的程序开发语言它提供如下一些支持模块化软件开发的功能: (1) C语言用函数组织程序,在C语言程序中,一个程序由一个或多个程序文件组或,每一个程序文件就是一个程序模块,每一个程序模块由一个或多个函数组成程序设计的任务就是设计一个个函数,并且确定它们之间的调用关系在设计函数时要使每个函数都具有各自独立的功能和明显的界面 (2) 通过给变量定义不同的存储类别,控制模块内部及外部的信息交换 (3) 具有编译预处理功能,为程序的调试、移植提供了方便,也支持了模块化程序设计4.1函 数,4.1.1 设计C语言程序就是设计函数 无论涉及的问题是复杂还是简单,规模是大还是小,用C语言设计程序,任务只有一种,就是编写函数,至少也要编写一个main函数执行C程序也就是执行相应的main函数即从main函数的第一个前花括号开始,依次执行后面的语句,直到最后的后花括号为止 模块化程序设计有一个原则:就是每个模块的规模一般不能太大(有人认为要控制在40~60行之间),以便于阅读,便于检查其中的错误。

      在C语言中,减少主函数规模的一项基本措施就是通过调用其它函数来实现主函数需要的一些功能4.1.2 函数结构,为了定义函数,必须首先了解函数的结构一个C语言函数的结构形式如下: 函数头 { 函数体 },1. 函数头函数类型 函数名(形式参数表列) 一个函数的函数头的结构如下: (1)函数类型指定函数值的类型,即函数返回值的类型 (2)函数名函数名必须采用合法的用户标识符 (3)圆括号:在函数名后面的一对圆括号是“函数运算符”,表示进行函数运算,函数运算符具有很高的运算优先级别 (4)形式参数表形式参数表由写在一对圆括号(函数运算符)中的一系列参数组成每一个参数由一个类型符和一个参数名组成参数名也应当是合法的用户关键字函数可以没有参数,这时在函数运算符内写一个“void”,也可以空允白2. 函数体 函数体由一些语句组成主要是三种类型的语句: 声明语句:声明在函数中要使用的变量等程序实体 用来实现函数的功能的可执行语句:包括若干流程控制 语句和表达式语句, return语句使流程返回到调用处 这里主要介绍return语句的用法 当函数执行到return语句时,将停止本函数的执行,将流程送回到调用处。

      同时,编译器将函数分为三类进行处理: 纯粹计算型函数,如squt()和sin()这类函数将返回一个计算结果 完成一项具体工作,返回完成的成败如printf()执行成功时,返回显示的字节数;失败时,返回一个负整数 只执行一个过程的函数,不产生返回值,其类型应定义为void C99规定,对于非void类型的函数,必须使用有返回值的return语句int absolutevalue (int x) { return (x=0?x:-x); } void spc (int n) { int i; for (i=0; in;i++)它 printf (″ ″); return; },3. 函数中变量的作用域,作用域指的是一个程序段中的代码的作用范围,在一个函数中定义的变量只在本函数中有效,在其它函数中不能使用这个变量,因此说,该变量的作用域是它所在的函数(从定义该变量的行开始到函数末尾)即使在不同的函数中定义了同名的变量,它们数也指的是不同的变量include int func(int x) { x=5; return x+3; } int main(void) { printf(“x=%d\n“,x); return 0; } 这个程序企图在main函数中使用func函数中的变量x。

      编译这个程序,系统将给出如下编译错误: c(13) : error C2065: 'x' : undeclared identifier,4. 空函数,空函数是一个不产生任何有效操作的函数,但它却是一个合法的C函数例如函数 void null (void){} 就是一个空函数 空函数多使用在模块化程序的设计或测试中一般首先写好main函数,确定需要调用的函数,然后逐步编写这些函数,如果在有一些函数还未编写好时想对已有俩编好的函数进行调试,可以先用空函数(函数名用将来使用的实际函数名,如sort)放在程序中原定的位置上,这样就可以调试程序的其它部分,等以后再逐步补上4.1.3 函数定义与函数声明,1. 函数定义 函数定义是按照C语言的语法规则引入新的函数,并提供如下信息: 函数的返回值类型(如果有); 参数的个数及类型和名称; 调用函数时要执行的代码; 函数的有效性2. 函数声明,函数声明是对所用到的函数的特征进行必要的声明编译系统以函数声明中给出的信息为依据,对调用表达式进行检测,例如,形参与实参类型是否一致,使用函数返回值的类型是否正确,以保证调用表达式与函数之间的参数正确传递 声明语句提供的必要信息包括:函数名,函数的类型,函数参数的个数、排列次序以及每个参数的类型。

      函数声明的一般格式为: 类型标识符 函数名(类型标识符形参,类型标识符形参,…);,设有一函数的定义为: double func (double a, int b, char c) { /* 函数体*/ } 与之相应的函数声明应为: double func (double x, int y, char z); /* 注意末尾的分号 */,4.1.4 虚实结合与传值调用,一个函数中的函数体,只有在该函数被调用时才会执行在函数被调用时,将要进行如下两个操作: 将函数调用中的实际参数值传送给函数定义中的形式参数; 将流程从调用处转到被调用的函数的开头,开始执行函数体中的代码1. 函数调用时的虚实结合,参数是函数调用时进行信息交换的载体实参是调用函数中的变量,形参是被调函数中的变量在函数调用过程中实现实参与形参的结合这称为“虚实结合” float add( ); int main(void) { float x=1.5, y=-5.7; printf (″%f+%f=%f\n″, x,y, add(x,y)); } float add (unsigned int a, unsigned int b) { printf(″a=%u, b=%u\n″, a,b); return (a+b); },2. 传值调用的虚实结合过程,程序进行编译时,并不为形式参数分配存储空间。

      只有在被调用时,形式参数才临时地占有存储空间,其过程如下: (1)调用开始,系统为形参开辟一个临时存储区,形参与实参各占一个独立的存储空间 (2)然后将各实参之值传递给形参,这时形参就得到了实参的值这种虚实结合方式称为“值结合” (3)函数返回时,临时存储区也被撤销 要特别注意在C程序中实参与形参结合的传值调用(call by value) 的特点即函数中对形参变量的操作不会影响到调用函数中的实参变量,即形参值不能传回给实参include void swap (int x, int y); int main(void) { int a=3, b=5; swap (a,b); printf (″a=%d, b=%d\n″, a,b); return 0; } void swap (int x, int y) { int temp; temp=x, x=y, y=temp; /* 交换变量的值 */ printf(″x=%d,y=%d\n″,x,y); } 执行结果: x=5,y=3 a=3,b=5,4.1.5 递归函数,由前面的学习已经知道,一个函数可以调用另一个函数C语言还允许一个函数自己调用自己(直接地或间接地调用自己)。

      于是形成一种特殊的函数结构——递归函数,并且,前者称为直接递归函数调用,后者称为间接递归调用函数递归计算n!的函数rfact( ) 通常,n的阶乘可以描述为: n!=1·2·…·n 但是,也可以描述为: n!= n·(n-1)·…·2·1 或者可以写为: n!= n·(n-1)! 更一般的形式是:,这就形成一个递归表达式这个递归表达式可以用下面的函数实现 long rfact(int n) { if (n0) { printf(″Negative argument to fact !\n″); exit (-1); } else if (n=1) return (1); else return (n*rfact (n-1)); /*自己调用自己*/ },当n=5时rfact的其调用和回代过程汉诺塔(Tower of Hanoi)问题据传古代印度布拉玛庙里僧侣们玩一种称为汉诺塔的游戏,据说游戏结束就标志着世界末日的到来游戏的装置是一块铜板,上面有三根杆,最左杆自下而上、由大到小顺序串有64个金盘,呈一个塔形(图4.8)游戏要求把左边杆上的金盘全部移到最右边的杆上,条件是一次只能够动一个盘,并且不允许大盘在小盘上面。

      容易推出,n个盘从一根杆移到另一根杆需要2n-1次,所以64个盘的移动次数为:264-1=18,446,744,073,709,511,615,这是一个天文数字,即使一台功能很强的现代计算机来解汉诺塔问题,每一微秒可能计算(不印出)一次移动,那么也需要几乎100万年而如果每秒移动一次,则需近5800亿年下面设计一个模拟僧侣们移动盘子的算法 假定僧侣们要把n个盘子按题中的规定由a杆借助c杆移到b杆模拟这一过程的算法称为hanoi(n,a,b,c)那么,很自然的想法是:,第一步:先把上面的n-1个盘子设法借助b杆放到c杆,如图4.8中的箭头①所示,记做hanoi(n-1, a,c,b) 第二步:把第n个盘子从a杆直接移到b杆,如图4.8中的箭头②所示 第三步:把c杆上的n-1个盘子借助a杆移到b杆,如图4.8中的箭头③所示,记做hanoi(n-1,c,b,a)include void hanoi(int n, char a, char b ,char c); int main(void) { int n; printf (“*************************************\n“); printf (“*Program for simulating the solution*\n“); printf (“** of the game of 'tower of Hanoi' **\n“); printf (“*************************************\n“); printf (“Please enter the number of disks to be moved:“); scanf (“%d“, ,hanoi (n,'a','b','c'); return 0; } void hanoi (int n, char a, char b, char c)/***汉诺塔问题***/ { if (n0) { hanoi (n-1, a,c,b); printf (“ Move disc %d from pile %c to %c\n“, n,a,b); (n-1, c,b,a); } },4.2 变量的存储属性,变量是对程序中数据存储的抽象。

      如前所述,C语言程序中的变量都是有类型的,数据类型是变量的运算属性的抽象,决定了该变量的取值范围和可以施加的运算种类除此之外,变量还有变量一些属性,例如: 一个变量在程序的哪个范围内是可以使用的——变量的可用域; 它什么时候生成以及什么时候被撤消——变量的生存期; 它存储在什么哪种类型的存储器中以及用什么机制进行存储——变量的存储区 这些都称为变量的存储属性4.2.1 变量的可用域和生存期,1. 局部变量和全局变量 变量的可用域是指。

      点击阅读更多内容
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.