ImageVerifierCode 换一换
格式:DOCX , 页数:33 ,大小:49.72KB ,
资源ID:23812493      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/23812493.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C语言模块化程序设计1王新余.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

C语言模块化程序设计1王新余.docx

1、C语言模块化程序设计1王新余模块化程序设计一、 概述 程序模块化的发展过程:(1) 开始,软件是一大块机器代码。(2) 程序库,为不同程序提供公共服务。(3) 独立地址空间和进程间通信。(4) 程序系统分布在不同的互联的主机上。本节课,先讲述程序库,即函数级,C语言程序模块化的基础知识和注意点。再讲述RMX上多进程的特点。程序设计方法:自上而下,逐步细化,模块化设计,结构化编程原则:模块间耦合越小越好C语言:函数式语言在C程序设计中,通常: 将一个大程序分成几个子程序模块(自定义函数)将常用功能做成标准模块(标准函数)放在函数库中供其他程序调用如果把编程比做制造一台机器,函数就好比其零部件。可

2、将这些“零部件”单独设计、调试、测试好,用时拿出来装配,再总体调试。这些“零部件”可以是自己设计制造/别人设计制造/现在的标准产品而且,许多“零部件”我们可以只知道需向它提供什么(如控制信号),它能产生什么(如速度/动力),并不需要了解它是如何工作、如何设计制造的所谓“黑盒子”。 控制信号 速度/动力 (输入参数) (返回结果)【例】编写一个儿童算术能力测试软件显示软件封面检查密码产生题目接受回答评判计分显示结果如果要继续练习告别词main() char ans = y;clrscr();cover(); /*调用软件封面显示函数*/password(); /*调用密码检查函数*/while

3、(ans =y| ans =Y) question(); /*调用产生题目函数*/ answers(); /*调用接受回答函数*/ marks(); /*调用评分函数*/ results(); /*调用结果显示函数*/ printf(“是否继续练习?(Y/N)n”); ans=getch (); printf(“谢谢使用,再见!”);/*定义所用函数*/cover() /*软件封面显示函数*/password() /*密码检查函数*/question() /*产生题目函数*/answers() /*接受回答函数*/marks() /*评分函数*/results() /*结果显示函数*/函数使用

4、常识:1、C程序执行总是从main函数开始,调用其它函数后总是回到main函数,最后在 main函数中结束整个程序的运行。2、一个C程序由一个或多个源(程序)文件组成可分别编写、编译和调试。3、一个源文件由一个或多个函数组成,可为多个C程序公用。4、C语言是以源文件为单位而不以函数为单位进行编译的。5、所有函数都是平行的、互相独立的,即在一个函数内只能调用其他函数,不能再定义一个函数(嵌套定义)。6、一个函数可以调用其他函数或其本身,但任何函数均不可调用main函数。二、函数的定义函数定义“制造函数”1、无参函数 定义格式:数据类型 函数名() /*现代风格是:函数名(void)*/ 函数体(

5、说明部分+ 语句)【注意】数据类型为int时,可以省略。2、有参函数 定义格式:数据类型 函数名(形参表) /*现代风格是:函数名(带类型形参表)*/形参类型说明; 函数体(说明部分+ 语句)函数的返回值通过函数体中的return语句获得。形式: return (x); return (x+y); return (xy?x:y); 语句中圆括号亦可省略。【注意】如果函数值类型与return语句表达式值的类型不一致,以函数类型为准(数值型会自动进行类型转换)。如果明确表示不需返回值,可用void作函数的数据类型。3、空函数 类型说明符 函数名() 空函数,什么工作也不作,没有任何实际作用,只表明

6、“这里要调用一个函数”,而现在这个函数没有起作用,等以后扩充函数功能时补上。这样做可使程序结构清晰,可读写好,以后扩充新功能方便,对程序结构影响不大。【例一】max(float x, float y) /*用“值传递”分析法进行变量跟踪*/float z; z=xy?x:y; return z;main() float a=1.5,b=2.5; int c; c=max(a,b); printf(“Max is %dn”,c);结果:Max is 2 (编译通过,结果错误) 【讨论】如何改错?如果将输出语句中的%d改为%f,结果: Max is 8.000000 (亦错)如果将max(x,y)

