导图社区 VFP
关于Visual FoxPro结构化程序设计,包含结构化程序设计、Visual FoxPro程序与程序文件、程序的调试等。
编辑于2021-10-23 19:55:19VFP
结构化程序设计
结构化程序设计的原则
1.自顶向下
2.逐步求精
3.模块化
4.限制使用Goto语句
结构化程序设计的基本结构
1.顺序结构
2.选择结构(分支结构)
3.循环结构(重复结构)
结构化程序设计风格
1.源程序文档化
2.数据说明规范化
3.语句模块化
4.输入输出要检验数据的合法性
Visual FoxPro程序与程序文件
程序的基本概念
计算机的程序就是让计算机工作的流程,是能够完成一定任务的命令的有序集合; 将这些命令存放在文件中就形成了程序文件(或命令文件);
优点: ·可以利用编辑器,方便地输入、修改和保存程序; ·可以用多种方式、多次运行程序; ·可以在一个程序中调用另外的程序。
程序文件的建立
建立和编辑程序文件可以在任何文本编辑软件(如Windows下带的记事本等)中进行,但在Visual FoxPro中,最方便的还是调用系统内置的的文本编辑器中来进行,它具有全屏幕编辑功能。建立的程序文件也称为源程序,其扩展名为.PRG ,源程序在执行时自动编译生成目标文件,目标文件的扩展名为.FXP
通过菜单直接调用
通过项目管理器调用
通过交互命令的方式调用:MODIFY COMMAND
程序文件的运行
对于项目中的程序文件,打开该项目后,选中要运行的程序文件,再单击“运行”按钮,即可运行该程序
对于不属于项目的程序文件,可以是在命令窗口使用DO <程序文件名>命令来执行程序
如果程序文件已经在程序编辑窗口中打开,只需单击常用工具栏中的运行按钮即可运行该程序
在运行程序时,若程序中有错误,系统将出现程序错误窗口,并提示是何种错误,单击“取消”,回到程序编辑窗口,可以修改,存盘后,再运行,直到没有错误。 程序一旦成功执行,就会生成编译后的.FXP文件,其主文件名同命令文件。
基本的输入和输出命令
输入命令
输入一个字符命令(或称中断等待命令)
【格式】WAIT [<字符表达式>] [TO <内存变量>] [WINDOWS [AT <行>,<列>] ] [CLEAR | NOCLEAR] [TIMEOUT <数值表达式>]
【功能】显示字符表达式的值作为提示信息,暂停程序执行,直到用户按任意键或单击鼠标时继续程序的执行
概要
【说明】
①只接收由键盘输入的单个字符。若选TO短语,内存变量则为字符型。即使用户只键入了一个回车键,本命令也认为接收到一个空字符(长度为0,ASCII码值为0)
② <字符表达式>是提示语,缺省时系统显示为“按任意键继续……”
③一般情况下,提示信息被显示在Visual FoxPro主窗口或用户自定义的当前窗口里。如选WINDOWS子句,则会出现一个WAIT提示窗口,用以显示提示信息;如不选AT子句,则将字符表达式的提示语显示在屏幕右上角的WAIT提示窗口中;选AT子句,提示语在指定的屏幕坐标处显示。
④ NOWAIT:在显示了提示语的同时,光标仍处于当前控制窗口中。
⑤NOCLEAR:不关闭提示窗口,直到执行下一条WAIT WINDOW命令或WAIT CLEAR命令为止。
⑥ 选TIMEOUT <数值表达式>项后,<数值表达式>给出以秒为单位的时间。若在此时间内用户不键入任何数据,WAIT语句将自动终止,并取回车键作为接受的值.
输入字符串命令
【格式】ACCEPT [<字符表达式>] TO <内存变量名>
【功能】从键盘上输入一个字符串常量给内存变量
【说明】
①字符表达式是提示语
②从键盘上输入的字符串内容不需要加定界符,否则定界符本身也当成字符串的一部分输入内存变量。
③命令中的TO短语是必选项。
④如果不输入任何内容而直接按回车键,系统会把空串赋给指定的内存变量
输入其他类型数据命令
【格式】INPUT [<字符表达式>] TO <内存变量名>
【功能】将从键盘上输入数据或表达式的计算结果存入指定的内存变量。
【说明】
①从键盘输的数据可以是数值型、字符型、日期型、逻辑型、货币型等数据类型但不能不输入任何内容直接按回车
②若输入字符型数据,一定要加定界符(与ACCEPT不同)
③字符表达式是提示语
④输入的内容可以是常量、变量或表达式,如果输入的变量或表达式,则把变量或表达式的结果内容存入指定内存变量
屏幕输入格式设计命令的基本格式
【格式】@<行,列> [SAY <字符型表达式>] GET <变量名> READ
【功能】从指定<行,列>位置开始,首先输出字符型表达式的内容,空一格后再显示GET子句中变量的值
输出命令
【格式】@<行,列> SAY <表达式> [FONT ‘字体’,字号]
【功能】在指定位置显示指定表达式的值
【说明】
FONT 子句中’字体’,可用“宋体”“黑体”、“仿宋体”、“楷体”、“隶书”等,字号为数值表达式,决定了显示的内容的字体和字号
程序的基本结构
程序结构是指程序中命令或语句执行的流程顺序
顺序结构
对于一个VFP程序,如果系统执行完一条语句后,将继续执行在书写顺序上紧接着此语句的下一条语句,那么这种语句就是顺序执行语句。 由顺序执行语句组成的程序称为顺序结构程序
【例4.1】求圆的面积,其中圆的半径从键盘输入
选择结构
在程序设计中,经常根据具体的条件,有选择地运行或跳过程序中的某段语句,这样的语句就是选择结构(又称为分支结构)
条件语句:(IF…ELSE…ENDIF)
简单的条件语句(双向分支)
【格式】IF <逻辑表达式> <语句序列1> [ELSE <语句序列2>] ENDIF
【功能】如果逻辑表达式(也可以为关系表达式)的值为.T.(条件满足),则执行语句序列1,然后执行ENDIF后的语句;而当条件不满足且具有ELSE语句时,执行语句序列2(如图4-2所示),若无ELSE语句(当然也就没有语句序列2),则执行ENDIF后面各语句(如图4-3所示)
例4.2 通过键盘输入一个数,求其绝对值
IF语句嵌套
条件语句可以嵌套,但不能出现交叉
多重嵌套时要特别注意的是IF和ELSE(可选项)以及ENDIF的配对使用
【例4.3】输入学生的百分制成绩,转换成不及格(小于60分)、及格(大于等于60小于75分)、良好(大于等于75小于90分)和优秀(90分以上)四级记分制成绩输出
IIF判断选择函数
为便于进行分支处理,Visual FoxPro提供了一个IIF()函数,它能够先进行条件判断,然后决定返回其值。它的使用效果比分支语句更快捷
【格式】 IIF(<逻辑表达式>,<表达式1>,<表达式2>)
【功能】 若<逻辑表达式> 的值为.T.时,函数返回<表达式1>的值;若<逻辑表达式> 的值为.F.时,函数返回<表达式2>的值
多重分支语句(DO CASE…ENDCASE)
Visual FoxPro提供了分支语句(DO CASE…ENDCASE),专门用来进行多重条件判断操作,它比IF语句的嵌套结构更清晰、易读
【格式】DO CASE CASE <逻辑表达式1> <语句组1> CASE <逻辑表达式2> <语句组2> …… CASE <逻辑表达式n> <语句组n> [OTHERWISE <语句组n+1>] ENDCASE
【功能】执行该语句时,系统依次查看每一个CASE后的条件,碰到第一个条件满足者,执行该条件下的语句组,然后执行ENDCASE后面的语句(其他CASE条件不再查看)。如果所有CASE条件都不满足,在没有OTHERWISE的情况下,则不执行任何语句,去执行ENDCASE后各语句;在有OTHERWISE选项的情况下,执行OTHERWISE后的语句组后再执行ENDCASE后面的语句
说明:多重分支的语句组可以包含Visual FoxPro的任何合法的语句,因此还可以和另一个多重条件分支语句或IF语句构成嵌套关系
循环结构
循环是按照给定的条件重复执行一个具有特定功能的去程序段,这样构成的语句就是循环结构
DO WHILE-ENDDO
【功能】 执行时,先判断<逻辑表达式>的值,若为.T.则执行循环体一遍,遇到ENDDO再转向DO WHILE处重新判断<逻辑表达式>的值,如此重复,直到<逻辑表达式>的值为.F.时结束循环,执行ENDDO后面的语句。
【说明】① 循环体可以包含Visual FoxPro合法的任何语句,特别是还可以包含另一个循环语句,称为循环的嵌套。每一个DO WHILE必须与一个ENDDO对应。内、外循环不能交叉。 ② 循环体中若有EXIT语句,当执行到该语句时,将无条件地跳出所在的循环,执行ENDDO后面的各语句;当执行到LOOP时(假如有的话),立即返回到本循环的DO WHILE处,再判断逻辑表达式的值以便决定是跳出循环还是执行循环体 ③ 在循环体中,必须要有改变逻辑表达式条件的语句,使得总有一刻,其值为.F.,或有EXIT语句退出循环,否则将形成无限循环(俗称“死循环”)。
FOR-ENDFOR
【功能】执行本命令时,系统首先把初值赋给<内存变量>,判断是否已超过终值,若是,则退出循环,否则执行<语句组>
【说明】: ①初值、终值和步长都可以是数值表达式。但这些表达式仅在循环语句执行开始时被计算一次。在循环语句的执行过程中,它们是不会改变的。 ②内存变量作为循环计数器,用于控制循环次数。每循环一次,就要修改循环变量的值,即在原来的基础上增加(或减少)步长。缺省步长时,默认为1。 ③若步长为正(负)数,则每循环一次,<内存变量>的值就增加(减少)步长的绝对值,直到<内存变量>的值“超过终值”为止。“超过终值”的含义是:步长为正时,内存变量的值大于终值;步长为负时,内存变量的值小于终值。 ④可以在循环体内改变循环变量的值,但这会影响循环体的执行次数。 ⑤EXIT和LOOP命令同样可以出现在该循环语句的循环体内。当执行LOOP命令时,结束循环体的本次执行,然后循环变量增加一个步长值,并再次判断循环条件是否成立。 ⑥ ENDFOR和NEXT二者等价,只能选择其中之一。
【例4.10】编写程序,求1000之内所有奇数之和
循环程序的嵌套 若一个循环语句的循环体内又包含其它循环,就构成了多重循环,也称为循环嵌套。 使用多重循环要分清外循环和内循环,外循环体中必然包含内循环语句,执行外循环体就是将其内循环语句及其它语句执行一遍。
【例4.11】编写程序TEST9.PRG,输出九九乘法表
【例4.12】从键盘上输入20个数,求其中的最大数和最小数
SCAN-ENDSCAN语句
该循环语句一般用于处理表中的记录。语句可指明需处理的记录范围以及应满足的条件。
【格式】SCAN [<范围>] [FOR <条件1>] [WHILE<条件2>] <循环体> ENDSCAN
【功能】记录指针自动并且依次地在当前表的指定范围内满足条件的记录上移动,对每一条记录执行循环体内的命令
【说明】 ① 使用该语句时,必须打开一个表。 ② <范围>的默认值是ALL。 ③ EXIT和LOOP命令同样可以出现在该循环语句的循环体内。 ④ SCAN…ENDSCAN语句也叫做“扫描循环”语句,其功能相当于LOCATE、CONTINUE和DO WHILE…ENDDO语句的合并功能
【例4.13】利用上一章的YYGL库的内容,编写程序TEST11.PRG,统计YSXX表中医生编号前三位为“108”的男、女医生数
子程序及其调用
在一个程序中,可能某些程序段需要多次使用, 通常将该程序段创建为一个命令文件。这个用来被其他程序调用的命令文件就叫子程序,而调用它的程序就叫它的主程序。 建立和编辑子程序的方法同建立其他命令文件一样,都是使用MODIFY COMMAND命令。
子程序的调用及形式参数的定义
子程序的调用命令
【格式】DO <子程序名> [WITH <实参表>] 或 子程序名([<实参1>] [,<实参2 >] ,…..)
【功能】调用指定的子程序
【说明】: ① 子程序名的缺省扩展名是.PRG。该文件必须在磁盘上存在。若不在当前目录下,还应指定路径。 ② 执行一个DO命令即打开一个子程序文件,子程序可以多次被调用,也可以嵌套调用。 ③ <实参表>是一些用逗号隔开的表达式或变量,其个数和类型应该与子程序中定义的形参变量的个数与类型相匹配(如果不需要参数传递,则不选可选项)。调用子程序时,如果实参为表达式,则先计算每个实参表中各表达式的值,然后传递给相应的形式参数,这种情况称为按值传递; 如果实参是变量,那么传递的将是变量的地址,这时形参和实参实际上是同一个变量(尽管它们的名字可能不同),在子模块中对形参变量值的改变同样是对实参变量值的改变,将会被带回到主程序的实参中,这种情况称为按引用传递。
形式参数的定义
【格式】PARAMETERS <形参表>
【功能】接收调用命令中相应实参值。如果是按引用传递,还要在调用结束后, 返回对应参数的计算值。
【说明】: ① <形参表>是用逗号分隔的若干个内存变量。它的个数和类型与调用它的实参表中对应的个数和类型相匹配。 ② 它必须作为子程序中的第一个可执行语句,否则会出错。 ③ 若实参是一个数组变量(不必带维数),则形参自动定义为一个同样的数组。
过程、过程文件和过程调用
过程及过程文件的概念 : 如果要调用多个子程序,由于子程序还可以嵌套调用,那么在内存中打开和管理这么多的文件,也有一定的难处。因此可以把每一个子程序作为一个“过程”,它不单独以文件方式存盘,而是“放入”一个过程文件中,这样一来,一个过程文件中可以包含一个或多个“过程”,只有过程文件是以文件的形式存盘,一旦打开过程文件,主程序便可以随心所欲地调用其中的若干过程(子程序)了。 每一个“过程”都有一个名字,称为“过程名”, “过程名”不允许使用扩展名。
【说明】: <形式参数表>用来接收调用它的实参数(假如需要的话)。 RETURN后面若选<表达式>,则返回时将表达式的值返回给调用程序。利用该返回值可以完成函数的功能。
过程文件的调用 在调用过程文件中的过程之前,一定要先打开过程文件。 【格式】SET PROCEDURE TO <过程文件名1>[,<过程文件名2>…][ADDITIVE] 【功能】打开一个或多个过程文件,以供程序调用其中的过程。也可以打开其他源代码文件,如菜单程序文件.MPR。
在打开过程文件后,即可通过DO命令调用过程: 【格式】DO <过程名> [WITH <实参表>] 或 =<过程名>(<实参表>)(实现函数型的过程调用) 或 <过程名>(<实参表>) 【功能】调用指定的过程。若选<实参表>,将它传给形式参数。
关闭过程文件 【格式】SET PROCEDURE TO 或 CLOSE PROCEDURE
过程的直接调用: 过程 也可放在主程序当中不形成一个过程文件。当然也不需要打开,直接调用过程即可
返回主程序语句 【格式】RETURN [<表达式>|TO MASTER|TO <过程名>] 【功能】终止当前运行的程序,返回主程序(或指定的程序)。 说明:如果在命令窗口下调用子程序,则返回到命令窗口;如果在子程序中调用另外的子程序,则返回到调用处的下一个语句;如果选择了TO MASTER,不管是哪一级调用,都返回最上级主程序;如果选用了TO <过程名>,则返回到指定的过程。
内存变量的作用域 开发应用程序的过程中,常发生在不同的程序中使用同名内存变量的问题。Visual FoxPro根据使用说明语句或创建的时间不同区别内存变量的作用范围,并分为局部型内存变量、全局型内存变量、隐蔽型内存变量和区域型内存变量四种
局部型内存变量 程序中未加任何说明定义的内存变量都是局部变量。它具有如下性质: (1)局部变量在定义它的程序运行完成后即被清除; (2)主程序中的局部变量在子程序中继续有效;如果它在子程序中被改变了值,返回主程序时也将新值带回主程序,除非子程序中将它定义为隐蔽型内存变量。但是,下一级程序中定义的局部变量却不能被任何上一级使用,即子程序中的局部变量在主程序中没有其同名变量,则该变量不能带回主程序。所以,局部型内存变量在子程序多层嵌套时的使用权具有单向性。
全局型内存变量 全局型内存变量可用命令PUBLIC来说明。 【格式】PUBLIC <内存变量名表> 或PUBLIC [ARRAY] <数组名1>(<数值表达式1>[,<数值表达式2>]) [,<数组名2>(<数值表达式3>[,<数值表达式4>])]… 【功能】将给定的内存变量名表中的每一个变量或定义的数组定义为全局变量。
【说明】: ① 格式中的关键字ARRAY可选可不选。 ② 在命令窗口定义的所有变量均为全局变量。 ③ 程序中的全局内存变量必须先说明后赋值。 ④ 全局变量在整个程序中包括子程序中都有效。在任一子程序中都可以改变它的值;在子程序中定义的全局变量在主程序中仍然有效;即使是整个程序运行结束回到命令窗口,所定义的全局变量仍然保持在内存中,除非用RELEASE或CLEAR ALL命令清除。
隐蔽(藏)型内存变量 隐蔽型内存变量可以用PRIVATE或PRIVATE ALL命令说明。但两者的功能不完全相同。 【格式】PRIVATE <内存变量名表> 或 PRIVATE ALL [LIKE <标识符>|EXCEPT <标识符>] 【功能】将内存变量名表中的各变量或指定的内存变量定义为隐蔽型内存变量。
【说明】: 隐蔽型内存变量屏蔽该变量仅在当前程序中有效。 【注意事项】: ① 若主程序中已将某一变量定义为隐蔽型内存变量,则不能在其调用的子程序中再将其定义为全局变量;反之,若在主程序中定义了全局变量,在其下级可以将其再定义为隐蔽型变量,只是该变量只在下级有效。 ② 主程序中的任何类型的隐藏型变量都可以在其下级有效,反之不行。
区域型内存变量 区域型内存变量用LOCAL命令说明,它的格式同PRIVATE。它与屏蔽型内存变量相似,差别在于作用范围更小,仅限于定义它的程序中,即使是调用下一层次的过程也无法传递。
程序的调试
程序调试是指在发现有错误的情况下,确定出错的位置并纠正错误。其中关键是要确定出错的位置。有些错误(如语法错误)系统是能够发现的,当系统编译、执行到这类错误代码时,不仅能给出出错信息,还能指出出错的位置;而有些错误(如计算或处理逻辑上的错误)系统是无法确定的,只能由用户自己来查错。Visual FoxPro提供的功能强大的调试工具―调试器,可以帮助我们进行这项工作。