由于一个应用程序通常是由多个相关的程序模块组成的,各模块之间按其互相调用的关系又有主模块和子模块之分。采用这种方式,能够使整个程序的结构清晰,易于分别编写与调试,且便于维护与调用。
模块化的设计要遵循“自顶向下”、“按功能划分模块”、“模块的大小要适中”、“各模块之间的接口要简单”的原则。模块可以是子程序、过程、自定义函数等。
子程序指的是一个能够独立实现某个功能的程序。其特点是:它总被其他程序调用而一般不能单独执行。通常把调用它的程序称为主程序,被主程序调用的程序称为子程序。
建立或者修改子程序的方法与建立其他一般程序的方法一样,其格式为:
Modify Command <子程序文件名>
说明:
(1)子程序的建立、修改和保存与其他Visual FoxPro程序一样可以使用Modify Command <程序文件名>命令或者通过菜单的方式来建立和修改,其扩展名也是*prg。
(2)子程序一定要用Return[To Master|To<程序名>]命令结束。Return后如果不加任何选项,则该语句结束子程序文件的运行,返回到调用子程序的主程序的下一个语句,继续执行;若选择To Master命令则返回到一级主程序;若选择To <程序名>命令则返回到“程序名”指定的程序。
如果要调用子程序,其命令格式如下:
Do <子程序名> [With <实际参数表>]
说明:
(1)[With <实际参数表>]是参数传递的选择。在实际应用中,有时需要在调用主程序与被调用的子程序之间进行一些参数的传递,从而来提高程序设计的灵活性。无论是在子程序、过程,还是在自定义函数中,参数传递都是一个非常重要的应用。
(2)如果存在参数传递,那么接受实际参数的Parameters <形式参数表>命令,必须是被调用子程序的第一条可执行语句。<实际参数表>与<形式参数表>应一一对应,当<实际参数表>的数量少于<形式参数表>的数量时,多余的形式参数取逻辑假的值。
(3)当With <实际参数表>是常量、内存变量表达式列表和加圆括号的简单内存变量时,这种传递接受参数的方式是值传送方式。
(4)当With <实际参数表达式列表>是简单内存变量列表时,这种传递接受参数的方式是地址传送方式。地址传送是一种双向传送,在调用With <实际参数表>中的变量值时,会按顺序传递给Parameters <形式参数表>对应的变量,而返回时,With <实际参数表>中的变量值会随Parameters <形式参数表>对应变量值的变化而变化。
【例5-23】对任意给定的正整数X、Y、Z,用子程序编写计算S=X!+ Y!+ Z!的程序,使用普通变量的方式进行传递。
*主程序5-23.PRG
clear
Store 0 To S,P
For J=1 To 3
Input "请依次输X、Y、Z的值:" To X1
Do 5-23-1 With X1
S=S+P
Endfor
? "S=",S
Return
*子程序5-23-1.Prg
Parameters X2
P=1
For I=1 To X2
P=P*I
Endfor
Return
运行结果如下:
过程也是一个实现某个功能的程序段,是子程序的另一种形式。但是,过程是主程序的一个组成部分,常把它写在主程序的最后。
格式:
Procedure<过程名> &&过程说明语句是非执行语句
[Parameters <形式参数表>]
<过程体命令序列> &&过程体
Return [To Master/To <程序名>] &&过程的结束语句
说明:
(1)过程是一个程序段,一般以程序文件的组成部分存在。
(2)过程的调用方法等同程序文件的执行方法:DO <过程名>[WITH <参数表>]。
(3)用户可以根据需要将自定义函数改成过程,或把过程改成自定义函数。
如果要调用过程,其格式如下:
DO <过程名> [With <实际参数表>]
[With <实际参数表>]的参数传递意义与子程序相同。如果存在参数传递,那么接受实际参数的Parameters <形式参数表>命令,必须写在Procedure<过程名>语句的后面。
【例5-24】使用过程的方式编程求圆的面积。
SET TALK OFF
CLEAR
S=0
DO AREA WITH 3
?"圆的面积是:",S
SET TALK ON
PROCEDURE AREA
PARAMETERS R
S=3.1416*R*R
RETURN
运行结果如下:
自定义函数和子程序、过程相似,也是实现某个功能的一个程序块。自定义函数既可以写在主程序的后面,也可以是一个独立的程序。所不同的是,自定义函数必须通过Return <表达式>返回一个函数值。
自定义函数既可以写在主程序的后面,也可以是一个独立的程序,用Modify Command <程序文件名>命令建立,其扩展名也是*.prg。自定义函数不管是写在主程序的后面,还是作为一个独立的程序来建立,其编写格式均为:
Function<函数名> &&自定义函数说明语句
[Parameters<形式参数表>]
<函数体>
Return<表达式> &&将<表达式>的值作为函数值返回
说明:在调用函数时,函数名(参数)中的“参数”应与Parameters<形式参数表>中“形式参数表”一致,自定义函数必须用Return<表达式>将<表达式>的值作为函数值返回。
自定义函数的调用与系统标准函数的调用方法相同,其形式为:
<函数名>[<参数表>]。
函数的参数传送方式默认为值传送方式,但在实际变量参数前加@符号为地址传送方式。也可在调用前用命令Set Udfparms To Value/Reference指明变量参数是使用值传送方式还是使用地址传送方式。地址传送是双向传送,而值传送是单向传送。
【例5-25】使用函数的方式编程求圆的面积。
SET TALK OFF
CLEAR
INPUT "请输入圆的半径:" TO X
?"则圆的面积为:", STR(area(X),8,2)
SET TALK ON
FUNCTION AREA
PARAMETERS R
S=3.1416*R*R
RETURN S
运行结果如下:
或者
【例5-26】参数传送示例,认识值传送和地址传送的区别。
Set Udfparms To Value &&设置为值传送,也可不设置
Clear
Wait "按任意键开始以值进行传送" Window
Store 10 To Mv1, Mv2
Modvar(Mv1,Mv2)
?Mv1,Mv2
Wait "按任意键开始以地址传送" Window
Set Udfparms To Reference &&设置为地址传送,也可不设置
Store 10 To Mv1,Mv2
Modvar(Mv1,Mv2)
?Mv1,Mv2
Set Udfparms To Value
Function Modvar
Parameters New_Var1,New_Var2
?New_Var1,New_Var2
Store 20 To New_Var1,New_Var2
Return
运行结果:
在使用Visual FoxPro设计应用程序时,一般都是将一个大的程序分成若干个模块,然后分别单独对这些模块进行设计,从而简化了程序的设计。
如图5-8所示是一个简化了的学生成绩管理系统的功能模块结构,每个模块程序都对应一个独立的*.prg文件。此类管理系统的主控模块程序,通常是一个供用户选择各操作功能的菜单程序,而具体的操作功能则由其下属若干个对应子程序模块实现。
图5-8 应用程序模块结构
【例5-27】使用程序模块结构编写如图5-8所示的程序。
SET SAFETY OFF
SET STATUS OFF
DO WHILE .T.
CLEAR
@ 2,31 SAY "★★★★学生成绩管理系统★★★★"
@ 4,40 PROMPT " 1.添加记录 "
@ 6,40 PROMPT " 2.删除记录 "
@ 8,40 PROMPT " 3.修改数据 "
@ 10,40 PROMPT " 4.查询记录 "
@ 12,40 PROMPT " 0.退出系统 "
@ 14,30 SAY "请选择0-4:"
MENU TO CJ
DO CASE
CASE CJ=1
DO DA_TJ
CASE CJ=2
DO DA_SC
CASE CJ=3
DO DA_XG
CASE CJ=4
DO DA_CX
CASE CJ=0
WAIT WINDOW "您已经退出,欢迎下次使用!"
EXIT
ENDCASE
ENDDO
CLOSE
RETURN