7、改为float max(x,y),结果编译出错:Type mismatch in redeclaration of max 三、函数参数和函数的值1、形参和实参 在调用有参函数时,主调函数和被调函数之间有数据传递关系。在定义函数名后面括号中的变量名称为“形式参数”,在调用函数时,函数名后面括号中的表达式称为“实际参数”。关于形参与实参的说明:形参在未出现函数调用时,不占用内存。只有在函数被调用时,形参才被分配内存单元,调用结束后,形参所占的内存单元自动释放。实参可以是常量、变量或表达式,但要求有确定的值。在调用时,把实参的值赋给形参变量(如果形参是数组名,则传递的是数组首地址)。在被定义的函数

8、中,必须指定形参的类型。实参与形参类型应一致。C语言规定,实参变量对形参变量的数据传递是“值传递”,即单向传递,只有实参传给形参,而不能由形参传回给实参。在内存中,实参与形参是不同的内存单元。【例一】 void GetMemory(char *p,int length) p=(char *)malloc(length);void Test(void) char *ptr=NULL; GetMemory(ptr,10); Strcpy(ptr,”hello”);2、数组名作为函数参数用数组名作为函数参数,此时实参与形参都应用数组名(或用数组指针),应该在主调函数和被调函数分别定义数组。实参数组和

9、形参数组的类型应一致。实参数组和形参数组的大小可以不一致,C编译对形参数组大小不作检查,只是将实参数组的首地址传给形参数组。形参数组也可以不指定大小,在定义数组时在数组名后面跟一个空的方括弧。数组名作为函数参数时,不是“值传递”,不是单向传递,而是把实参数组的起始地址传给形参数组,两个数组共同占用一段内存单元。【例二】float average(float array,int n)main() float score5;average(score,5);在此例中,main函数调用average时,是把数组score地址压入堆栈,array指向数组score的内存单元。多维数组作为函数参数,形参

10、只能省略第一维的大小说明。在C语言中,数组在内存中按行列规则存放,先行后列,如果形参中不说明列数,系统无法决定多少行多少列。3、函数的返回值函数的返回值是通过函数中的return语句获得。函数定义指定函数值类型。C语言规定,凡不加类型说明的函数,一律自动按整形处理。如果函数值的类型和return语句表达式的值不一致,以函数类型为准。如果被调用函数中没有return语句,函数并不是不带回值,而是带回一部确定的值。C语言中,普通数据类型用寄存器eax带回返回值,指针类型用寄存器dx带回段地址,寄存器eax带回偏移地址。如果被调用函数中没有return语句,则返回值就是在函数运行结束时寄存器eax和

