1、第第6章结构化与面向对象程序设计基础章结构化与面向对象程序设计基础6.1 6.1 结构化程序设计的基本概念结构化程序设计的基本概念 程序是一组能够完成特定任务的命令序列的集合。这些命令按照一定的逻辑顺序有机地结合在一起,并以文件形式存储在磁盘上,这种文件称为程序文件或命令文件,VFP中其扩展名为.PRG。执行程序时,计算机按程序的逻辑顺序自动执行程序文件中的命令。与在VFP的命令窗口逐条输入命令相比,采用程序方式的好处有:可利用编辑器方便地输入、编辑和保存程序。可采用多种方式、多次运行程序。可以实现程序代码的复用。6.1.1 6.1.1 程序程序【例6.1】编写程序文件exam6_1.prg实
2、现例4.31。*显示学生选课成绩表xkcjb.dbf中当前记录的学号、课程号和成绩字段的值 CLOSE ALL&关闭所有打开的文件 SELECT 2 USE dab&选择2号工作区打开 dab表 SELECT C USE kcb&选择3号工作区打开kcb表 USE xkcjb IN 5&在5号工作区打开xkcjb表?xkcjb.学号,b.姓名,xkcjb.课程号,xkcjb-成绩 CLOSE ALL&关闭所有打开的文件 RETURN 在命令窗口中执行MODIFY COMMAND exam6_1命令后,弹出代码编辑窗口,在该窗口中输入上述程序代码并保存。在命令窗口输入:DO exam6_1,程序
3、执行结果为:20050010 001 38.0 从该例子可以看出:程序代码保存在一个程序文件exam6_1.prg中,可以多次执行。1 1)算法的概念及特点)算法的概念及特点 要编制一个程序,必须首先构建解决问题的算法。所谓算法(Algorithm)就是对解决问题所采用的方法和步骤的描述。6.1.2 6.1.2 算法及算法的表示算法及算法的表示【例6.2】输入3个数,找出其中的最大值并输出。分析:假设这3个数分别用a、b、c表示,最大值用max表示。由于计算机一次只能比较2个数,首先可以将a和b进行比较,把其中大的数放入max中,再将max与c比较,又将大的数放入max中,最后将max输出。此
4、时max中的值就是a、b、c中的最大值。可以将求解这一问题的算法描述为:第1步:输入a、b、c。第2步:将a、b中大的一个数放入max中。第3步:将c与max中大的数放入max中。第4步:输出max。从该例子可以看出,算法是对一个问题的解决方法和步骤的描述,是一个有穷规则的集合。一个算法应该具有以下特点:确定性确定性。一个算法给出的每个计算步骤都必须是准确的、无二义性。在【例6.2】中每一个步骤的含义都是确定的。有穷性有穷性。一个算法必须在执行有穷多个计算步骤后终止。在【例6.2】中执行4个步骤后问题处理结束。有效性有效性。算法中的每一个步骤必须能够有效地执行,并能够得到确定的结果。输入输入。
5、一个算法可以有0个或1个以上的输入。在【例6.2】中需要输入a、b、c 3个数。输出输出。一个算法有1个或多个的输出,一个算法得到的结果就是算法的输出。在【例6.2】中输出的是max。任何一个问题能否让计算机处理,关键在于能否设计出合理的算法,有了合适的算法,再使用合适的计算机语言来编写程序。VFP就是一种语言工具。要用VFP编写出高质量的程序,一方面要构建合理的算法,另一方面要掌握VFP的语法规则,它是实现算法的基础。2 2)算法的描述)算法的描述 算法的描述方法有很多,如自然语言、伪代码、流程图等。为直观、准确地表示一个问题的处理方法和步骤,通常采用流程图的方法。流程图是用一些几何图形符号
6、、线条及文字说明来表征一个问题的处理过程。一般采用传统流程图和N-S图来描述算法。实现【例6.2】的算法所对应的传统流程图如图(a)所示、N-S图如图(b)所示。输入a,b,c开始输入a,b,c将a,b中大的数放在max中将c,max中大的数放在max中输出max开始输出max将c,max中大的数放在max中将a,b中大的数放在max中(a)(b)3 3)3 3种基本结构的表示种基本结构的表示 1966年,Bohra和Jacopini提出了程序的3种基本结构:顺序结构、选择(或分支)结构、循环结构,它们构成了实现一个算法的基本单元。顺序结构顺序结构:是一种最基本、最简单的程序结构。如下图所示,
7、先执行A,再执行B,A与B按照顺序执行。ABAB (a)流程图 (b)N-S图 选择(或分支)结构:根据条件是否成立而执行不同的程序模块。在下图中,当条件P为真时,执行A,否则执行B。即要么执行A,要么执行B。PT F A B条 件pABYN (a)流程图 (b)N-S图 循环结构:是指重复执行某些操作,重复执行的部分称为循环体。如图所示为当型循环结构,当条件P为真时,反复执行A,直到条件P为假时才终止循环。其中A是循环体,A被重复执行的次数称为循环次数。循环结构除当型循环外,还有直到型循环。条件PAN 条件P AY (a)流程图 (b)N-S图 结构化程序设计方法是一种自顶向下、逐步求精、模
8、块化的程序设计方法。结构化程序设计方法的思想,就是将给定的一个功能较多的复杂问题合理地划分为若干个较简单的子问题,还可以将这些子问题再分解为若干功能更简单的子任务(可将每个子任务看作一个模块),以便于“分而治之”。如下图表达了一个较复杂问题的模块分解过程。6.1.3 6.1.3 结构化程序设计方法概述结构化程序设计方法概述问题C1问题A问题B1问题B2问题Bn问题C2问题Cn 在模块划分时,应该尽可能地保证数据的独立性和模块功能的唯一性。也就是说,各模块间的耦合性要尽量弱,即一个模块最好像是一个黑盒子,模块间的数据交换要尽量少;模块的内聚性要尽量强,即每个模块只完成单一的功能。采用结构化程序设
9、计方法的好处是:可以使每个模块功能明确,模块间的关系简单、清晰(即可读性强),每个模块内部的修改尽可能不影响其他模块(即独立性好),同时每个模块的正确性容易验证(即可维护性好)。在VFP中,程序模块化是通过编写子程序、过程、函数来实现的。6.2 6.2 程序文件的建立、编辑、修改与执行程序文件的建立、编辑、修改与执行 在VFP中,建立和编辑程序文件可以采用多种文本编辑工具实现,这些文本编辑工具可以是VFP系统提供的内部编辑器,也可以是其他常用文本编辑软件。一般在代码编辑窗口中编辑程序代码。在VFP系统环境下,建立和编辑程序文件有多种方法,在此主要介绍以下3种方式。6.2.1 6.2.1 程序文
10、件的建立、编辑与修改程序文件的建立、编辑与修改 1 1)在项目管理器中创建程序文件)在项目管理器中创建程序文件 如果要让程序包含在一个项目文件中,可在项目管理器中建立程序文件。在上图所示的【项目管理器】中,选择【代码】选项卡中的“程序”项,单击【新建】按钮,进入代码编辑窗口,输入程序内容,如右图所示。2)2)用菜单方式新建程序文件用菜单方式新建程序文件 在【文件】菜单中选择【新建】菜单选项,在出现的【新建】对话框中选择“程序”文件类型,再单击【新建文件】按钮即可进入代码编辑窗口编辑程序代码。如果要修改已有的程序文件,则在【文件】菜单中选择【打开】菜单项,这时弹出一个包含文件列表的对话框。在【文
11、件类型】列表框中选择“程序”,然后在文件列表中选定要修改的程序文件,单击【确定】按钮即可。3)3)用命令方式新建程序文件用命令方式新建程序文件 格式:格式:MODIFY COMMAND MODIFY COMMAND|?|?例如,在命令窗口中输入“MODIFY COMMAND search”命令(如图6.8所示),即可打开代码编辑窗口。如果程序文件不存在,系统就自动建立一个指定名字的新程序文件;如果文件已存在,则将打开该程序文件。用上述3种方法之一创建程序文件后,必须在代码编辑完毕时,保存文件。其方法是选择【文件】菜单下的【保存】或【另存为】命令进行保存;也可以利用“Ctrl+W”组合键进行保存
12、,程序将保存在当前盘的当前路径下(注意:“Ctrl+Q”组合键放弃存盘)。程序文件创建之后便可执行,执行程序文件的方法有:若程序文件包含在一个项目中,则在【项目管理器】中,打开【代码】选项卡,展开“程序”项,选定程序文件,单击【运行】按钮。在【程序】菜单中选择【运行】菜单项,在弹出的对话框中选定要运行的程序文件,单击“运行”按钮。在【命令】窗口中,输入命令:DO WITH。6.2.2 6.2.2 执行程序文件执行程序文件6.3 6.3 程序中常用命令程序中常用命令 输入/输出处理是计算机和用户打交道的接口,是程序设计过程中不可缺少的组成部分。处理过程中的原始数据或用户的要求都需要通过输入语句来
13、输入,而处理结果又通过各种形式的输出语句来输出。在VFP中用于输入、输出的命令很多,在此只介绍几个常用的命令。6.3.1 6.3.1 基本的输入基本的输入/输出命令输出命令1 1)INPUTINPUT命令命令 格式:格式:INPUT INPUT TO TO 功能:在屏幕上显示,并等待用户通过键盘输入表达式,再把表达式的值赋给指定的。例如:s=75 input to a?a=,a 执行上述命令,若输入的内容为s+20,则输出结果为:a=95这表明变量a接收的是表达式的值。2 2)ACCEPTACCEPT命令命令格式:格式:ACCEPT ACCEPT TO TO 功能:该命令和INPUT类似,不同
14、的是它会把输入内容作为字符串常量赋值给指定的。例如,把上例中的input改成accept:s=75accept to b?b=,b执行上述命令,若输入的内容为s+20,则输出结果为:b=s+20这表明变量b接收的是字符串“s+20”。说明:这两个命令中的可以缺省。当提示信息缺省的时候,则直接等待用户输入。3 3)WAITWAIT命令命令格式:格式:WAIT WAIT TO TO WINDOW WINDOW AT AT,NOWAITNOWAITCLEAR|NOCLEARCLEAR|NOCLEARTIMEOUTTIMEOUT 功能:该命令的作用是暂停程序的执行,直到用户按任意键或单击鼠标或等待输入
15、一个字符(可存入指定的内存变量)或在指定时间内继续程序的执行。说明:在该命令中,若选用说明:在该命令中,若选用WINDOWWINDOW,则会出现一个用于,则会出现一个用于显示提示信息的显示提示信息的WAITWAIT提示窗口,通常位于主窗口的右上角。提示窗口,通常位于主窗口的右上角。若需指定提示窗口的位置时,可使用若需指定提示窗口的位置时,可使用ATAT实现;若同时选用实现;若同时选用NOWAITNOWAIT和和WINDOWWINDOW,则程序不等待用户按键就继续执行;若选,则程序不等待用户按键就继续执行;若选用用NOCLEARNOCLEAR,则不关闭提示窗口,直到执行下一条,则不关闭提示窗口,
16、直到执行下一条WAIT WAIT WINDOWWINDOW或或WAIT CLEARWAIT CLEAR为止;若选用为止;若选用TIMEOUTTIMEOUT,则在超过设定,则在超过设定等待时间后程序自动继续执行。等待时间后程序自动继续执行。例如:若在主窗口的10行、20列处显示提示信息“输入无效,请等待重新输入”,10秒钟后自动关闭提示窗口,程序继续执行。可使用命令:WAIT“输入无效,请等待重新输入”WINDOW TIMEOUT 10 AT 10,20。4 4)基本输出命令)基本输出命令?|?|?格式:格式:?|?|?1,2 功能:计算给定的一个或多个表达式的值,并将结果显示在屏幕上。说明:说
17、明:“?”?”表示在当前光标的下一行输出,而表示在当前光标的下一行输出,而“?”?”表示表示在当前光标位置处输出。在当前光标位置处输出。在程序中,有一些专门用于程序开始和结束、对程序进行注释以及环境设置的命令,常用的有:1 1)注释命令)注释命令 为了提高程序的可读性,编写程序时可在程序中适当加上一些注释。注释命令在执行时不做任何操作,也不影响程序的功能。格式格式1 1:NOTE NOTE 格式格式2 2:&格式格式3 3:*功能:用于在程序中加入说明,以增加程序的可读性。说明:说明:NOTE NOTE 和和*命令用于行首注释,而命令用于行首注释,而&命令通常用于行尾注释。命令通常用于行尾注释
18、。6.3.2 6.3.2 程序文件中的辅助命令程序文件中的辅助命令 2 2)程序结束命令)程序结束命令 VFP的应用程序可以根据需要终止执行并返回命令窗口,返回操作系统或返回到调用它的上一级程序或主程序。格式格式1 1:CANCELCANCEL 功能:结束当前 Visual FoxPro 程序的执行。格式格式2 2:RETURN RETURN TO MASTERTO MASTER 功能:结束当前程序的执行,返回到调用它的上一级程序。带TO MASTER选项表示直接返回到主程序。格式格式3 3:QUITQUIT 功能:关闭所有文件,退出VFP系统,返回到操作系统。3 3)清屏命令)清屏命令命令格
19、式:命令格式:CLEARCLEAR功能:清除屏幕内容。4 4)SET TALK ON/OFFSET TALK ON/OFF功能:控制非输出性的结果是否在屏幕上显示出来。系统默认值为ON。5 5)SET SAFETY ON/OFFSET SAFETY ON/OFF功能:确定在改写已有文件前,是否显示提示对话框。系统默认值为ON。6.4 VFP6.4 VFP程序的三种基本结构程序的三种基本结构顺序结构始终按照程序中语句的先后顺序逐条执行。6.4.1 6.4.1 顺序结构顺序结构【例6.3】鸡兔同笼,已知鸡兔的总头数为h,总脚数为f,求鸡兔各有多少只?鸡兔同笼问题的算法如图所示。输入h,fx=(4*
20、h-f)/2y=(f-2*h)/2输出s 其程序文件exam6_3.prg的代码为:input“请输入鸡兔总头数:”to h input“请输入鸡兔总脚数:”to f x=(4*h-f)/2&x为鸡的只数y=(f-2*h)/2&y为兔的只数?”共有鸡:”,x?”共有兔:”,ycancel 应用程序在进行数据处理时需要根据不同的条件选择执行不同的操作,使程序的流程根据不同条件来决定程序的走向,这种程序结构称为选择结构。在VFP中是用IFELSEENDIF和DO CASEENDCASE来实现的。6.4.2 6.4.2 选择结构选择结构1 1)IFIF语句语句格式:格式:IF IF 1ELSEELS
21、E 2ENDIFENDIF功能:执行该语句时,若条件表达式的值为.T.,则执行,否则执行,然后再执行ENDIF之后的语句,如图所示。条件表达式TF语句序列1语句序列2执行ENDIF之后的语句说明:说明:在在IFIF语句中,语句中,ELSEELSE选项可缺省,此时在如上图中去选项可缺省,此时在如上图中去掉掉 2即可。当即可。当ELSEELSE缺省时,如果条件表达式缺省时,如果条件表达式为为.F.F.,则执行,则执行ENDIFENDIF后面的语句。后面的语句。IFIF和和ENDIFENDIF必须成对出现,否则程序将无法执行。必须成对出现,否则程序将无法执行。该语句可以嵌套使用,但是在嵌套使用时不能
22、出现该语句可以嵌套使用,但是在嵌套使用时不能出现交叉现象。交叉现象。【例6.4】输入球的半径,计算球的体积。其程序文件exam6_4.prg的代码为:clearinput 请输入球的半径:to rif r0 v=(4/3)*3.1416*r3?球的体积是:,round(v,2)&保留2位小数else messagebox(输入半径不能为负数!)endifcancel 【例6.5】判断某一年是否是闰年。分析:假如年份用year表示,判断year是否是闰年的方法是:year能够被400整除或year能够被4整除并且不能够被100整除 (用vfp表示的逻辑表达式为year/4=int(year/4)
23、and year/100int(year/100)or year/400=int(year/400))。其程序文件exam6_5.prg的代码为:clearinput 请输入年份:to yearif year/4=int(year/4)and year/100int(year/100)or year/400=int(year/400)?str(year,4)+年是闰年else?str(year,4)+年不是闰年endifreturn提示:判断一个整数提示:判断一个整数M M能否被另一个整数能否被另一个整数N N整除,一般采用整除,一般采用3 3种方法,种方法,即:判断即:判断MOD(M,N)M
24、OD(M,N)是否等于是否等于0 0或或INT(M/N)INT(M/N)是否等于是否等于M/NM/N或或M%NM%N是否等是否等于于0 0,若等于,则表明,若等于,则表明M M能被能被N N整除。整除。2 2)多路分支语句)多路分支语句格式:格式:DO CASEDO CASE CASE CASE 1 1 CASE CASE 2 2 CASE CASE N N OTHERWISE OTHERWISE Q ENDCASE ENDCASE 功能:从第一个CASE的条件开始判断,若(I=1、2、3n)的值为.T.,则执行(I=1、2、3n),然后执行ENDCASE之后的语句。所以在一个DO CASE结
25、构中,最多只能执行一个CASE语句后面的语句序列。如果所有CASE语句后的条件表达式的值均为.F.,则执行OTHERWISE之后的。OTHERWISE子句可以缺省,此时如果所有条件表达式的值均.F.,就退出该结构执行EDNCASE语句后面的语句。说明:说明:DO CASEDO CASE、CASE CASE I、OTHERWISEOTHERWISE和和ENDCASEENDCASE必须必须各占一行。各占一行。DO CASEDO CASE和和ENDCASEENDCASE必须成对出现。必须成对出现。语句序列中可以嵌套各种控制结构的命令语句。语句序列中可以嵌套各种控制结构的命令语句。【例6.6】计算分段
26、函数的值)0(57)0(4)0(12)(xxxxxxxf分析:这是一个多分支结构的问题,实现方法很多,下面给出其中的2种。方法1:用CASE语句实现input 输入x的值:to xdo casecase x0 f=2*x-1case x=0 f=4*xotherwisef=7*x-5endcase?f(,x,)=,freturn方法2:用IF的嵌套结构实现input 输入x的值:to xif x=0 if x=85?xh+的成绩为:优秀case 成绩=70 and 成绩=60 and 成绩70?xh+的成绩为:及格otherwise?xh+的成绩为:不及格endcaseendifuseretu
27、rn 循环是按照给定的条件去重复执行一段具有特定功能的程序。循环结构是一种重要的程序结构。在VFP中提供了DO WHILEENDDO、FORENDFOR、SCANENDSCAN三种循环处理命令。1 1)DO WHILEDO WHILE循环循环 命令格式:命令格式:DO WHILE DO WHILE ENDDO ENDDO 功能:当执行DO WHILE语句时,如果表达式的值为.T.,则执行,否则结束该循环,执行ENDDO之后的语句。语句序列条件ENDDO之后的语句假真6.4.3 6.4.3 循环结构循环结构【例6.9】计算s=1+2+3+.+100 求解该问题的算法所对应的传统流程图和N-S图如
28、图所示。开始I=1 s=0I=100s=s+II=I+1Y输出s结束NI=1,s=0I=100 s=s+I I=I+1 输出s(a)传流程图 (b)N-S图程序文件exam6_9.prg的代码为:s=0i=1do while i=100s=s+II=I+1enddo?”s=“,scancel 【例6.10】逐条显示学生档案表dab.dbf中计算机1班学生的信息。其程序文件exam6_10.prg的代码为:clearuse dabdo while.not.eof()&当记录指针指到数据表尾则结束该循环if 专业班级=“计算机1班”&指定学生的班级dispendifskip&记录指针移向下一记录e
29、nddousecancel2 2)FORFORENDFORENDFOR计数循环计数循环格式:格式:FOR FOR TO TO STEP STEP ENDFOR|NEXTENDFOR|NEXT功能:当FOR语句中循环变量的值在“初值”和“终值”之间时,执行FOR与ENDFOR之间的循环体,否则退出循环,如下图所示。说明:说明:当当STEPSTEP(步长)缺省时,其默认值为(步长)缺省时,其默认值为1 1。当当STEP STEP 不为不为1 1时,则循环变量的值就按照步长的值自动增加或时,则循环变量的值就按照步长的值自动增加或减少(步长大于减少(步长大于0 0,则增加,此时,循环条件为循环变量,则
30、增加,此时,循环条件为循环变量=终值)。终值)。循环初值赋给循环变量循环变量是否超过终值?执行循环体中语句序列循环体变量按步长变化执行ENDFOR之后的语句【例6.11】求n的阶乘。求解该问题的算法如图所示。其程序文件exam6_11.prg的代码为:input 请输入n:to nfac=1for i=1 to nfac=fac*iendfor?n,!=,facreturn输入ni=1,fac=1 i=100 fac=fac*i i=i+1 输出s 求n!的N-S图3 3)SCAN.ENDSCANSCAN.ENDSCAN循环循环格式:格式:SCANSCAN范围范围 FOR|WHILE FOR|
31、WHILE ENDSCANENDSCAN功能:在当前数据表中扫描指定范围内满足条件的所有记录,找到一条满足条件的记录就执行一遍,直到对所有满足条件的记录执行完为止。在命令中当范围缺省时为ALL。【例6.12】利用SCAN语句在学生档案表dab.dbf中查找7月份出生的学生的学号、姓名、出生日期以及专业班级情况,并统计人数。其程序文件exam6_12.prgset talk offclearuse dab?学号,姓名,出生日期,专业班级scan for month(出生日期)=7?学号,姓名,出生日期,专业班级endscancount to rs for month(出生日期)=7?合计:,rs
32、,人use set talk oncancel 程序执行结果为:学号 姓名 出生日期 专业班级20050010 蜂雪燕 07/02/87 计算机1班20050030 陈宗贵 07/02/87 英语3班合计:2人 4 4)循环结构中的)循环结构中的2 2个特殊语句个特殊语句 在循环结构中可使用2个特殊语句LOOP和EXIT来改变程序的正常循环。如果在DO WHILE循环、FOR循环、SCAN循环语句中含有LOOP语句,当遇到了LOOP语句时,则忽略LOOP后面的语句序列,结束本次循环,去再次计算的值;当遇到EXIT语句时,则无条件退出本层循环,执行ENDDO、ENDFOR、ENDSCAN之后的语
33、句。如下图所示为DO WHILE循环中含有LOOP及EXIT语句的情况。语句序列1LOOPEXIT语句序列2条件 ENDDO之后的语句假真【例6.13】利用exit和loop语句编写程序计算100以内的奇数和。其程序文件exam6_13.prg的代码为:s=0i=0do while.t.i=i+1if i100exit&退出循环endifif i%2=0&如果i为偶数loop&结束本次循环elses=s+iendifenddo?100以内的奇数和为:,scancel说明:实现该问题的方法说明:实现该问题的方法很多,该程序仅仅是为了很多,该程序仅仅是为了说明说明EXIT和和LOOP语句的语句的使
34、用,而不是最佳实现方使用,而不是最佳实现方法。法。5 5)多重循环结构)多重循环结构 若在一个循环结构的循环体中又包含了循环,则该循环结构称为循环嵌套。在一个循环结构中按照嵌套层次的多少,可分为双重循环、三重循环等。嵌套层次在2层以上一般称为多重循环结构。按其所处的位置分别称为外循环与内循环,其中内循环结构的循环体称为内循环体,外循环结构的循环体称为外循环体,如下图所示。每一层循环结构可以采用DO WHLIE、FOR等语句,其执行过程,按照各自语句的含义执行。外循环体外循环结构内循环结构内循环体 (a)双重循环 (b)三重循环EXITEXIT【例6.14】利用双重循环编程求sum=1+(1+2
35、)+(1+2+3)+(1+2+3+10)之值。其程序文件exam6_14.prg的代码为:clearsum=0for i=1 to 10t=0for j=1 to it=t+jendforsum=sum+tendfor?1+(1+2)+(1+2+3)+(1+2+3+10)=,sumreturn【例6.15】利用xkcjb.dbf和dab.dbf,通过反复输入学生的学号(输入回车键退出),查询学生的姓名、专业班级、课程号以及成绩情况。方法1:建立表间关联,并进行查找处理。set safety off&当产生已存在的文件或索引标记时,直接覆盖,不给出确认对话框sele 1use dabindex
36、on 学号 tag xhsele 2use xkcjbset relation to 学号 into dabdo while.t.&外循环accept 请输入学生的学号:to xhif len(alltrim(xh)=0exitendif?“姓名 专业班级 课程号 成绩scan for 学号=xh&内循环?dab.姓名,dab.专业班级,课程号,成绩endscanenddoclose allset safety onreturn方法2:利用SELECT-SQL语言实现。clear alldo while.t.accept 请输入学生的学号:to xhif len(alltrim(xh)=0ex
37、itendif select 姓名,专业班级,课程号,成绩;from xkcjb,dab where dab.学号=xh and xkcjb.学号=dab.学号 to screenenddo 在编写应用程序时,往往会遇到一些比较复杂的问题。对这些问题的处理可以采用“自顶向下,逐步细化、模块化”的方法,把整体的功能需求逐步划分,通过简单而具有独立功能的子模块来实现。这样既可以保证模块的重复使用,也可以方便调试、节省存储空间。模块就是具有独立功能的程序段。在VFP中可以通过子程序、过程和自定义函数来实现模块的功能。6.5 6.5 模块化程序设计模块化程序设计 对于2个具有调用关系的程序文件,常把被
38、调用的程序文件称为子程序,而调用它的程序称为主程序。子程序是指具有相对独立性和通用性的程序段,它是一个独立的程序文件(.prg),存放在磁盘上。(1 1)子程序的建立、调用与返回)子程序的建立、调用与返回 子程序的建立方法与程序文件的方法相同。执行指定子程序可用DO命令来实现。格式:格式:DO DO 6.5.1 6.5.1 子程序子程序 主程序与子程序的概念是相对的,子程序还可以调用它自己的子程序,即子程序可以嵌套调用。子程序的嵌套如下图所示。主程序DO ADO A子程序ADO BDO BRETURN子程序BRETURN主程序DO ADO A子程序ADO BDO BRETURN子程序BRETU
39、RN TO MASTER VFP的返回命令包含了因嵌套而引出的多种返回方式。格式:格式:RETURNRETURNTO MASTERTO MASTER|TO TO 说明:命令格式中的TO MASTER选项表示返回到最外层主程序;选项TO 强制返回到指定的程序文件。【例6.16】输入圆的半径r,求圆的面积。程序代码如下:*主程序*exam6_16.prginput 请输入圆的半径:to rdo sub1&调用子程序return*子程序,独立于主程序的程序文件*sub1.prgarea=pi()*r2&计算圆的面积,pi()返回值?圆的面积为:,areareturn&返回主程序 (2)带参数的子程序
40、)带参数的子程序 由于模块的功能之间具有相关性,有时候需要从主程序向子程序传递数据,有时候子程序又要传递数据给主程序,这些数据称为参数。具有参数传递的子程序称为带参数子程序。带参数子程序的开头必须是PARAMETERS参数语句,相应地,主程序的调用方式也有所不同。在带参数子程序中参数语句的格式为:PARAMETERS 说明:形式参数表又简称形参,必须是变量,用来接收说明:形式参数表又简称形参,必须是变量,用来接收主程序传递过来的参数,多个形参用逗号隔开。主程序传递过来的参数,多个形参用逗号隔开。主程序的调用命令是:主程序的调用命令是:DO DO WITH WITH 说明:说明:实际参数又简称实
41、参,是用于向子程序传递数据的参数,实际参数又简称实参,是用于向子程序传递数据的参数,可以是常量、已赋值的变量、表达式或函数。可以是常量、已赋值的变量、表达式或函数。实参的个数、类型应与带参数子程序实参的个数、类型应与带参数子程序PARAMETERSPARAMETERS语句中语句中的形参个数、类型一致,但名字可以不同。的形参个数、类型一致,但名字可以不同。调用时,主程序将实参一一对应地传送给子程序PARAMETERS语句中的形参(主程序子程序)。子程序返回时,若实参是变量,则接受对应的形参的值(子程序主程序)。【例6.17】用带参数子程序编写例6.16。程序代码如下:*主程序*exam6_17.
42、prgarea=0input 请输入圆的半径:to rdo sub2 with r,area&调用子程序时传递参数?圆的面积为:,areareturn*子程序*sub2.prgparameters a,bb=pi()*a2return调用时,将主程序的实参变量r、area的值一一对应地传递给子程序中的形参变量a、b;返回时,又会将a和b的值分别传给r和area。这是一个双向参数传递(主程序r 子程序a,主程序area 子程序b)。子程序有一个弱点,每调用一次子程序,系统就要打开一个程序文件,当调用很多子程序或一个子程序被反复调用时,频繁打开文件的操作会增加磁盘开销,降低系统运行速度,同时也给系
43、统开发带来了不便,为此,引入了过程。过程是可命名的、具有独立功能的程序段,与子程序不同的是,过程可以不是一个独立的程序文件。它既可以与主程序同在一个文件中,也可以和其他过程一起单独组成一个文件,这就克服了调用子程序时反复打开文件的缺陷。6.5.2 6.5.2 过程过程格式:格式:PROCEDURE PROCEDURE RETURN|ENDPROCRETURN|ENDPROC说明:说明:PROCEDURE PROCEDURE 是过程的开始,是过程的开始,RETURNRETURN是过程的是过程的结束。过程可以与调用它的主程序放在同一个文件中,一般结束。过程可以与调用它的主程序放在同一个文件中,一般
44、放在程序文件的末尾。放在程序文件的末尾。过程的调用与子程序的调用完全相同,即用DO 语句直接调用。【例6.18】用过程编写例6.16计算圆面积。程序代码如下:*exam6_ 18.prgarea=0input 请输入圆的半径:to rdo sub3 with r,area&调用过程?圆的面积为:,areareturn*将过程直接放在主程序的后面procedure sub3&sub3是过程名parameters a,bb=pi()*a2return&返回主程序 VFP为用户提供了大量的系统函数(第3章已经学习了很多的系统函数),同时也允许用户创建自己的函数以满足不同领域的特殊需要。用户自己创建的
45、函数称为自定义函数。与系统函数类似,自定义函数也是通过函数名返回函数值。6.5.3 6.5.3 自定义函数自定义函数定义格式:定义格式:FUCATION FUCATION PARAMETERS PARAMETERS RETURN RETURN 调用格式为:调用格式为:()说明:说明:若使用若使用FUNCTIONFUNCTION语句来指出函数名,表示该函数包含在主程语句来指出函数名,表示该函数包含在主程序中。若缺省该语句,表示此函数是一个独立的文件,函数名序中。若缺省该语句,表示此函数是一个独立的文件,函数名即程序文件名,其扩展名是即程序文件名,其扩展名是.prgprg,并可使用命令,并可使用命
46、令MODIFY MODIFY COMMAND COMMAND 来建立或编辑自定义函数。来建立或编辑自定义函数。自定义函数的函数名不能和自定义函数的函数名不能和VFPVFP的系统函数同名,也不的系统函数同名,也不能和内存变量同名。能和内存变量同名。PARAMETERS PARAMETERS 定义了函数的参数,与带定义了函数的参数,与带参子程序的参数用法相同。参子程序的参数用法相同。组成为函数体,用于各种处理;简单的函组成为函数体,用于各种处理;简单的函数其函数体可以为空。数其函数体可以为空。RETURN RETURN 将表达式作为函数值返回给主程序。将表达式作为函数值返回给主程序。【例6.19】
47、用自定义函数编写例6.16计算圆面积。方法1:自定义函数作为一个独立的文件。自定义求圆面积的函数area.prg如下:parameters areturn pi()*a2&函数体为空,直接将表达式的值返回若要计算半径为10的圆面积,则在命令窗口中直接输入?area(10)&显示结果:314.1593 在实际应用中,常常把多个过程或自定义函数集中在一个程序文件中,这个文件称为过程文件。在过程文件中,每个过程或自定义函数仍然是独立的,只是为了避免频繁读取磁盘,在主程序调用时,一次全部调入内存,从而提高了系统的运行效率。6.5.4 6.5.4 过程文件过程文件(1 1)过程文件的格式)过程文件的格式
48、PROCEDURE PROCEDURE 1 1RETURNRETURNPROCEDURE PROCEDURE 2 2RETURNRETURNFUNCTION FUNCTION 3 3RETURNRETURNFUNCTION FUNCTION 4 4RETURNRETURN(2 2)过程文件的建立)过程文件的建立 过程文件的建立与一般程序文件的建立方法一样。(3 3)打开过程文件)打开过程文件格式:格式:SET PROCEDURE TO SET PROCEDURE TO 说明:该命令在主程序中使用。在同一时刻只能打开一个过程说明:该命令在主程序中使用。在同一时刻只能打开一个过程文件,打开新的过程
49、文件时原来的过程文件会自动关闭。文件,打开新的过程文件时原来的过程文件会自动关闭。(4 4)关闭过程文件)关闭过程文件格式:格式:SET PROCEDURE TO SET PROCEDURE TO 或或 CLOSE PROCEDURECLOSE PROCEDURE说明:若要修改过程文件,必须先关闭它。说明:若要修改过程文件,必须先关闭它。VFP的内存变量除类型、取值外,还有一个非常重要的属性作用域。变量的作用域是指变量在什么范围内是可见的、有效的和可操作的。在程序设计中,特别是模块化程序中,经常会遇到许多内存变量,这些内存变量有的在整个程序运行过程中有效,有的只在某些模块中有效,这就是内存变量
50、的作用域。VFPVFP中的内存变量按其作用范围可分为公中的内存变量按其作用范围可分为公共变量、私有变量和本地变量共变量、私有变量和本地变量。6.5.5 6.5.5 变量的作用域变量的作用域 1 1)公共变量)公共变量 公共变量是指在整个程序执行过程中任何模块内都有效的内存变量。格式:格式:PUBLIC PUBLIC 功能:将中的变量全部设置成公共变量,并把这些变量的初值赋为.F.。说明:说明:在在 中的变量可以是简单变量,也可以是数组。中的变量可以是简单变量,也可以是数组。在在VFPVFP命令窗口中定义的变量默认为全局变量,但这样定义的变命令窗口中定义的变量默认为全局变量,但这样定义的变量不能