480 likes | 585 Views
第七章 程序设计基础. 5.1.1 VFP6 程序设计基本概念. VFP6 支持过程化程序设计和面向对象程序设计两种程序设计与开发的类型。 下面是一个完整的 VFP 过程化程序,可以引出几个基本概念。. * 功能说明:求圆形的面积。 *文件名: L501.PRG CLEAR CTALK=SET("TALK") SET TALK OFF INPUT " 请输入圆的半径,半径 =" TO R S=PI()*R*R ? " 半径为 "+ALLTRIM(STR(R))+" 的圆,面积 =",S SET TALK &CTALK RETURN.
E N D
5.1.1 VFP6程序设计基本概念 VFP6支持过程化程序设计和面向对象程序设计两种程序设计与开发的类型。 下面是一个完整的VFP过程化程序,可以引出几个基本概念。 *功能说明:求圆形的面积。 *文件名:L501.PRG CLEAR CTALK=SET("TALK") SET TALK OFF INPUT "请输入圆的半径,半径=" TO R S=PI()*R*R ? "半径为"+ALLTRIM(STR(R))+"的圆,面积=",S SET TALK &CTALK RETURN
1、从形式上看,VFP的程序是由若干有序的命令行组成,且满足下列规则: (1)一个命令行内只能写一条命令,命令行的长度不得超过2048个字符,命令行以回车键结束。 (2)、一个命令行可以由若干个物理行组成,即一条命令在一个物理行内写不下时,可以分成几行。换行的方法有两种:一种是在物理行的末尾加符号“;”,表示下一行输入的内容是本行的继续;另一种是系统自动换行,即输入程序时,只管逐条命令输入,无需考虑本条语句是否超过屏幕行宽的最大限度,当输入的语句超过屏幕的最大行宽时,系统自动换行。输入时只需在一行结束时按回车键,通知系统本命令行输入完毕。 (3)为便于阅读,可以按一定的格式输入程序,即一般程序结构左对齐,而控制结构内的语句序列比控制结构的语句缩进若干格。 2、从功能上看,程序可以分为三个部分: 第一部分是程序的说明部分,在本例程序中是前面的四行,一
般用于说明程序的功能、文件名等需要说明的有关信息。般用于说明程序的功能、文件名等需要说明的有关信息。 第二部分是进行数据处理的部分,在本例程序中是从第五行开始的三行。通常任何一个有意义的程序,总是要有一些原始数据,否则,这个程序就没有处理对象。同样,程序运行的结果也有必要显示或打印出来,否则,用户将不知道程序干了一些什么。因此,第二部分程序常包括下列三个部分,依次为:提供原始数据部分、数据处理部分、输出结果部分。 第三部分是程序的控制返回部分,在本例中就是最后二条命令。它控制程序返回到调用该程序的调用处。 过程化程序设计与面向对象程序设计 过程化程序设计:它是采用结构化编程语句来编写的程序。这类方法的特点是容易把一个复杂的程序分解为若干个较小的过程,每个过程都可进行独立的调试。这类设计方法发展的总思想是从程序员角度考虑使程序设计更简单,而较少从使用角度去考虑。使用这类方法设计的程序流程完全由程序员控制,使用者只能做由程序员预先安排好的事情。
面向对象程序设计:这类程序设计思想是面向对象,即设计的重要任务在于描述对象。程序是由事件驱动的,因而,在执行过程中,持续等待的是一个发生在对象上的事件。而发生什么事件则要看使用者的操作,如单击、双击鼠标等。至于下一步的程序流向,则要看驱动的是什么事件。这类程序设计的主要目的是从任何方便与简化使用入手,由使用者控制程序流向,这在一定程序上增加了编程的难度。 返 回 5.1.2 VFP6程序设计基本操作 1、过程化程序设计基本操作 (1)建立过程文件。在VFP中,一个过程文件就是一个ASCII文本文件,因而可用各类编辑工具来建立。在VFP中有下面二种简易方法来建立: ■在【文件】菜单下的【新建】菜单项中,选择“程序”可选项 。■在命令窗口中使用MODIFY COMMAND命令。
格式:MODIFY COMMAND [<文件名>/?] 功能:打开文本编辑窗口,编写程序代码。 参数描述: [<文件名>]:为可选项,指定打开或创建的程序文件名。若不指定新建程序文件的扩展名,VFP自动指定.PRG为扩展名。MODIFY COMMAND命令支持含有“*”和“?”通配符的文件梗概。名称与这个梗概匹配的每一个文件都在编辑窗口中打开。若省略文件名,将给打开的编辑窗口赋一个初始名称“程序1.PRG”。当关闭编辑窗口时,可以用另外的文件名保存该文件。 [?]:显示“打开”对话框。可以从中选择一个已有程序或输入要创建的新程序名。 说明: 修改程序文件之后,更新过的文件将写到磁盘上。除非在配置文件中用TEDIT指定一个外部编辑器,否则,一般使用VFP的内置编辑器。
【例5-2】用户通过VFP6的命令窗口建立上例程序文件。【例5-2】用户通过VFP6的命令窗口建立上例程序文件。 在VFP6的命令窗口中输入下条命令后按回车键。 MODIFY COMMAND L501 打开程序编辑窗口 在程序编辑窗口中输入程序代码 用Ctrl+W存盘退出编辑窗口,或单击程序编辑窗口上的【关闭】按钮,在弹出的对话窗口中确定存盘,生成L501.prg文件。
(2)运行程序 下面的任一方法均可运行程序: ■选择【程序】菜单下的“运行”菜单,利用“运行”对话框选择要运行的程序; ■在命令窗口中输入如下命令: DO <程序文件名> 系统就会运行这个程序。如果文件不加扩展名,系统会假定它具有.PRG的扩展名,如果想运行一个具有其它扩展名的命令文件时,在输入命令时必须给出这个命令文件的全名。 如:要运行上例中编辑的程序,可以在命令窗口中输入: DO L501 然后按回车键执行。
5.1.3 VFP程序设计编程方式 VFP程序由代码组成,代码包括以命令形式出现的指令、函数和VFP可以理解的任何操作。这些指令包含在“命令”窗口、程序文件、表单设计器与类设计器的事件或方法程序代码窗口、菜单设计器的过程代码窗口、报表设计器的过程代码窗口中。 使用“命令”窗口 可以在“命令”窗口中键入VFP命令并按Enter键执行。若要重新执行该命令,还可以将光标移到此命令所在行并按Enter键。 甚至可以在“命令”窗口中像独立程序一样执行多行代码。要在“命令”窗口中运行多行代码,可以按下述方法执行: (1)选取代码行。 (2)按Enter键或右击并在快捷菜单中选择“运行所选区域”。 因为“命令”窗口是一个编辑窗口,所以在编辑命令时可以使用VFP提供的编辑工具。在“命令”窗口中可以修改、插入、删除、剪切、复制和粘贴正文。
在“命令”窗口中执行命令的优点是:能够立即执行被键入的命令,不需要将其保存为文件并用程序方式执行。此外,在菜单或对话框中所作的选择可以马上转换成“命令”窗口中的命令。用户可以将这些命令复制并粘贴到VFP程序中,然后重复执行这些程序。这样做可以很容易地重复执行成百上千条的命令。在“命令”窗口中执行命令的优点是:能够立即执行被键入的命令,不需要将其保存为文件并用程序方式执行。此外,在菜单或对话框中所作的选择可以马上转换成“命令”窗口中的命令。用户可以将这些命令复制并粘贴到VFP程序中,然后重复执行这些程序。这样做可以很容易地重复执行成百上千条的命令。 2、创建程序 VFP程序是包含一系列命令的文本文件。在VFP中可以通过下述途径创建程序: (1)在项目管理器中,选定“代码”选项卡中的“程序”项; (2)选择“新建”命令。 或者: (1)在【文件】菜单中选择【新建】命令; (2)在“新建”对话框中选择“程序”; (3)单击【新建文件】按钮。 或者在“命令”窗口中键入: MODIFY COMMAND
3、保存程序 创建程序后,一定要注意保存程序。若要保存程序,可以从【文件】菜单中选择【保存】命令。或者按Ctrl+W组合键保存,若不想保存对新建程序或已有程序所做的修改,也可以使用Ctrl+Q组合键,不存盘而退出编辑窗口。 若要关闭一个没有保存的程序,则会弹出相应对话框,提示用户是否保存已作的修改。 若保存了一个由项目管理器创建的程序,则该程序被加入到项目中。 若保存一个尚未命名的程序,则会打开“另存为…”对话框,提示用户可以在其中为程序指定程序名。程序保存后,可以运行或修改它。 4、修改程序 程序保存后可以修改。首先,按以下四种方法之一打开想要修改的程序文件: ■若程序包含在一个项目中,则在项目管理器中选定它并选择
修改命令。 ■在【文件】菜单中选择【打开】命令,这时弹出一个包含文件列表的对话框,在“文件类型”列表框中选择“程序”,然后在文件列表中选定要修改的程序,单击【确定】按钮。 ■在“命令”窗口中按如下方式键入要修改的程序名: MODIFY COMMAND <程序文件名> ■在“命令”窗口中输入: MODIFY COMMAND ? 然后从文件列表中选择要修改的程序,单击【打开】按钮。打开文件之后便可进行修改,修改完成后就可以保存。 5、运行程序 程序创建之后便可以运行。若要运行程序,有以下三种方法: ■若程序包含在一个项目中,则可在项目管理器中选定它,并选择【运行】命令。
5.2 VFP6的程序设计语言基础 5.2.1 VFP的交互式输入输出命令 5.2.2 VFP6程序设计的条件与循环 返 回 退 出
5.2.1 VFP的交互式输入输出命令 设计程序,就是用一系列命令存储数据并操作这些数据。程序设计的原材料是数据和数据的存储容器,而处理这些原材料的工具是命令、函数的操作符。 1、交互式输入命令 (1)字符接收语句 格式:ACCEPT [<提示信息>] TO <内存变量名> 功能:将从键盘上接收的字符串数据存入指定的内存变量中。提供此命令是为了向后兼容,在VFP中可以用文本框控制命令代替。 参数描述: [<提示信息>]:指定提示信息字符串,其后是数据输入区。在VFP中,提示文本的字体与VFP主窗口的字体相同。但输入的字符数据用9磅FoxFont字体显示。
[<内存变量名>]:指定存储字符数据的内存变量或数组元素。如果没有定义此内存变量,ACCEPT将自动创建。如果没有输入数据就按Enter键,内存变量或数组元素则为空字符串。 说明: 在VFP中可用表单设计器或DEFINE CLASS来创建文本框控制。ACCEPT命令允许直接向内存变量或数组元素输入字符数据,输入时不需要用引号将字符括起来。 执行此语句时,先在屏幕上显示<提示信息>,光标紧随其后,然后暂停程序运行,等待用户从键盘上输入信息。输入的信息可以是任何可显示的ASCII码字符串,并以回车键结束。系统将此字符串信息存入指定的内存变量中,然后,继续运行暂停的程序。 【例5-3】试编程完成下述功能:从键盘随机输入某个表的文件名,要求打开并显示此表的内容。 在命令窗口输入下列命令: MODIFY COMMAND L503 (文件名中的扩展名.PRG可省略,以后不再说明)
屏幕显示编辑窗口。在编辑窗口输入如下程序代码后用Ctrl+ W存盘,返回命令窗口。 CLEAR SET TALK OFF ACCEPT "请输入表文件名" TO FileName USE (FileName) LIST USE RETURN 说明:程序中第四句使用了宏代换函数,这是由于FileName本身不是文件名,而其内容才是文件名。 (2)通用数据接收命令 ACCEPT语句只能给字符型内存变量提供数据。如果用户想给其它类型的内存变量提供数据,可以使用下列命令: 格式:INPUT[<提示信息>] TO <内存变量名>
功能:用于接收从键盘上输入的表达式,并将计算结果存入指定的内存变量或数组元素中。包含此命令也是为了提供向后的兼容性。在VFP中,该命令也可以用文本框控制代替。功能:用于接收从键盘上输入的表达式,并将计算结果存入指定的内存变量或数组元素中。包含此命令也是为了提供向后的兼容性。在VFP中,该命令也可以用文本框控制代替。 参数描述: [<提示信息>]:提示信息,提示用户输入数据。 [<内存变量名>]:指定一个内存变量或数组元素,存储从键盘输入的数据。如果指定的内存变量或数组元素不存在,VFP将自动创建该内存变量或数组。 说明: INPUT语句与ACCEPT语句的执行过程相同,功能相似。 <内存变量名>的数据类型取决于输入数据的类型。可以为数字型、字符型、日期型和逻辑型。 INPUT语句与ACCEPT语句的区别是:ACCEPT命令只能接收字符串,而INPUT语句可以接收任意类型的VFP表达式;如果输入的是字符串,ACCEPT语句不要使用字符型定界符,而INPUT语句必须用定界符括起来。
【例5-4】试编程完成下列功能。从键盘上随机输入一个正数,以此数为半径,求圆面积和球体积,并输出结果。【例5-4】试编程完成下列功能。从键盘上随机输入一个正数,以此数为半径,求圆面积和球体积,并输出结果。 程序如下: 程序中的第一行为注释行,说明此程序文件名;第四行的功能是不显示命令处理信息,第十行的功能是恢复显示命令处理信息。 *L504.PRG CLEAR CTALK=SET("TALK") SET TALK OFF INPUT "半径=" TO R S=PI()*R*R V=4/3*PI()*R**3 ? "圆面积=",S ? "球体积=",V SET TALK &CTALK RETURN 在命令窗口中执行: DO L504 屏幕显示 输入10后按Enter键 半径= 10 显示结果 圆面积= 314.16 球体积= 4188.790205
(3)输入一个字符语句 格式:WAIT[<提示信息>][TO <内存变量名>] 功能:暂停正在运行的程序,直到输入一个字符为止。 此语句与ACCEPT语句的功能部分相似。若选择TO <内存变量名>子句,则将输入的单个字符存入指定的内存变量。若直接输入回车键,则内存变量中存入空字符串。内存变量的类型为字符型。若选择<提示信息>子句,执行此命令时,屏幕上将显示提示信息,否则,屏幕上将显示“按任意键继续…” WAIT语句主要用于下列两种情况。 ■暂停程序的运行,以便观察程序的运行情况,检查程序运行的中间结果。 ■根据实际情况输入某个字符,以控制程序的执行流程。比如,在某应用程序的“Y/N”选择中,常用此命令暂停程序的执行,等待用户回答“Y”或“N”,由于这时只需输入单个字符,也不用按回车键,操作简便,响应迅速。
2、格式化输出命令 前面的章节中在屏幕上显示信息时,使用的是非格式化输出命令:“?”或“??”,为了能按一定的要求来设计屏幕格式,使之美观、方便,下面介绍一个屏幕显示格式控制命令。 格式:@ <行号, 列号> SAY <表达式> 功能:从指定的行、列号开始输出表达式的值。 说明:①<表达式>可以是常数、字段变量及由它们组成的表达式。②定位输出时,一次只能输出一个表达式。 3、程序设计辅助命令 (1)、中止程序运行 ■在程序运行过程中,按Esc键可以中止程序的运行,系统会显示警告对话框让用户选择: 【取消】 中止程序运行,这是缺省选择; 【挂起】 暂停程序运行,返回命令窗口。当选择【程序】菜单下的【继续执行】选项或在命令窗口中输入“Resume”命令,系统
则从中止的地方继续程序的执行; 【忽略】 忽略所给的Esc,继续程序的执行。 通常在程序的开始时加有命令: SET ESCAPE OFF 执行该命令后,Esc键处于关闭状态,在程序运行过程中,用户不能通过Esc键来中止程序的运行,因为在应用程序中,不希望中止它;而在程序调试阶段,通常不关闭这个键,让程序在运行过程中,随时都可以中断执行,以检查程序中间的运行状况。 格式 一:CANCEL 功能:结束程序的运行,返回命令窗口,同时关闭所有打开的文件。 格式二:SUSPEND 功能:暂时中止程序运行,返回命令窗口。当在菜单中选择【程序】|【继续执行】时,或在命令窗口中输入RESUME命令时,系统再次从中止的地方继续执行程序。
(2)、注释命令 格式一:NOTE/ * <注释字符串> 格式二:&& <注释字符串> 说明:上述命令不作任何操作,只是注释标记,用于说明程序或命令的功能等。注释内容不需要用定界符定界,执行时也不显示。注释信息如果在一行内没有写完,换行时也必须再写注释命令。NOTE或*是用于整行注释的,因此,它必须写在每一个注释行的开头;而&&命令是用于注释一行的部分内容的,因此,它可以写在行中(命令的尾部、注释信息的头部),这是程序中唯一可以在一个逻辑行写二个语句的命令。 USE STUDENT &&打开STUDENT表 (3)文本显示命令 功能:将<文本字符串>原样输出。 这条命令通常是用于程序中对用户说明某些问题。 格式:TEXT <文本字符串> ENDTEXT 返 回
5.2.2 VFP6程序设计的条件与循环 VFP的程序结构可以分为三种:顺序结构、分支结构、循环结构。 下面将以一个程序演示条件分支结构的循环结构,并对这些概念详细说明。 【例5-5】假设某单位有很多员工,并且要给月工资高于或等于1000元的员工增加5%的工资,给月工资低于1000元的员工增加10%的工资。 下面的示例程序将完成这一任务。此示例程序假定已在当前工作区打开了员工工资表,表中有一个名为“月工资”的数值型字段。 *L505 CTALK=SET("TALK") SET TALK OFF SCAN IF 月工资>=1000 REPLACE 月工资 WITH 月工资*1.05
真 假 条件判断 ELSE REPLACE 月工资 WITH 月工资*1.1 ENDIF ENDSCAN SET TALK &CTALK RETURN 在这一示例程序中用到了顺序结构、循环结构和条件分支结构。 1、条件语句 条件分支根据条件的计算结果执行不同的操作。 条件分支结构逻辑流程图 : VFP中有两条命令实现条件分支: 单条件选择命令 入口 格式:IF <条件表达式> <语句序列1> [ELSE <语句序列2>] ENDIF 语句序列1 语句序列2 出口
参数描述: <条件表达式>:指定要计算的逻辑表达式。如果<条件表达式>的值为“真”,则执行IF语句之后的<语句序列1>;如果<条件表达式>的值为“假”,而且包含ELSE语句和<语句序列2>,则执行<语句序列2>;如果<条件表达式>的值为“假”,而且不包含ELSE语句和<语句序列2>,则程序忽略IF语句和ENDIF语句之间的所有语句,程序从ENDIF语句后的第一条命令开始继续往下执行其它程序。 说明:一个IF…ENDIF语句块中可以嵌套另一个IF…ENDIF语句块。 从【例5-5】所示的程序中可以看到:当当前记录中“月工资”字段的值大于等于1000元时,将使“月工资>=1000”这个条件表达式的值为“真”,此时,程序控制执行<语句序列1>“REPLACE 月工资 WITH 月工资*1.05”,即将月工资高于或等于1000元的工资上调5%。否则,即当当前记录中“月工资”字段的值低于1000
元时,将使“月工资>=1000”这个条件表达式的值为“假”,此时,程序控制执行<语句序列2>“REPLACE 月工资 WITH 月工资*1.1”,即将月工资低于1000元的工资上调10%。 (2)多条件选择语句 参数描述: CASE <条件表达式1> <语句序列1> … :VFP在执行这条多条件选择命令时,按命令行中写出的条件表达式的顺序逐条检查<条件表达式>,当遇到第一个结果为“真”的<条件表达式>时,就执行它后面的语句序列。语句序列中的命令逐条被执行,直到遇到下一个CASE或OTHER-WISE或ENDCASE,然后, 格式:DO CASE CASE <条件表达式1> <语句序列1> [CASE <条件表达式2> <语句序列2> … CASE <条件表达式N> <语句序列N>] [OTHERWISE <语句序列N+1>] ENDCASE
再从ENDCASE语句后的第一条命令开始继续执行其它命令。再从ENDCASE语句后的第一条命令开始继续执行其它命令。 如果一个CASE <条件表达式>的<条件表达式>为“假”,就忽略它后面的语句序列。 【例5-6】运行一个程序,随机输出一条信息: CLEAR AA=INT(RAND()*10) &&随机产生一个10以内的整数 DO CASE CASE AA=0 ? “这次产生的随机数是:0” CASE AA=1 ? “这次产生的随机数是:1” CASE AA=2 ? “这次产生的随机数是:2” CASE AA=3 ? “这次产生的随机数是:3” OTHERWISE ? “这次产生的随机数是:大于3!” ENDCASE
2、循环语句 程序设计中的循环,是指在程序中从某处开始,有规律地反复执行某一个程序块的现象。VFP的循环命令有三类:基于条件的循环、基于计数的循环和基于表的循环。 (1)基于条件的循环:DO WHILE命令 格式:DO WHILE <条件表达式> [<语句序列>] [EXIT] [LOOP] ENDDO 参数描述: <条件表达式>:指定一个逻辑表达式,它的值决定是否执行DO WHILE和ENDDO之间的命令集合。如果<条件表达式>的值为“真”,就执行命令集。 [<语句序列>]:指定当<条件表达式>计算为“真”时要执行的
VFP命令集。 [LOOP]:直接将程序控制返回到DO WHILE语句,并重新计算条件值。LOOP可以放在DO WHILE和ENDDO之间的任何位置。 [EXIT]:将程序控制从DO WHILE和ENDDO循环的内部转到ENDDO后的第一条命令。EXIT可以放在DO WHILE和ENDDO之间的任何位置。 ENDDO:表明DO WHILE语句的结束。 【例5-7】计算连续自然数之和,并且显示和刚大于1000的最后一个自然数。 STORE 0 TO AA,BB DO WHILE AA<=1000 BB=BB+1 AA=AA+BB ENDDO ? BB 结果显示为45。
【例5-8】求连续N个不是7的倍数的自然数之和,当和是101的倍数时显示最后的自然数和它们的和。 STORE 0 TO AA,BB &&定义二个变量,用以保存累加值和累加数 DO WHILE .T. BB=BB+1 IF MOD(BB,7)=0 &&判断BB是否为7的倍数 LOOP &&如果BB是7的倍数则返回去将BB再加1 ENDIF AA=AA+BB &&将BB不是7的倍数的连续自然数累加求和 IF MOD(AA,101)=0 &&判断AA是否是101的倍数 EXIT &&如果AA是101的倍数,则结束程序的循环 ENDIF ENDDO ? BB,AA 屏幕显示结果为207和18483。
(2)基于计数的循环:FOR命令 格式:FOR <内存变量>=<初始值> TO <终值> [STEP <步长>] <语句序列> [EXIT] [LOOP] ENDFOR/NEXT 参数描述: <内存变量>:指定作为计数器的内存变量或数组元素。在执行FOR…ENDFOR语句之前,此内存变量或数组元素不一定存在。 <初始值> TO <终值>:<初始值>是计数器的初始值,而<终值>是计数器的终止值。 [STEP <步长>]:是计数器递增或递减的步长。如果<步长>是负值,则计数器递减;如果省略STEP子句,计数器每次递增1。 <语句序列>:指定要执行的VFP命令,它可以包含任意数量的命令。
[EXIT]:将控制权交给紧接在ENDFOR后面的命令。可以在FOR与ENDFOR之间的任何地方放置EXIT。[EXIT]:将控制权交给紧接在ENDFOR后面的命令。可以在FOR与ENDFOR之间的任何地方放置EXIT。 [LOOP]:将控制权直接交给FOR子句,不再执行LOOP与ENDFOR之间的语句。计数器正常递增或递减,就像执行到ENDFOR子句一样。可以在FOR与ENDFOR之间的任何地方放置LOOP。 说明: 可以用内存变量或数组元素作为计数器,指定FOR…ENDFOR循环中VFP命令的执行次数。在遇到ENDFOR或NEXT之前,始终执行FOR后面的VFP命令。执行过程中,每循环一次,计数器都会产生一次计数,计数增量由<步长>值控制,然后把计数器的值与<终值>进行比较,决定是否进行下一次循环。 【例5-9】求1到100中偶数的和 AA=0 FOR II=2 TO 100 STEP 2 AA=AA+II ENDFOR ? AA 屏幕显示为:2550
(3)基于表的循环命令 格式:SCAN [<范围>] [FOR <条件>] [WHILE <条件>] [<语句序列>] [LOOP] [EXIT] ENDSCAN 参数描述: [<范围>]:指定对当前表中记录扫描的范围。只有在范围之内的记录才有可能扫描到。SCAN命令的默认范围为ALL。 [FOR <条件>]:只有条件表达式的计算结果为“真”的记录,才能对其执行命令。包含FOR子句可以筛选出不想扫描的记录。 [WHILE <条件>]:指定一个逻辑表达式作为执行命令的条件,只要逻辑表达式计算为“真”,就对记录执行命令,直到遇到使表达式不为“真”的记录为止。 [<语句序列>]:指定要执行的VFP命令集。
[LOOP]:把控制权直接交给SCAN子句。LOOP子句可以放在SCAN和ENDSCAN之间的任何地方。[LOOP]:把控制权直接交给SCAN子句。LOOP子句可以放在SCAN和ENDSCAN之间的任何地方。 [EXIT]:把控制权力从SCAN…ENDSCAN循环语句交给ENDSCAN下面的命令。EXIT子句可以放在SCAN和ENDSCAN之间的任何地方。 ENDSCAN:标志SCAN过程的结束。 说明:SCAN命令自动将记录指针移到下一条满足条件的记录,并执行相应的命令块。 【例5-10】逐条显示STUDENT表中男生的情况。 USE STUDENT SCAN FOR 性别=”男” DISP WAIT ENDSCAN USE 或者使用下列代码: USE STUDENT SCAN IF 性别#”男” LOOP ENDIF DISP WAIT ENDSCAN USE
3、使用过程和自定义函数 (1)子程序和过程的调用 子程序或过程的编写和修改方式与一般的程序一样,不同的是过程的最后一个语句必须是返回语句(RETURN),调用过程的程序是主程序,过程可以嵌套,即一个子程序可以再调用其它子程序,但不能形成循环嵌套。 子程序或过程的调用也是用DO命令: 格式:DO <过程名> [IN <程序文件名>][WITH <参数表>] 功能:执行过程名所指定的子程序。WITH用于主程序和子程序间参数的传递。 参数描述: <过程名> :指定要执行的过程名称。VFP首先在当前执行的程序中查找此过程,如果在该程序中找不到此过程,VFP就在用SET PROCEDURE命令打开的过程文件中查找此过程,如果还未找到,则以反向调 用顺序在当前打开的其它程序文件中查找此内
内部过程;若仍未找到,则在磁盘上检索以.FXP为扩展名的外部过程;若还未找到,最后检索以.PRG扩展名的外部过程,并把它编译为.FXP文件。 在执行一个可执行文件或应用程序中,多个过程可以有相同的过程名。当使用DO去启动一个可执行文件或一个应用程序的过程时,VFP只在可执行文件或应用程序的主程序中搜索指定的过程。 IN <程序文件名> :执行<程序文件名> 指定的程序文件中的一个过程。当找到该文件时就执行该过程。如果找不到该程序文件,就会显示“文件不存在”的信息。如果找到了程序文件,但指定的过程不存在,就会显示“找不到过程”的信息。 [WITH <参数表>]:指定要传递给程序或过程的参数。列在<参数表>中的可以是表达式、内存变量、字母和数字、字段或用户自定义函数。默认情况下,参数按引用传递给程序和过程,也可以将参数放在括号中按值传递。传递给程序或过程的参数的最大数目为27。
(2)子程序或过程的返回语句 格式:RETURN [<表达式>/TO MASTER/TO <过程名>] 功能:将程序控制权返回给调用程序。 参数描述: [<表达式>]:指定返回给调用程序的表达式。如果省略RETURN命令或省略返回表达式,则自动将“真”返回给调用程序。 [TO MASTER]:将控制权返回给最高层的调用程序。 [TO <过程名>]:将控制权返回给指定的过程。 说明: RETURN终止程序、过程或函数的运行,并将控制权返回给调用程序、最高次调用程序、另一个程序或窗口。当执行RETURN命令时,VFP释放PRIVATE(专用)类型的内存变量。通常,RETURN放在程序、过程或函数的末尾,用来将控制返回给高层的程序。但是,如果省略RETURN命令,一个隐含的RETURN命令也将被执行。
子程序或过程调用及返回示意图 【例5-11】计算圆面积的主程序为MYMAIN.PRG,子程序为MYSUB.PRG *MYMAIN.PRG CTALK=SET("TALK") SET TALK OFF CLEAR STORE 0 TO RR, AREA
DO WHILE .T. INPUT " 请输入圆的半径:" TO RR DO MYSUB WITH RR, AREA ? "圆的面积是:", AREA WAIT "还要继续计算吗(Y/N)?" TO ANSWER IF UPPER(ANSWER)="Y" LOOP ELSE EXIT ENDIF ENDDO SET TALK &CTALK *MYSUB.PRG PROCEDURE MYSUB PARAMETERS R,S S=PI()*R^2 RETURN } 以一个独立的文件形式存在
(3)过程文件的建立 在实际的程序设计中,需要调用的过程不是一个或二个,而是几个、十几个甚至上百个,这就有可能使打开的文件数超过系统允许打开的文件数,而且将导致磁盘目录过于庞大,使系统调用文件的速度降低,程序执行速度也随之下降,因而有必要将若干个过程按一定的规定放在一个大文件中,这个文件称为过程文件。 1)过程文件的建立 命令格式与建立程序文件一样: 格式:MODIFY COMMAND <过程文件名> 过程文件的格式要求每个过程文件的开头必须用下列语句: 格式:PROCEDURE <过程名> 功能:标明是一个过程。 参数描述: <过程名>:指定过程名称。命名方法与文件名的命名方法相同。
过程文件的内容如下: PROCEDURE <过程名1> <语句序列1> RETURN PROCEDURE <过程名2> <语句序列2> RETURN … … PROCEDURE <过程名N> <语句序列N> RETURN 说明:在一个过程文件中可以包含多个过程,在同一个过程文件中不允许出现相同的过程名,如果有相同的过程名,则只有第一次出现的过程才有被调用的可能。一个过程文件中最多允许包含128个过程。 2)过程文件的调用 过程文件和表文件一样,都是在先打开后才能使用。 ①过程文件的打开命令 格式:SET PROCEDURE TO <过程文件名> 在主程序中应先打开过程文件,将过程文件中的所有过程都调入
内存(打开一个过程文件只算打开了一个文件) 当过程文件不再用时应将其关闭,以节省内存空间。 系统允许打开一个过程文件,当打开另一个过程文件时,先已打开的过程文件系统会自动将其关闭。 【例5-12】程序中常用到计算圆面积、长方形面积、阶乘等,现将它们编为三个过程,放在一个过程文件(MYPROCED.PRG)中,被主程序MYMAIN.PRG调用。 *MYMAIN CLEAR TEXT 这是一个计算圆面积、长方形面积、阶乘等的程序,先输入功能选择: 1--计算圆面 积;2--计算长方形面积;3--计算阶乘;4--退出。再输入参数:所有数据之间用逗号 ","分隔。如计算长方形面积则在下面的提示信息后面输入2,10,15。 ENDTEXT CTALK=SET("TALK") SET TALK OFF SET PROCEDURE TO MYPROCED DO WHILE .T. ACCEPT "请输入您的功能选择及参数:" TO SELECT PROGNAME="PROGRAM"+SUBSTR(SELECT,1,1)
IF (SUBSTR(SELECT,1,1)="1".OR. SUBSTR(SELECT,1,1)="3").AND.OCCURS(",",SELECT)#1; .OR.SUBSTR(SELECT,1,1)="2".AND.OCCURS(",",SELECT)#2.OR.SUBSTR(SELECT,1,1)>"4"; .OR.SUBSTR(SELECT,1,1)<"1" WAIT WINDOW AT 15,20 "输入的参数错误,请重新输入!" NOWAIT LOOP ELSE IF SUBSTR(SELECT,1,1)="4" EXIT ENDIF ENDIF IF OCCURS(",",SELECT)=1 POSITION=ATC(",",SELECT,1) AA=VAL(SUBSTR(SELECT,POSITION+1,LEN(SELECT)-POSITION)) DO (PROGNAME) WITH AA ELSE POSITION1=ATC(",",SELECT,1) POSITION2=ATC(",",SELECT,2) AA=VAL(SUBSTR(SELECT,POSITION1+1, LEN(SELECT)-POSITION1)) BB= VAL(SUBSTR(SELECT,POSITION2+1,LEN(SELECT)-POSITION2)) DO (PROGNAME) WITH AA,BB ENDIF ENDDO CLOSE PROCEDURE SET TALK &CTALK RETURN
*MYPROCED PROCEDURE PROGRAM1 PARAMETERS R S=PI()*R^2 ? "半径为"+ALLTRIM(STR(R))+"的圆的面积为:",S RETURN PROCEDURE PROGRAM2 PARAMETERS LONG,WIDTH S=LONG*WIDTH ? "长为"+ALLTRIM(STR(LONG))+"宽为"+ALLTRIM(STR(WIDTH))+; "的长方形的面积为:",S RETURN PROCEDURE PROGRAM3 PARAMETERS R N=1 T=1 DO WHILE N<=R T=T*N N=N+1 ENDDO ? "值为"+ALLTRIM(STR(R))+"的阶乘为:",T RETURN
③递归调用 在过程中不但可以调用另外一个过程,而且还可以调用自己,这就叫递归调用。 【例5-13】求一个30以内的自然数的阶乘。 *MYMAIN.PRG CTALK=SET("TALK") SET TALK OFF SET PROCEDURE TO MYSUB INPUT “请输入一个30以内的正整数:” TO NUMBER II=1 DO MYSUB WITH NUMBER,II CLOSE PROCEDURE SET TALK &CTALK RETURN *MYSUB.PRG PROCEDURE MYSUB PARAMETERS MM,NN IF MM>1 DO MYSUB WITH MM-1,NN &&递归调用。请注意同下一句的次序 NN=NN*MM &&计算乘积。 ENDIF ? STR(MM,2)+”!=”+STR(NN,10) RETURN 返 回
5.3 VFP6程序设计步骤 5.3.1 对任务进行说明 5.3.2 分解问题 5.3.3 编制模块 5.3.4 测试模块 5.3.5 组装全部模块 5.3.6 整体测试 5.3.7 提高程序的可靠性 5.3.8 将程序定义为过程或函数 返 回 退 出
也可以使用循环结构多次重复执行相同的操作。因为用以测试的字符串有固定的字符数(15),即使在表的记录中这个字段的长度不是定长,也能够使用FOR循环命令。因为FOR循环的计数器每执行一遍增1,因此,可以在SUBSTR()函数中使用该计数器。所以可以编写一个示例程序: FOR II=1 TO 15 ?? SUBSTR(cTest,II,1) ENDFOR 将此程序保存为L508.PRG后运行 运行结果 123_456_7 8 9_0 2、判断字符是否为数字 从字符串中分离出单个字符之后便可以判断它是否为数字。在命令窗口中输入如下命令: 运行结果 ? ISDIGIT(“2”) .T. ? ISDIGIT(“_”) .F. ? ISDIGIT(SUBSTR(cTest,10,1)) .F.
3、若字符为数值,将它复制到新串中 既然可以逐一检查字符是否为数值,下面可以使用内存变量来保存该数字。为了创建一个变量,需要给它赋一个初值——一个零长度的字符串。 cNumbVar=”” 因为FOR循环扫描整个字符串,所以最好用一个变量暂存每次分离出来的字符以便处理。 cCharacter=SUBSTR(cTest,II,1) 提示:在计算、求值以及在函数中得到的结果,最好保存在内存变量中,这样便于直接处理这些变量而不必重新计算或求值。 可以使用以下代码将每个被确认为数字的字符添加到新串中: cNumbVar=cNumbVar+ cCharacter cNumbVar=”” FOR II=1 TO 15 cCharacter=SUBSTR(cTest,II,1) IF ISDIGIT(cCharacter) cNumbVar=cNumbVar+ ccharacter ENDIF ENDFOR 完整的程序 返 回