C语言(谭浩强)第4章模块化程序设计.ppt
《C语言(谭浩强)第4章模块化程序设计.ppt》由会员分享,可在线阅读,更多相关《C语言(谭浩强)第4章模块化程序设计.ppt(60页珍藏版)》请在三一办公上搜索。
1、第4章 模块化程序设计,函 数 变量的存储属性 模块的编译和链接 宏定义与宏替换,第4章 模块化程序设计,C语言是一种较现代的程序开发语言。它提供如下一些支持模块化软件开发的功能:(1)C语言用函数组织程序,在C语言程序中,一个程序由一个或多个程序文件组或,每一个程序文件就是一个程序模块,每一个程序模块由一个或多个函数组成。程序设计的任务就是设计一个个函数,并且确定它们之间的调用关系。在设计函数时要使每个函数都具有各自独立的功能和明显的界面。(2)通过给变量定义不同的存储类别,控制模块内部及外部的信息交换。(3)具有编译预处理功能,为程序的调试、移植提供了方便,也支持了模块化程序设计。,4.1
2、函 数,4.1.1 设计C语言程序就是设计函数 无论涉及的问题是复杂还是简单,规模是大还是小,用C语言设计程序,任务只有一种,就是编写函数,至少也要编写一个main函数。执行C程序也就是执行相应的main函数。即从main函数的第一个前花括号开始,依次执行后面的语句,直到最后的后花括号为止。模块化程序设计有一个原则:就是每个模块的规模一般不能太大(有人认为要控制在4060行之间),以便于阅读,便于检查其中的错误。在C语言中,减少主函数规模的一项基本措施就是通过调用其它函数来实现主函数需要的一些功能。,4.1.2 函数结构,为了定义函数,必须首先了解函数的结构。一个C语言函数的结构形式如下:函数
3、头函数体,1.函数头函数类型 函数名(形式参数表列)一个函数的函数头的结构如下:(1)函数类型。指定函数值的类型,即函数返回值的类型。(2)函数名。函数名必须采用合法的用户标识符。(3)圆括号:在函数名后面的一对圆括号是“函数运算符”,表示进行函数运算,函数运算符具有很高的运算优先级别(4)形式参数表。形式参数表由写在一对圆括号(函数运算符)中的一系列参数组成。每一个参数由一个类型符和一个参数名组成。参数名也应当是合法的用户关键字。函数可以没有参数,这时在函数运算符内写一个“void”,也可以空允白。,2.函数体 函数体由一些语句组成。主要是三种类型的语句:声明语句:声明在函数中要使用的变量等
4、程序实体。用来实现函数的功能的可执行语句:包括若干流程控制 语句和表达式语句,。return语句。使流程返回到调用处。这里主要介绍return语句的用法。当函数执行到return语句时,将停止本函数的执行,将流程送回到调用处。同时,编译器将函数分为三类进行处理:纯粹计算型函数,如squt()和sin()。这类函数将返回一个计算结果。完成一项具体工作,返回完成的成败。如printf()执行成功时,返回显示的字节数;失败时,返回一个负整数。只执行一个过程的函数,不产生返回值,其类型应定义为void。C99规定,对于非void类型的函数,必须使用有返回值的return语句。,int absolute
5、value(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=%dn,x);return 0;这个程序
6、企图在main函数中使用func函数中的变量x。编译这个程序,系统将给出如下编译错误:c(13):error C2065:x:undeclared identifier,4.空函数,空函数是一个不产生任何有效操作的函数,但它却是一个合法的C函数。例如函数void null(void)就是一个空函数。空函数多使用在模块化程序的设计或测试中。一般首先写好main函数,确定需要调用的函数,然后逐步编写这些函数,如果在有一些函数还未编写好时想对已有俩编好的函数进行调试,可以先用空函数(函数名用将来使用的实际函数名,如sort)放在程序中原定的位置上,这样就可以调试程序的其它部分,等以后再逐步补上。,4
7、.1.3 函数定义与函数声明,1.函数定义函数定义是按照C语言的语法规则引入新的函数,并提供如下信息:函数的返回值类型(如果有);参数的个数及类型和名称;调用函数时要执行的代码;函数的有效性。,2.函数声明,函数声明是对所用到的函数的特征进行必要的声明。编译系统以函数声明中给出的信息为依据,对调用表达式进行检测,例如,形参与实参类型是否一致,使用函数返回值的类型是否正确,以保证调用表达式与函数之间的参数正确传递。声明语句提供的必要信息包括:函数名,函数的类型,函数参数的个数、排列次序以及每个参数的类型。函数声明的一般格式为:类型标识符 函数名(类型标识符形参,类型标识符形参,);,设有一函数的
8、定义为:double func(double a,int b,char c)/*函数体*/与之相应的函数声明应为:double func(double x,int y,char z);/*注意末尾的分号*/,4.1.4 虚实结合与传值调用,一个函数中的函数体,只有在该函数被调用时才会执行。在函数被调用时,将要进行如下两个操作:将函数调用中的实际参数值传送给函数定义中的形式参数;将流程从调用处转到被调用的函数的开头,开始执行函数体中的代码。,1.函数调用时的虚实结合,参数是函数调用时进行信息交换的载体。实参是调用函数中的变量,形参是被调函数中的变量。在函数调用过程中实现实参与形参的结合。这称为“
9、虚实结合”。float add();int main(void)float x=1.5,y=-5.7;printf(%f+%f=%fn,x,y,add(x,y);float add(unsigned int a,unsigned int b)printf(a=%u,b=%un,a,b);return(a+b);,2.传值调用的虚实结合过程,程序进行编译时,并不为形式参数分配存储空间。只有在被调用时,形式参数才临时地占有存储空间,其过程如下:(1)调用开始,系统为形参开辟一个临时存储区,形参与实参各占一个独立的存储空间。(2)然后将各实参之值传递给形参,这时形参就得到了实参的值。这种虚实结合方式
10、称为“值结合”。(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=%dn,a,b);return 0;void swap(int x,int y)int temp;temp=x,x=y,y=temp;/*交换变量的值*/printf(x=%d,y=%dn,x,y);执行结果:x=5,
11、y=3a=3,b=5,4.1.5 递归函数,由前面的学习已经知道,一个函数可以调用另一个函数。C语言还允许一个函数自己调用自己(直接地或间接地调用自己)。于是形成一种特殊的函数结构递归函数,并且,前者称为直接递归函数调用,后者称为间接递归调用函数。,递归计算n!的函数rfact()。通常,n的阶乘可以描述为:n!=12n但是,也可以描述为:n!=n(n-1)21或者可以写为:n!=n(n-1)!更一般的形式是:,这就形成一个递归表达式。这个递归表达式可以用下面的函数实现。long rfact(int n)if(n0)printf(Negative argument to fact!n);exi
12、t(-1);else if(n=1)return(1);elsereturn(n*rfact(n-1);/*自己调用自己*/,当n=5时rfact的其调用和回代过程。,汉诺塔(Tower of Hanoi)问题。,据传古代印度布拉玛庙里僧侣们玩一种称为汉诺塔的游戏,据说游戏结束就标志着世界末日的到来。游戏的装置是一块铜板,上面有三根杆,最左杆自下而上、由大到小顺序串有64个金盘,呈一个塔形(图4.8)。游戏要求把左边杆上的金盘全部移到最右边的杆上,条件是一次只能够动一个盘,并且不允许大盘在小盘上面。容易推出,n个盘从一根杆移到另一根杆需要2n-1次,所以64个盘的移动次数为:264-1=18,
13、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
14、杆移到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
15、 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%cn,n,a,b);(n-1,c,b,a);,4.2 变量的存储属性,变量是对程序中数据存储的抽象。如前所述,C语言程序中的变量都是有类型的,数据类型是变量的运算属性的抽象,决定了该变量的取值范围和可以施加的运算种类。除此之外,变量还有变量一些属性,例如:一个变量在程序的哪个范围内是可以使用的变量的可用域;它什么时候生成以及什么时候被撤消变量的生存期;它存储在什么哪种类型的存储器中以
16、及用什么机制进行存储变量的存储区。这些都称为变量的存储属性。,4.2.1 变量的可用域和生存期,1.局部变量和全局变量变量的可用域是指一个变量的标识符在程序的哪个域内才是可以被识别的,也称为可见(或可用)的。大体上可以分为两种:全局可用全局变量与局部可用局部变量。局部变量是定义在一个程序块(用一对花括号括起的语句块)内的变量。程序块可能是一个函数体(主函数),也可能是一个循环体或是选择结构中的一个分支语句块,也可以是任何一个用花括号扩起的语句块。而全局变量是定义在函数之外的变量。一般说来,定义在什么范围的变量,其作用域就在那个范围,并且在从定义语句开始到这个域结束的范围(域)内被使用,在这个域
17、之外是不可见的。在C语言中,凡是声明在函数内部的变量都是局部变量。,2.动态变量与静态变量,任何一个运行中的程序,在内存中都被分成代码区和数据区两大部分,而数据区又被分为静态存储区、自动存储区和动态分配区等三部分。自动存储区是按栈组织的存储区。除特别声明的外,局部变量通常被存放在栈区。这些变量在进入所在的块时被创建,所在的块结束时被撤销,当所在的块结束后,各变量的值不再保留。并且,变量必须有程序员显式地进行初始化,否则它们的初始值是不确定的。前面例存储区是在程序编译时就分配的存储区,分配在静态存储区的变量在程序开始执行时被创建并自动初始化(数值变量被初始化为0),当程序结束时才被撤销。所以常称
18、静态变量的生存期是永久的。全局变量就是被分配在静态存储区的。下面的例子说明将例4.8中的程序改用全局变量实现后的情形。,4.2.2 C语言中变量的存储类型,根据程序中实际应用的需要,C语言将可用域和生存期整合成4种存储类型:局部自动类型,在函数内部用标识符auto或register声明。静态局部类型,在函数内部,使用static声明。静态全局类型,在函数外部,使用static声明,也称静态外部变量。全局类型,不需要标识符声明。在函数外部直接声明即可,通称外部变量。,auto存储类型和register存储类型 auto声明符的作用就是告诉编译器将变量分配在自动存储区。也就是说,使用auto声明的
19、变量是局部变量。其格式为:auto 数据类型变量名=初值表达式,;其中,方括号表示可省略,auto是自动变量的存储类别标识符。如果省略auto,系统隐含认为此变量为auto。函数的参数也是一种自动变量。register的作用是用来声明寄存器存储自动变量。这类变量具有局部变量的所有特点。当把一个变量指定为寄存器存储类别时,系统就将它存放在CPU中的一个寄存器中。通常把使用频率较高的变量(如循环次数较多的循环变量)定义为register类别。,2.静态局部类型,定义局部变量时,使用static修饰,可以在不改变局部量的可见域的前提下,使变量成为静态的,即当函数撤销后,变量的值还保留。或者说,这些变
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 谭浩强 模块化 程序设计

链接地址:https://www.31ppt.com/p-6503684.html