11、dx的值。为了明确函数“不带回值”,用“void”定义“无类型”。 四、函数的调用函数和变量一样,在其主调函数中也必须“先说明,后使用”。注意关系: 函数定义制造函数函数使用说明(准备使用)调用(使用函数)调用方式:赋值 如:c=max(x,y); 表达式中 c=1+max(x,y); printf(“Max=%dn”,max(x,y); 执行函数 max(x,y);1、调用外部函数(其他源文件中定义的函数)时 函数说明语句 extern 函数类型 函数名(); 【例】 文件file1.c中 main() Int x=80,y=90,c; extern max(); /*函数说明*/ c=ma

12、x(x,y)+20; /*调用max函数*/ printf(“Max is %dn”,c);文件files2.c中(与file1.c同目录)extern max(int a,int b) /*extern可省*/float c; c=ab?a:b; return c;2、调用同一源文件中的非标准函数时也必须在主调函数中对所调函数进行说明: 函数说明语句 数据类型 函数名(); (不说明会出现编译错误)但三种情况下可以省略说明: 函数值是整型(int)或字符型(char)时系统自动按整型说明; 所调函数的定义出现在主调函数之前时; 文件一开头,在所有函数之前,对所用函数作了说明3、通过函数指针调

13、用4、函数的嵌套调用 C语言的函数定义都是相互平行、独立的,也就是在定义函数时,一个函数内不能包含另一个函数。C运用可以嵌套定义数据类型和嵌套调用函数,五、函数的递归调用1、递归的概念 直接递归调用 调用函数的过程中又调用该函数本身间接递归调用 调用f1函数的过程中调用f2函数,而f2中又需要调用f1。以上均为无终止递归调用。为此,一般要用if语句来控制使递归过程到某一条件满足时结束。2、递归法 类似于数学证明中的反推法,从后一结果与前一结果的关系中寻找其规律性。归纳法可以分为:递推法 从初值出发,归纳出新值与旧值间直到最后值为止存在的关系 要求通过分析得到: 初值+递推公式 编程:通过循环控

14、制结构实现(循环的终值是最后值)递归法 从结果出发,归纳出后一结果与前一结果直到初值为止存在的关系 要求通过分析得到: 初值+递归函数编程:设计一个函数(递归函数),这个函数不断使用下一级值调用自身,直到结果已知处选择控制结构其一般形式是:在主函数中用终值n调用递归函数,而在递归函数中:递归函数名f (参数x) if (n=初值) 结果=; else 结果=含f(x-1)的表达式; 返回结果(return);【例一】(P118例7.8)用递归法求n!分析比较:递推法递归法0!=11!=0!12!=1!23!=2!3n!=(n1)!n分析得Sn=n!的求解 1 (n=1,0)Sn=Sn-1n (

15、n1)其中Sn-1先求出n!=(n1)! n(n1)!= (n2)! (n1)(n2)!= (n3)! (n2)(n3)!= (n4)! (n3)2!=1!2分析得f(n)=n!的求解 1 (n=1,0)f(n)=f(n1)n (n1)其中f(n1)未求出实际上,递归程序分两个阶段执行回推(调用):欲求n! 先求 (n-1)! (n-2)! 1! 若1!已知,回推结束。递推(回代):知道1!2!可求出3! n!程序如下:main()int n;float s; float fac(); clrscr(); printf(Input n=); scanf(%d,&n); s=fac(n); pr

16、intf(%d!=%.0f,n,s);float fac(int x)int f; if (x=0|x=1) f=1; else f=fac(x-1)*x; return f; 执行:Input n=5结果:5!=120【例二】(P116例7.7)有5个人,第5个人说他比第4个人大2岁,第4个人说他对第3个人大2岁,第3个人说他对第2个人大2岁,第2个人说他比第1个人大2岁,第1个人说他10岁。求第5个人多少岁。分析: 10 (n=1) age(n)= age(n-1)+2 (n1)程序如下:main()clrscr(); printf(%d,age(5);age(int n) int c;

17、if (n=1) c=10; else c=age(n-1)+2; return c;结果:18 【例三】在屏幕上显示杨辉三角形 1 分析:若起始行为第1行1 1 则: 第x行有x个值1 2 1 对第x行第y列,其值(不计左侧空格时)1 3 3 1 1 (y=1 或 y=x) 1 4 6 4 1 c(x,y)=1 5 10 10 5 1 c(x-1,y-1)+c(x-1,y) 程序如下:main()int i,j,n;clrscr();printf(Input n=);scanf(%d,&n);for (i=1;i=n;i+) for (j=0;j=n-i;j+) printf( ); /*为

18、了保持三角形态,此处输出两个空格*/ for (j=1;j1)程序如下:fib (int n) int f; if (n=1|n=2) f=1; else f=fib(n-1)+fib(n-2); return (f);main() int i,s=0; clrscr(); for (i=1;i=12;i+) s=s+fib(i); printf(n=12,s=%d,s);结果:376【例五】运行下列程序,当输入字符序列AB$CDE并回车时,程序的输出结果是什么?#include rev() char c; c=getchar(); if (c=$) printf(%c,c); else re

19、v(); printf(%c,c); main()rev();结果:$BA【例六】反向输出一个整数(非数值问题)非数值问题的分析无法象数值问题那样能得出一个初值和递归函数式,但思路是相同的。分析方法:简化问题:设要输出的正整数只有一位,则“反向输出”问题可简化为输出一位整数。对大于10的正整数,逻辑上可分为两部分:个位上的数字和个位以前的全部数字。将个位以前的全部数字看成一个整体,则为了反向输出这个大于10的正整数,可按以下步骤: a、输出个位上的数字; b、将个位除外的其他数字作为一个新的整数,重复a步骤的操作。其中b问题只是对原问题在规模上进行了缩小递归。所以,可将反向输出一个正整数的算法

20、归纳为: if (n为一位整数) 输出n; else 输出n的个位数字; 对剩余数字组成的新整数重复“反向输出”操作; 程序如下:#include void main()void printn(int x); int n; printf(Input n=); scanf(%d,&n); if (n=0&x=9) /*若x为一位整数*/ printf(%d,x); /*则输出整数x*/else /*否则*/printf(%d,x%10); /*输出x的个位数字*/ printn(x/10); /*将x中除个位数字外的全部数字形成新的x后,继续递归操作*/ 执行:Input n=12345结果:5

21、4321执行:Input n=12479结果:97421【讨论】Input n=123456 6167为什么:123456710=1 1110 0010 0100 00002 int类型的数实际只能存入16位,即1110 0010 0100 00002 第1位为符号位,其余各位取反后再加1,得原码1001 1101 1100 0000 (真值-761610)【例七】汉诺塔(Tower of Hanoi)问题。 P118例7.9 试题汇编【7.18】也是一个非数值问题。分析方法:简化问题:设盘子只有一个,则本问题可简化为ab。对于大于一个盘子的情况,逻辑上可分为两部分:第n个盘子和除n以外的n-

22、1个盘子。如果将除n以外的n-1个盘子看成一个整体,则要解决本问题,可按以下步骤: a、将a杆上n-1个盘子借助于b先移到c杆; ac (n-1,a,c,b) b、将a杆上第n个盘子从a移到b杆; ab c、将c杆上n-1个盘子借助a移到b杆。 cb (n-1,c,b,a)【注意】 由于递归调用的堆栈占用不能控制,在RMX的进程中,不提倡递归调用。六、变量的存储类型 模块化设计要求研究不同模块(函数、源文件)间变量的关系。变量两大属性: 数据类型 存储类别1、数据类型(复习)通过变量说明(定义)来规定其数据类型: 格式 数据类型关键字 变量名 如 char a; int b,c ; float

23、 x,y;为什么使用变量前要先对其数据类型进行“说明”好比看电影前先买票订座预留存储空间(如char型为1个字节,int型为2个字节)确定存储方式(如char型存放ASCII值,int型存放补码值) char型 (用一个字节存放该字符的ASCII值) int 型 (用两个字节存放该数值的补码) float型 (四个字节) 尾数(补码) 阶码一个变量的数据类型定义后,就规定了该变量只能存储相应类型的数据。如定义int x,则x只能存放整型数,如果x=3.14159,会被自动转为整型存放。2、存储类别 P130 规定了变量在计算机内部的存放位置决定变量的“寿命”(何时“生”,何时“灭”) 一个完整

24、的变量说明格式如下: 存储类别 数据类型 变量名 如 static int x , y ;存储类别:register型(寄存器型) 变量值存放在运算器的寄存器中存取速度快,一般只允许23个,且限于char型和int型,通常用于循环变量(在微机的Turbo C中实际上自动转为auto型)auto型(自动变量型)变量值存放在主存储器的动态存储区(堆栈方式)优点同一内存区可被不同变量反复使用以上两种均属于“动态存储”性质,即调用函数时才为这些变量分配单元,函数调用结束其值自动消失。static型(静态变量型)变量值存放在主存储器的静态存储区程序执行开始至结束,始终占用该存储空间extern型(外部变

25、量型)同上,其值可供其他源文件使用以上两种均属于“静态存储”性质,即从变量定义处开始,在整个程序执行期间其值都存在。未说明存储类别时,函数内定义的变量为auto型,函数外定义的变量为extern型。七、局部变量与全局变量1、局部变量函数内部或复合语句内定义的变量 auto(默认) 所在函数调用结束时,其值自动消失 局部变量 register static 所有函数调用结束,其值仍保留如不赋初值,auto变量和register变量为随机值,static变量取初值为0(数值型)或空格(字符型) 所有形参都是局部变量 局部变量只在本函数或本复合语句内才能使用,在此之外不能使用(视为不存在)main函

26、数也不例外。【例一】求程序运行结果main() int a=2,i; clrscr(); for (i=0;i3;i+) printf(%4d,f(a);f(int a) int b=0;static int c=3; b+;c+; return a+b+c; a i b c f(a) 2 0 01 4 71 01 5 82 01 6 9【结果】 7 8 9【例二】求程序运行结果main() int k=4,m=1,p; clrscr(); p=func(k,m); printf(%d,p); p=func(k,m); printf(%d,p);func(int a,int b) static

27、 int m=0,i=2; i+=m+1; m=i+a+b; return m; k m a b m i 4 1 4 1 08 23 4 1 4 1 817 312【结果】 8,172、全局变量在函数之外定义的变量 extern(默认) 允许本源文件中其他函数及其他源文件使用 全局变量 static 只限本源文件中使用有效作用范围:从定义变量位置开始直到本源文件结束如果需要将全局变量的作用范围扩展至整个源文件法1:全部在源文件开头处定义 法2:在引用函数内,用extern说明 法3:在源文件开头处,用extern说明【例三】求程序运行结果extern int x,y; /*可以省略int。如果没有此句,编译就会出错*/ clrscr();printf(x=%d,y=%dn,x,y);

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1