1
第六章结构化程序设计目录上页下页退出
2
本 章 目 录第一节 程序文件第二节 程序的基本结构第三节 程序的模块化第四节 程序调试目录上页下页退出
3
Visual FoxPro的工作方式
Visual FoxPro系统提供有三种工作方式:即单命令方式、菜单方式及程序文件方式。
1.单命令方式
Visual FoxPro单命令方式是利用 Command 窗口来实现的。用户通过 Command 窗口输入命令,并执行操作。在 Command 窗口中,可以输入单个的操作命令和系统命令,完成对数据库的操作管理和系统环境的设置;也可以建立命令文件及运行命令文件。
Command 窗口不仅是 Visual FoxPro命令的执行窗口,也是 Visual FoxPro命令文件的编辑窗口 。
所谓单命令方式,即输入一条命令,完成一个操作的工作方式 。
目录上页下页退出
4
2.菜单方式在 Visual FoxPro 环境下,也可以通过系统提供的菜单选项,对数据库资源进行操作管理和对系统环境进行设置;并通过菜单建立命令文件及运行命令文件。所谓菜单方式,即通过打开不同的菜单选择并完成不同的操作。我们在以前各章所讲的内容其实都可说是菜单方式。
3.程序文件方式程序文件(简称程序)也叫做命令文件。运用程序文件方式进行数据库管理,是通过程序文件编辑工具,将对数据库资源进行操作管理的命令和对系统环境进行设置的命令,集中在一个以(,PRG)
为扩展名的命令文件中,然后再通过菜单方式或命令方式运行该命令文件。所谓命令方式,即通过程序文件中的命令完成不同的操作。
目录上页下页退出
5
第一节 程序文件一,Visual FoxPro程序的几点说明
1,注释语句
【 格式 1】 NOTE <注释内容 >
【 格式 2】 * <注释内容 >
【 格式 3】 && <注释内容 >
【功能】增强程序文件的易读性或放弃 <注释内容 >中语句的执行
2,对话开关语句
【 格式 】 SET TALK OFF|ON
【 功能】关闭或打开命令执行时的对话开关
3,命令的分行
Visual FoxPro程序是命令行的序列,每个命令都以回车键结束,一行只能写一条命令;若一条命令太长,一行写不下,
也可分行书写,并在分行处加上续行符,;,,再按回车键 。
目录上页下页退出
6
二、程序文件的建立、修改与执行
1.建立或修改程序文件可用以下方式调用系统内置的文本编辑器建立或修改程序文件,
1)命令方式:
MODIFY COMMAND [<盘符 >] [<路径 >]〈 程序文件名 〉

MODIFY FILE [<盘符 >] [<路径 >]〈 程序文件名 〉
2)菜单方式:
打开,文件,菜单,选择,新建,;在,新建,窗口,选择,程序,,再选择,新建文件,
目录上页下页退出
7
3)项目管理器:
选定项目管理器,代码,选项卡中的,程序,
项,选择,新建,命令 。
2,保存程序文件程序输入、编辑完毕,单击【文件】 |【保存】菜单项,或按 Ctrl+W复合键,在,另存为,对话框中指定程序文件的存放位置和文件名,并单击,保存,
按钮保存程序文件并退出文本编辑器。程序文件的默认扩展名是,PRG。
目录上页下页退出
8
3,执行程序文件程序文件建立后,可以用多种方式,多次执行它 。
下面是两种常用的方式 。
1) 菜单方式
① 单击 【 程序 】 |【 运行 】 菜单项,打开,运行,对话框;
② 从文件列表框中选择要运行的程序文件,并单击“运行”命令按钮,启动运行该程序文件
2) 命令方式
【 格式 】 DO [<盘符 >][<路径 >]<文件名 >
【功能】执行指定 <盘符 >,<路径 >下的程序文件当程序文件被执行时,文件中包含的命令将被依次执行,
直到所有命令被执行完毕,或者执行到以下命令:
目录上页下页退出
9
执行程序文件时,将依次执行文件中的命令,直到所有命令执行完毕,或者执行到以下命令:
(1) CANCAL,终止程序运行,清除所有的私有变量,
返回命令窗口;
(2) RETURN,结束程序执行,返回调用它的上级程序,
若无上级程序则返回命令窗口;
(3) QUIT,结束程序执行并退出 Visual FoxPro系统,返回操作系统
(4) DO <程序文件名 >,转去执行另一个程序。
3)项目管理器若程序包含在一个项目中,则在项目管理器中选定它并选择“运行”命令。
目录上页下页退出
10
第二节 程序的基本结构
Visual FoxPro系统提供的命令丰富,且功能强大,
把这些命令和程序设计语句有效地组织在一起,就形成了实现某一特定功能的程序。
Visual FoxPro系统的程序有两个特点:一是程序控制流模式,由顺序、分支、循环三种基本结构构成。二是面向对象可视化的结构程序模块,在每个模块的内部也是由程序控制流组成。
目录上页下页退出
11
一,结构化程序设计基础
1.原则和方法结构化程序设计是一种程序设计方法,其设计原则和方法是:自顶向下,逐步求精,程序结构模块化。
2.基本结构结构化程序由若干基本结构组成,每一个基本结构可以包含一个或多个命令,它们有以下三种基本结构。
( 1)顺序结构,如图 6-1所示,该结构先执行 A操作,再执行
B操作。
图 6-1 顺序结构流程图 图 6-2 分支结构流程图目录上页下页退出
12
( 2)分支结构:如图 6-2所示,该结构中 P代表一个条件,
当条件 P成立时执行 A操作,否则执行 B操作。
( 3)循环结构:循环结构则能够使某些语句或程序段重复执行若干次。如果某些语句或程序段需要在一个固定的位置上重复操作,使用循环是最好的选择。该结构有以下两种形式:
① 当型循环结构,如图 6-3所示。
② 直到型循环结构,如图 6-4所示 。
图 6-3 当型循环结构流程图形 图 6-4 直到型循环结构流程图目录上页下页退出
13
(4)
在许多应用程序中,有一些程序段需要反复执行多次,这些程序段不在一个固定的位置上,而是分散在程序的许多位置上重复执行,可将其与嵌入它的程序分开,
形成独立的程序序列,待使用时再调入程序中,以实现不同位置上的重复操作 。 这样做增强了程序的可读性和模块化 。 我们称这种具有独立功能而且可以被其它程序调用的程序序列为过程 。
目录上页下页退出
14
3.使用结构化程序设计的优点
(1)可读性强:每个模块功能明确、模块间的关系简单、
清晰。
(2)独立性好:每个模块内部的修改尽可能不影响其它模块。
(3)易验证:每个模块的正确性容易验证,各模块连接起来后,整个程序也便于验证。
目录上页下页退出
15
二,交互式命令
1,输入字符串语句 ACCEPT
【 格式 】 ACCEPT [<提示信息 >] TO <内存变量 >
【功能】在程序执行过程中,将用户交互式输入的内容作为字符串赋值给指定内存变量。
【说明】该命令只接受字符型数据,输入的字符串不需要加定界符 。
目录上页下页退出
16
【 例 6-2】 编程从键盘输入某数据库的文件名,要求打开该数据库并显示其内容 。
程序文件名为 PROG2.PRG。
MODI COMMAND PROG2
SET TALK OFF
CLEAR
ACCEPT,请输入数据库名:,TO AAA
OPEN DATABASE &AAA
ACCEPT "请输入表名 " TO BBB
USE &BBB
LIST
USE
SET TALK ON
RETURN
目录上页下页退出
17
2,INPUT命令
【 格式 】 INPUT [<提示信息 >] TO <内存变量 >
【功能】在程序执行过程中,将用户交互式输入的内容赋值给指定内存变量。
【说明】可以输入字符型、数值型、逻辑型、日期型和日期时间型等类型数据,而且可以是常量、
变量、函数或表达式等形式,按回车键结束输入,系统将输入的数据赋值给 <内存变量 >。
目录上页下页退出
18
【 例 6-4】 从键盘输入两个任意正数,编程求以两数为边长的长方形面积 。 程序文件名为 PROG4.PRG
SET TALK OFF
CLEAR
INPUT,长方形一边的长为:,TO A
INPUT,长方形另一边的长为:,TO B
S=A*B
“长方形的面积为:,,S
SET TALK ON
RETURN
目录上页下页退出
19
3,WAIT命令
【 格式 】 WAIT [< 提 示 信 息 > ] [ TO< 内 存 变 量 >]
[ WINDOW [AT< 行 >,< 列 > ] ] [ NOWAIT]
[CLEAR|NOCLEAR] [TIMEOUT<数值表达式 >]
【 功能 】 显示提示信息,暂停程序执行,直到用户按任意键或单击鼠标时继续执行程序 。
【 说明 】 若选择可选项 [TO <内存变量 >],将输入的单个字符作为字 符型数 据赋给 指定的 < 内存变 量 > ;
若用户是 按 Enter 键或单 击鼠标,< 内 存变 量 > 的值为空串 。
若省略所有可选项,屏幕显示,键入任意键继续 ……,默认提示信息 。
目录上页下页退出
20
【 例 6-6】 在 STUDENT数据库的 STUD表中显示任意一个系学生的情况 。 程序文件名为 PROG6.PRG
SET TALK OFF
CLEAR
OPEN DATABASE STUDENT
USE STUD
WAIT,请输入待查学生的系号 ( 1—3),,TO N
IF VAL(N)<1,OR,VAL(N)>3
WAIT,输入无效,结束程序运行 !,WINDOW TIMEOUT
5
RETURN
ELSE
STORE,0”+N TO AAA
LIST FOR 系别号 =AAA
ENDIF
CLOSE DATABASE
SET TALK ON
RETURN
目录上页下页退出
21
4,三条输入命令的异同
ACCEPT命令只能接受字符型数据,不需定界符,输入完毕按回车键结束 。
WAIT命令只能输入单个字符,且不需定界符,输入完毕不需按回车键 。
INPUT命令可接受数值型,字符型,逻辑型,日期型和日期时间型数据,数据形式可以是常量,变量,
函数和表达式,如果是字符串,需用定界符,输入完毕按回车键结束 。
目录上页下页退出
22
5.编辑修改变量语句
【格式】 @<行号,列号 > [SAY,提示信息,] [GET<变量 >]
READ
【功能】 在屏幕上或窗口中指定的坐标位置对内存变量
(它已预先赋值 )或表中当前记录的字段名变量进行编辑修改。
【说明】 @… GET语句必须与编辑修改语句 READ一起使用才有意义。当执行 READ语句时,系统将光标移到
@… GET的变量位置,这时如果从键盘上键入新的数据,则变量中原来的数据被取代目录上页下页退出
23
【例 6-7】建立程序文件,要求通过程序方式在,读者,表中添加一条新记录,程序文件名为 PROG7.PRG。
CLEAR
USE 读者
APPEND BLANK
@ 2,8 SAY "读者基本情况输入界面,"
@ 4,10 SAY "读者编号," GET 读者编号
@ 6,10 SAY "读者姓名," GET 姓名
@ 8,10 SAY "读者性别," GET 性别
@ 10,10 SAY "出生日期," GET 出生日期
@ 12,10 SAY "少数民族否," GET 少数民族否
@ 14,10 SAY "籍贯 " GET 籍贯
READ
USE
目录上页下页退出
24
【例 6-8】编写程序文件 PROG8.PRG,修改读者表中第三条记录的姓名和籍贯两个字段。
SET TALK OFF
USE 读者
GO 3
@2,20 SAY,姓名,GET 姓名
@4,20 SAY "籍贯 " GET 籍贯
READ
DISPLAY
USE
RETURN
目录上页下页退出
25
分支结构形式有如下三种:
1
单向分支语句,即根据用户设置的条件表达式的值,
决定某一操作是否执行 。
【 语句 格式 】
IF〈 条件表达式 〉
〈 命令行序列 〉
ENDIF
【 语句功能 】
该语句首先计算 〈 条件表达式 〉 的值,当 〈 条件表达式 〉 的值为真时,执行 〈 命令行序列 〉 ;否则,执行
ENDIF后面的第一条命令 。
三、分支结构条件式达式真语句序列假
E N D IF 之后语句目录上页下页退出
26
【 例 6-9】 求一元二次方程 AX2+ BX+ C= 0的实根 。
程序文件名为 PROG9.PRG。
SET TALK OFF
CLEAR
INPUT TO A
INPUT TO B
INPUT TO C
Z= B^2-4*A*C
IF Z>=0
X1=(-B+SQRT(Z))/(2*A)
X2=(-B-SQRT(Z))/(2*A)
X1,X2
ENDIF
SET TALK ON
RETURN
目录上页下页退出
27
2,双向分支双向分支语句,即根据用户设置的条件表达式的值,选择两个操作中的一个来执行 。
【 语句 格式 】
IF〈 条件表达式 〉
〈 命令行序列 1〉
ELSE
〈 命令行序列 2〉
ENDIF
【 语句功能 】
该语句首先计算 〈 条件表达式 〉 的值,当 〈 条件表达式 〉 的值为真时,执行 〈 命令行序列 1〉 中的命令;
否则,执行 〈 命令行序列 2〉 中的命令;执行完 〈 命令行序列 1〉 或 〈 命令行序列 2〉 后都将执行 ENDIF后面的第一条命令 。
真条件式假语句序列 2 语句序列 1
EN D IF 后面语句目录上页下页退出
28
【 例 6 -10】 编写一密码校验程序 ( 假设密码为
ABC) 。 程序文件名为 PROG10.PRG。
SET TALK OFF
CLEAR
ACCEPT,请输入您的密码:,TO AAA
IF AAA=”ABC”
CLEAR
”欢迎使用本系统 !,
ELSE
”密码错误 !,
WAIT
QUIT
ENDIF
SET TALK ON
目录上页下页退出
29
3.
多向分支语句,即根据多个条件表达式的值,选择执行多个操作中的一个对应执行 。
【 语句 格式】
DO CASE
CASE〈 条件表达式 1〉
<命令行序列 1〉
CASE〈 条件表达式 2〉
<命令行序列 2
… …
CASE〈 条件表达式 N〉
命令行序列 N
[ OTHERWISE
〈 命令行序列 N+1〉]
ENDCASE
真条件式 2
语句序列 1
EN D CA SE 后面语句条件式 1
O th e rw is e
条件式 2
真语句序列 2
真语句序列 n - 1
有语句序列 n
无目录上页下页退出
30
【 语句功能 】
该语句根据给出的 N个 〈 条件表达式 〉 的值,选择 N+1个 〈 命令行序列 〉 中的一个执行 。 当所有 CASE
中 〈 条件表达式 〉 的值都是假时,如果有 OTHERWISE
项,则执行 〈 命令行序列 N+1〉,再执行 ENDCASE后面的第一条命令;否则,直接执行 ENDCASE后面的第一条命令 。
【 例 6-11】 假设收入 ( P) 与税率 ( R) 的关系如下表,
编程求税金 。 程序文件名为 PROG11.PRG。
0 P< 800
R= 0.05 800 ≤ P< 2000
0.08 2000≤P< 5000
0.1 P≥5000
目录上页下页退出
31
SETTALK OFF
CLEAR
INPUT,请输入收入:,TO P
DO CASE
CASE P<800
R=0
CASE P<2000
R=0.05
CASE P<5000
R=0.08
OTHERWISE
R=0.1
ENDCASE
TAX=P*R
,税金为:,,TAX
SETTALK ON
RETURN
目录上页下页退出
32
4,使用分支语句应注意的几点
( 1) IF… … ENDIF和 DO CASE… … ENDCASE 必须配对使用,DO CASE与第一个 CASE(条件表达式 )之间不应有任何命令 。
( 2) (条件表达式 )可以是各种表达式或函数的组合,其值必须是逻辑值 。
( 3) (命令行序列 )可以由一个或多个命令组成,可以是条件控制语句组成的嵌套结构 。
( 4) DO CASE… … ENDCASE 命令,每次最多只能执行一个 (命令行序列 )。 在多个 CASE项的 (条件表达式 〉
值为真时,只执行第一个 (条件表达式 )值为真的 (命令行序列 ),然后执行 ENDCASE的后面的第一条命令 。
目录上页下页退出
33
四、循环结构
1,DO WHILE循环语句
【 格式 1】 DO WHILE <条件表达式 >
<语句序列 >
ENDDO
END DO 后面的语句条件表达式式真循环体假一个循环结构一般应具备如下的条件:
( 1) 循环的初始条件:一般为给循环控制变量赋初值;
( 2) 循环头:循环语句的起始,设置,判断循环条件;
( 3) 循环尾:循环语句的结尾;
( 4)循环体:位于循环头和循环尾之间、循环控制重复执行的语句序列。
目录上页下页退出
34
【 格式 2】 DO WHILE <条件表达式
>
<语句序列 1>
[LOOP]
<语句序列 2>
[EXIT]
<语句序列 3>
ENDDO
E N D DO 后面的语句条件表达式式真假循环体
[ L O O P ]
[ E X I T ]
LOOP语句:强行返回到循环开始语句 。
EXIT语句:强行跳出循环,接着执行 ENDDO后的语句目录上页下页退出
35
【 例 6-12】 编程求 1+ 2+ 3+ …… + 100之和 。
程序文件名为 PROG12.PRG。
SET TALK OFF
CLEAR
S=0
I=1
DO WHILEI<=100
S=S+I
I=I+1
ENDDO
”1+ 2+ 3+ …… + 100=,,S
SET TALK ON
RETURN
目录上页下页退出
36
【 例 6-13】 逐条显示在 STUDENT数据库的 STUD表中性别为,男,的所有记录 。 程序文件名为 PROG13.PRG。
SET TALK OFF
CLEAR
OPEN DATABASE STUDENT
USE STUD
DO WHILE,NOT,EOF()
IF 性别 =” 男,
DISPLAY
ENDIF
SKIP
ENDDO
CLOSE DATABASE
SET TALK ON
RETURN
目录上页下页退出
37
【 例 6-14】 编程显示 STUDENT数据库的 STUD表中除
,李宁,以 外 的 所 有 记 录 。 程 序 文 件 名 为
PROG14.PRG。
SET TALK OFF
CLEAR
OPEN DATABASE STUDENT
USE STUD
DO WHILE,NOT,EOF()
IF 姓名 =” 李宁,
SKIP
LOOP
ENDIF
DISPLAY
SKIP
ENDDO
CLOSE DATABASE
SET TALK ON
RETURN
目录上页下页退出
38
2,FOR循环语句
【 格式 】
FOR <循环变量 >=<初值 > TO <终值 > [STEP<步长 >]
<语句序列 1>
[LOOP]
<语句序列 2>
[EXIT]
<语句序列 3>
ENDFOR/NEXT
FOR语句的执行流程如右图所示 。
目录上页下页退出
39
使用 FOR循环语句的有关说明:
① 省略 STEP <步长 >,则 〈 步长 〉 为默认值 1;
② 〈 初值 〉,〈 终值 〉 和 〈 步长 〉 都可以是数值表达式,但这些表达式仅在循环语句开始执行时计算一次 。 循环语句执行过程中,初值,终值和步长是不会改变的,并由此确定循环的次数;
③ 可以在循环体内改变循环变量的值,但会改变循环执行次数;
④ EXIT和 LOOP命令可以出现在循环体内。执行 LOOP
命令时,结束本次循环,循环变量增加一个步长值,
返回 FOR循环头判断循环条件是否成立。执行 EXIT
命令时,程序跳出循环,执行循环尾后面的语句 。
目录上页下页退出
40
【 例 6-15】 从键盘输入 10个数,编程找出其中的最大值和最小值 。 程序文件名为 PROG15.PRG。
SET TALK OFF
CLEAR
INPUT,请从键盘输入一个数:,TO A
STORE A TO MAX,MIN
FOR I=2 TO 10
INPUT,请从键盘输入一个数:,TO A
IF MAX<A
MAX=A
ENDIF
IF MIN>A
MIN=A
ENDIF
ENDFOR
,最大值为:,,MAX
,最小值为:,,MIN
SET TALK ON
RETURN
目录上页下页退出
41
【例 6-16】 编程判断一个数是否素数,程序文件名为
PROG16.PRG。
SET TALK OFF
CLEAR
INPUT "请输入一个数," TO x
FOR i=2 TO x-1
IF Mod(x,i)=0
EXIT
ENDIF
ENDF
IF i>=x
STR(X)+“是素数,
ELSE
STR(X)+"不是素数 "
ENDIF 程序 N-S流程图目录上页下页退出
42
【例 6-17】从键盘输入任意的 10个数,按从大到小的顺序依次输出,程序文件名为 PROG17.PRG。
DIME A(10)
FOR i=1 TO 10
INPUT "请输入一个数 " TO a(i)
a(i)
ENDFOR
FOR i=1 TO 9
FOR j=1 TO 10-i
IF a(j)<a(j+1)
t=a(j)
a(j)=a(j+1)
a(j+1)=t
ENDIF
ENDFOR
ENDFOR
FOR i=1 TO 10
a(i) 程序 N-S流程图
ENDFOR
目录上页下页退出
43
3.,指针,型循环控制语句
,指针,型循环控制语句,即根据用户设置的表中的当前记录指针,决定循环体内语句的执行次数据 。
【 语句 格式 】
SCAN[〈 范围 〉] [ FOR〈 条件表达式 1〉
[ WHILE 〈 条件表达式 2〉 ]]
〈 命令行序列 〉
ENDSCAN
【 语句 功能】
该语句在指定的范围内,用数据记录指针来控制循环次数。执行语句时,首先判断函数 EOF() 的值,
若其值为,真,,则结束循环,否则,结合 (条件表达式 1)或 (条件表达式 2),执行 (命令行序列 ),记录指针移到指定的范围和条件内的下一条记录,重新判断函数 EOF( )的值,直到函数 EOF( )的值为真时结束循环。
目录上页下页退出
44
【 例 6-18】 输出 STUDENT数据库的 STUD表中所有团员的姓名和地址 。 程序文件名为 PROG18.PRG。
SET TALK OFF
CLEAR
OPEN DATABASE STUDENT
USE STUD
SCAN FOR 是否团员姓名,地址
ENDSCAN
CLOSE DATABASE
SET TALK ON
RETURN
目录上页下页退出
45
4,使用循环语句时应注意的几点
( 1 ) DO WHILE 和 ENDDO,FOR 和 ENDFOR,SCAN 和
ENDSCAN必须配对使用 。
( 2) 〈 命令行序列 〉 可以是任何 FoxPro命令或语句,
也可以是循环语句,即可以为多重循环 。
( 3) 〈 循环变量 〉 应是数值型的内存变量或数组元素 。
( 4) EXIT和 LOOP命令嵌入在循环体内,可以改变循环次数,但是不能单独使用 。 EXIT的功能是跳出循环,转 去 执 行 ENDDO,ENDFOR,ENDSCAN后 面 的 第一条命令; LOOP的功能是转回到循环的开始处,
重新对,条件,进行判断,相当于执行了一次
ENDDO,ENDFOR,ENDSCAN命令,它 可 以 改 变 〈 命令行序列 〉 中部分命令的执行次数 。 EXIT,LOOP
可以出现在 〈 命令行序列 〉 的任意位置 。
目录上页下页退出
46
5,多重循环多重循环即循环的嵌套,是在一个循环结构的循环体中又包含另一个循环 。 我们称外层循环为外循环,
被包含的循环为内循环 。 嵌套层数一般没有限制,但内循环的循环体必须完全包含在外循环的循环体中,
不能相互交叉 。 正确的嵌套关系如:
DO WHILE <条件表达式 1>
<语句序列 11>
DO WHILE <条件表达式 2>
<语句序列 21>
DO WHILE <条件表达式 3>
<语句序列 3>
ENDDO
<语句行序列 22>
ENDDO
<语句行序列 12>
ENDDO
目录上页下页退出
47
【 例 6-19】 编程输出下三角形乘法口诀表 。 程序文件名为 PROG19.PRG。
SET TALK OFF
CLEAR
X=1
DO WHILE X<=9
Y=1
DO WHILE Y<=X
S=X*Y
STR(Y,1)+”*”+STR(X,1)+”=”+STR(S,2)+”,
Y=Y+1
ENDDO
X=X+1
ENDDO
SET TALK ON
RETURN
目录上页下页退出
48
第三节 过程的模块化结构化程序设计方法要求将一个大的系统分解成若干个子系统,每个子系统就构成一个程序模块。模块是一个相对独立的程序段,它可以为其他模块所调用,也可以去调用其他模块。将一个应用程序划分成一个个功能相对简单、单一的模块程序,不仅有利于程序的开发,也有利于程序的阅读和维护。 VFP模块化在具体实现上提供三种形式,它们是子程序、过程和函数。
主程序与子程序调用关系示意图目录上页下页退出
49
一、子程序子程序也叫外部过程,是以程序文件(,PRG) 的形式单独存储在磁盘上。子程序只需录入一次,就可反复被调用执行 。
1.子程序的结构在 VFP中,子程序的结构与一般的程序文件一样,
可以用 MODIFY COMMAND命令来建立、修改、和存盘,扩展名也默认为,PRG。
子程序与其他程序文件的唯一区别是其末尾或返回处必须有返回语句 RETURN。
【 语句 格式】
RETURN [TO MASTER|TO 程序文件名 |表达式 ]
【 语句 功能】该命令中止一个程序、过程、或用户自定义函数的执行,返回上一级调用程序、最高级调用程序、
另外一个程序或命令窗口。
目录上页下页退出
50
【 语句 说明】
( 1)通常程序执行到 RETURN时,会自动返回到上级调用程序调用语句的下一条语句继续执行。如果是在最高一级主程序中,则返回命令窗口。
( 2)选用 TO MASTER 子句时,则返回最高一级调用程序,即在命令窗口下,调用的第一个主程序。
( 3) TO 程序文件名表示程序将转向到指定的程序。
( 4)如选用表达式,表示将表达式的值返回调用程序,
通常用于自定义函数。
( 5) 在程序最后,如果没有 RETURN命令,则程序运行完毕后,将自动默认执行一个 RETURN命令,但过程文件除外。
目录上页下页退出
51
2.子程序的调用:
【 语句 格式】
DO <程序文件名 >|<过程名 >[ WITH 参数表]
【 语句 功能】 执行以 <程序文件名 >或 <过程名 >为名的过程。
【 语句 说明 】 WITH参数表子句用来指定传递到程序或过程的参数,在参数表中列出的参数可以是表达式、内存变量、
常量、字段名或用户自定义函数,各参数间用逗号分隔。
【例 6-20】分别建立如下程序文件。
* MAIN.PRG
SET TALK OFF
,正在执行主程序,
DO SUB1
SET TALK ON
*SUB1.PRG
,正在执行 SUB1”
RETURN
目录上页下页退出
52
【例 6-21】 利用子程序方法求 M! /(N! *( M-N)! )( M>N)
*main.prg *子程序 sub1.prg
INPUT "请输入 M," TO m s=1
INPUT "请输入 N," TO n FOR i=1 TO x
s=0 s=s*i
x=m ENDFOR
DO sub1 RETURN s
s2=s
x=n
DO sub1
s3=s
x=m-n
DO sub1
s4=s
s1=s2/(s3*s4)
s1
目录上页下页退出
53
二、过程 (内部 )
内部过程:把多个过程组织在一个文件中 (这个文件称之为过程文件 ),或者把过程放在调用它的程序文件的末尾。
Visual FoxPro为了识别过程文件或者程序文件中的不同过程,
规定过程文件或者程序文件中的过程必需用 PROCEDURE语句说明。其格式为:
PROCEDURE <过程名 >
[PARAMETER <参数表 >]
<命令序列 >
[RETURN [<表达式 >]]
过程有两种存放方式:
( 1)把所有的过程集中写入一个被称为过程文件(,prg文件)
的磁盘文件中
( 2)直接把过程写在调用它的主程序文件中,主程序被打开时,
过程同时被调入内存。
目录上页下页退出
54
1.过程写在过程文件里主程序与过程的相互关系如下图所示。
调用过程之前,首先要打开存放该过程的过程文件,任何时候只能打开一个过程文件。
打开过程文件的命令:
SET PROCEDURE TO <过程文件名 >
关闭过程文件的命令:
SET PROCEDURE TO 或用,CLOSE PROCEDURE
目录上页下页退出
55
2.过程与主程序写在同一个程序文件里主程序与过程的相互关系如下图所示。
过程和子程序都是用 DO<文件名 >来调用,当出现了同名的过程和子程序时,调用的顺序首先从过程与主程序在同一文件中调用,其次从过程文件中调用,最后从子程序中调用。
目录上页下页退出
56
【 例 6-22】 建立如下程序文件,过程放在程序文件中 。
* MAIN.PRG
SET TALK OFF
,正在执行主程序,
DO SUB1
SET TALK ON
Procedure SUB1
,正在执行 SUB1”
RETURN
目录上页下页退出
57
【例 6-22】请考察下述程序运行流向,求出正确运行结果。
*prog22.prg
CLEAR
STORE 2 TO I,C,T
DO WHILE I<=4
DO PR
" F("+STR(I,1)+ ")="+STR(C,2)
I=I+1
ENDDO
"T="+STR(T,2)
RETURN
PROCEDURE PR
C=C+2
T=T+C
RETURN
目录上页下页退出
58
三、过程文件的建立过程文件的建立方法与程序文件相同 。 可用
MODIFY COMMAND <过程文件名 >命令或调用其他文字编辑软件来建立 。
过程文件的结构一般为:
PROCEDURE <过程名 1>
<命令序列 1>
RETURN
PROCEDURE <过程名 2>
<命令序列 2>
RETURN

PROCEDURE <过程名 N>
<命令序列 N>
RETURN
目录上页下页退出
59
1,过程文件的调用调用某过程文件中的过程时,必须先打开该过程文件,
打开过程文件命令为:
【 格式 】 SET PROCEDURE TO <过程文件名 >
任何时候系统只能打开一个过程文件,当打开一个新的过程文件时,原已打开的过程文件自动关闭 。
2,过程文件的关闭关闭过程文件可用下列命令:
【 格式一 】 SET PROCEDURE TO
【 格式二 】 CLOSE PROCEDURE
目录上页下页退出
60
【例 6-23】用过程文件实现对 STUDENT数据库的 STUD表进行查询、删除和插入操作。
主程序如下:
* PROG23 && 主程序文件名
SET TALK OFF
CLEAR
OPEN DATABASE STUDENT
SET PROCEDURE TO PROCE && 打开过程文
USE STUD
INDEX ON 姓名 TO XM
DO WHILE,T,&& 显示菜单
CLEAR
@ 2,20 SAY,学籍管理系统,
@ 4,20 SAY,A:按姓名查询,
@ 6,20 SAY,B:按记录号删除,
目录上页下页退出
61
@ 8,20 SAY,C:插入新的记录,
@ 10,20 SAY,D:退出,
CHOISE=””
@ 12,20 SAY,请选择 A,B,C,D:,GET CHOISE
READ
DO CASE
CASE CHOISE=”A”
DO PROCE1
CASE CHOISE=”B”
DO PROCE2
CASE CHOISE=”C”
DO PROCE3
CASE CHOISE=”D”
EXIT
ENDCASE
ENDDO
SET PROCEDURE TO && 关闭过程文件
CLOSE DATABASE
SET TALK ON
目录上页下页退出
62
过程文件如下:
*PROCE.PRG && 过程文件名
PROCEDURE PROCE1 && 查询过程
CLEAR
ACCEPT,请输入姓名:,TO NAME
SEEK NAME
IF FOUND()
DISPLAY
ELSE
,查无此人,
ENDIF
WAIT
RETURN
目录上页下页退出
63
PROCEDURE PROCE2 && 删除记录过程
CLEAR
INPUT,请输入要删除的记录号,” TO N
GO N
DELETE
WAIT,物理删除吗 Y/N:” TO FLAG
IFFLAG=”Y”,OR.,y”
PACK
ENDIF
RETURN
PROCEDURE PROCE3 && 插入新的记录过程
CLEAR
APPEND
RETURN
目录上页下页退出
64
四、自定义函数自定义函数和过程一样,可以以独立的程序文件形式单独存储在磁盘上,也可以放在过程文件或直接放在程序文件中。
自定义函数具有如下语法结构:
FUNCTION <函数名 >
PARAMETER <参数表 >
<函数体命令序列 >
RETURN <表达式 >
自定义函数的调用语法与系统函数的调用相同 。 和过程一样,自定义函数可以是常规程序文件的一部分,
也可以是独立的程序文件 。 不同的是调用过程或子程序使用 DO命令,调用函数名称后面加上括号 。 注意:函数不是命令,函数调用只能出现在表达式中 。
目录上页下页退出
65
【 例 6-24】 计算圆面积
*PROG24.PRG
SET TALK OFF
CLEAR
INPUT,请输入圆的半径,” TO R
,圆的面积为,”,AREA(R)
SET TALK ON
FUNCTION AREA && 计算面积的函数
PARAMETER X && 形参说明
RETURN (3.1416*X**2)
目录上页下页退出
66
【例 6-25】利用自定义函数编程求一元二次方程的实根。
*prog25.prg FUNCTION root
INPUT "a=" TO a PARAMETERS a,b,c
INPUT "b=" TO b d=b*b-4*a*c
INPUT "c=" TO c IF d>=0
k=root(a,b,c) d=sqrt(d)
IF k>=0 ENDIF
"x1=",(-b+k)/(2*a) RETURN d
"x2=",(-b+k)/(2*a)
ELSE
? "方程无实根 "
ENDIF
目录上页下页退出
67
五、过程调用中的参数传递
1,有参过程中的形式参数定义有参过程中的形式参数定义语句为:
【 格式 】 PARAMETERS <参数表 >
该语句必需是过程中第一条语句。 <参数表 >中的参数可以是任意合法的内存变量名 。
2,程序与被调用过程间的参数传递程序与被调用过程间的参数传递是通过过程调用语句 DO <过程名 > WITH <参数表 >中 WITH <
参数表 >子句来实现的 。
目录上页下页退出
68
【 说明 】
( 1 ) DO 命令 < 参 数 表 > 中 参 数 称 为 实 际 参 数,
PARAMATERS命令 <参数表 >中的参数称为形式参数 。
两个 <参数表 >中的参数必须相容,即个数相同,类型和位置一一对应;
( 2) 实际参数可以是任意合法表达式,形式参数是过程中的局部变量,用来接收对应实际参数的值;
( 3) Visual FoxPro的参数传递规则为:如果实际参数是常数或表达式则传值,如果实际参数是变量则传址,即传递的不是实参变量的值而是实参变量的地址,这样,
过程中对形参变量值的改变也将使实参变量值改变。如果实参是内存变量而又希望进行值传递,可以用圆括号将该内存变量括起来,强制该变量以值方式传递数据目录上页下页退出
69
【 例 6-26】 用参数传递编程,计算圆的面积 。
* 主程序名 PROG26.PRG
SET TALK OFF
CLEAR
S=0
INPUT,请输入圆的半径,” TO R
DO AREA WITH R,S
,圆的面积为,”,S
SET TALK ON
PROCEDURE AREA && 计算面积的过程
PARAMETER X,Y && 形参说明
Y=3.1416*X**2
RETURN
目录上页下页退出
70
六、过程的嵌套调用
Visual FoxPro中允许一个过程调用第二个过程,第二个过程又可调用第三个过程,……,这种调用关系称为过程的嵌套调用 。
DO< 过程 A>
RE T U RN,
DO< 过程 B>
RE T U RN,
DO< 过程 C>
RE T U RN
,
,RE T U RN

… … …
… …


主程序 过程 A 过程 B 过程 C
目录上页下页退出
71
七、过程的递归调用
Visual FoxPro 允许递归调用,所谓递归调用,即某一过程直接或间接调用自己。过程直接调用自己称为直接递归(见图),间接调用自己称为间接递归 。
过程 A 过程 A
过程 A 过程 B 过程 A
目录上页下页退出
72
【 例 6-27】 编程用递归方法求 N的阶乘 。 程序文件名为
PROG27.PRG。
SET TALK OFF
CLEAR
INPUT,请输入 N:” TO N
Y=1
DO PROCE1 WITH N,Y
STR(N,2)+”!=”,Y
SET TALK ON
PROCEDURE PROCE1 && 求阶乘的过程
PARAMETER X,Y
IF X>1
DO PROCE1 WITH X-1,Y && 递归调用
Y=X*Y
ENDIF
RETURN
目录上页下页退出
73
八、变量的作用域
1.公共 (全局 )变量公共变量是指在所有程序模块中都有效的内存变量。
在程序或过程中定义公共变量的语句为:
【格式】 PUBLIC <内存变量表 >
该命令的功能是建立公共变量,并为它们赋初值为逻辑假,F.
例如,PUBLIC a,b,c(5)建立了三个公共内存变量,它们的初值都是,F,
在命令窗口直接使用的内存变量(不必用 PUBLIC定义)都是全局变量。
目录上页下页退出
74
【 说明 】
( 1) 当定义多个变量时,各变量名之间用逗号隔开;
( 2) 用 PUBLIC语句定义过的内存变量,在程序执行期间可以在任何层次的程序模块中使用;
( 3) 变量定义语句要放在使用此变量的语句之前,否则会出错;
( 4) 任何已经定义为全局变量的变量,可以用
PUBLIC语句再定义,但不允许重新定义为局部变量;
( 5)使用全局变量可以增强模块间的通信,但会降低模块间的独立性。
目录上页下页退出
75
2,私有变量在程序中直接使用(没有通过 PUBLIC和
LOCAL命令事先声明)而由系统自动隐含建立的变量都是私有变量。私有变量的作用域是建立它的模块及其下属各层模块,一旦建立它的模块运行结束,这些私有变量将自动清除。
3,局部变量局部变量只能在定义它的模块中使用,不能在上层或下层模块中使用。当定义它的模块运行结束时,局部变量自动释放。局部变量用 LOCAL命令建立:
【格式】 LOCAL <内存变量表 >
【功能】该命令建立指定的局部内存变量,并为它们赋初值为逻辑假,F.。
目录上页下页退出
76
【例 6-28】 分析下面程序中变量的作用域
*prog28.prg
PUBLIC x1 &&建立公共变量 X1
LOCAL x2 &&建立局部变量 X2
STORE "f" TO x3 &&建立私有变量 X3
DO proc1
"主程序中 --" &&三个变量在主程序中都可使用
? "x1=",x1
? "x2=",x2
? "x3=",x3
RETURN
PROCEDURE proc1
,子程序中 --” &&公共变量和私有变量在子程序中可以使用
? "x1=",x1
? "x3=",x3
RETURN
目录上页下页退出
77
4.变量的隐藏根据结构化程序设计方法,将应用程序分成若干层不同的模块,有可能在各层模块中有变量同名的情况。
为了解决此问题,可以在子程序中使用 PRIVATE命令隐藏主程序中可能存在的变量,使得这些变量在子程序中暂时无效。其语法格式为:
PRIVATE 内存变量表 | ALL [LIKE 通配符 ][EXCEPT
通配符 ]
该命令并不建立内存变量,它的作用是:隐藏指定的上层模块中可能已经存在的内存变量,使得这些变量在当前模块程序中暂时无效。于是这些变量名就可以用来命名在当前模块或其下属模块中需要的私有变量或局部变量,并且不会改变上层模块中同名变量的取值。
目录上页下页退出
78
【例 6-29】 变量的隐藏示例。
*prog29.prg *过程 P
SET TALK OFF PROCEDURE p
x=10 PRIVATE x
y=15 x=50
DO p y=100
x,y? x,y
RETURN
运行结果:
50 100
10 100
目录上页下页退出
79
【例 6-30】 LOCAL 和 PRIVATE 命令的比较示例
*prog30.prg
PUBLIC x,y
X=10
Y=100
DO p1
x,y &&显示 10 bbb
*过程 P1
PROCEDURE p1
PRIVATE x && 隐藏上层模块中的变量 x
x=5 && 建立私有变量 x,并赋值 5
LOCAL y && 建立局部变量 y,并隐藏同名变量
DO p2
x,y && 显示 aaa,F.
*过程 P2
PROCEDURE P2
x="aaa" && x是在 P1中建立的内存变量
y="bbb" && y是在主程序中建立的公共变量
RETURN
目录上页下页退出
80
第四节 程序调试程序调试是指在发现程序有错误的情况下,确定出错的位置并加以改正,直至满足设计要求。程序调试往往是先分模块调试,当各模块都调试通过以后,
再将各模块联合起来进行调试,通过联调后,便可试运行,试运行无误后即可投入正常使用。
程序的错误通常有两类:语法错误和逻辑错误。
语法错误相对容易发现和修改,当程序运行到这类错误时,VFP会自动中断程序的执行,并弹出编辑窗口,
显示出错的命令行,给出出错信息,这时可以方便地修改错误。逻辑错误系统是无法确定,只能用户自已来查错。往往需要跟踪程序的执行,在动态执行过程中监视并找出程序中的错误。
目录上页下页退出
81
一、建立测试环境
1,硬件和软件问题为了获得最大的可移植性,应当在预期运行的最底层平台上开发应用程序 。 要保证应用程序能在满足最低要求的平台上正常工作,应该做到以下几点:
( 1) 使用最低层常用的视频方式开发应用程序 。
( 2) 确定最低所需的RAM以及存储介质的空间大小,
其中应包括必需的驱动程序以及同时运行的软件所占用的空间 。
( 3)对于应用程序的网络版,还应考虑内存、文件和记录锁定特殊要求。
目录上页下页退出
82
2,系统路径和文件属性为了在运行应用程序的每台机器上都能够快速访问所有必需程序文件,可能需要确定一个基本文件配置 。
在定义基本配置时,应考虑下列问题:
( 1) 应用程序是否需要公用系统路径 。
( 2) 设置的文件存取属性是否合适 。
( 3)为每个用户设置的网络权限是否正确。
目录上页下页退出
83
3,目录结构和文件位置如果源代码引用的是绝对路径或文件名,那么当应用程序安装到任何其他机器上时必须存在相同的路径和文件 。 若要避免这一情况,可采用以下方法:
( 1) 使用 Visual FoxPro配置文件 。
( 2) 另建一个目录或目录结构,将源文件和生成的应用程序文件分开 。 这样就可以对应用程序的相互引用关系进行测试,并且准确地知道在发布应用程序时应包含哪些文件 。
( 3)使用相对路径。
目录上页下页退出
84
二,设置验证的内容
在代码中可以包含验证的内容,其作用是验证代码运行环境的假设情况 。
若要设置验证的内容,使用 ASSERT命令标明程序中的假设 。
当 ASSERT命令中所规定的条件为,假,(,F.) 时,将显示一个提示信息对话框,同时在,调试输出,窗口中反映出来 。
例如,可以编写一个函数,函数需要一个非0的参数值。
如果参数为0时,下面的函数代码将提醒用户:
ASSERT nParm!=0 MESSAGE“接受的参数数值为 0” 。
可以使用 SET ASSERTS命令指定是否显示提示信息,
默认情况下,不显示提示信息 。
目录上页下页退出
85
三、在调试器中调试程序
1.打开调试器选择 【 工具 】 |【 调试器 】 命令 。,调试器,窗口是一个独立运行的窗口,它有自己的菜单和工具栏,
在,调试器,窗口中可有选择地打开 5个子窗口:跟踪,监视,
局部,调用堆栈和调试输出 。 如图所示目录上页下页退出
86
2,跟踪代码在调试中,最有用的方法就是跟踪代码,以此观察每一行代码的运行,同时检查所有的变量、属性和环境设置值,如图所示。
1、如果“跟踪
”窗口没有打开
,在调试窗口的菜单栏中选择【
窗口】 |【跟踪
】命令
2、在调试窗口的菜单栏中选择【
调试】 |【运行】
命令。打开要调试的程序
3、在调试窗口的菜单栏中选择【调试】 |【单步】命令(或 F6键),或选择【调试】 |【单步跟踪】命令(
F8键)
目录上页下页退出
87
3,设置断点
( 1) 在特定代码行设置断点在,跟踪,窗口中,找到需要设置断点的那一行,并将光标放置在该代码行上
按下 F9键或者单击,调试器,工具栏上的,切换断点,按扭 。
或者双击该行代码行左边的灰色区域,该代码行左边的灰色区域中会显示一个实心点,这表明在该行已经设置一个断点 。
如果正在调试对象,那么,通过从对象列表中选择对象,从过程列表中选择所需方法程序或事件,就可以在,跟踪,窗口中找到特定的代码行 。
目录上页下页退出
88
( 2)在文件指定位置设置断点在调试窗口中选择【工具】 |【断点】命令,打开
“断点”对话框 。
1、在“类型”列表框中选择“在定位处中断”
2、在“定位”和“文件
”输入框中指定所需断点的位置和文件来设置断点目录上页下页退出
89
4,移去断点
在“断点”对话框中,单击断点列表框中某断点左侧的复选框可使该断点无效,单击
“删除”按钮可删除选定的断点。
在“跟踪”窗口中,双击断点标记可以删除该断点。
目录上页下页退出
90
5,查看存储元素的值
( 1) 在,局部,窗口中查看变量的值
“局部”窗口会显示调用堆栈上的任意程序、过程或方法程序里所有的变量、数组、对象和对象元素,如图所示。默认情况下,在“局部”窗口中所显示的是当前执行程序中的变量值。
通过在“位置”列表中选择程序或过程,也可以查看其他程序或过程中的变量值目录上页下页退出
91
( 2)在“监视”窗口中查看变量的值在“监视”窗口的“监视”框中,键入任意一个有效的 Visual FoxPro表达式,然后按下回车键。这时,该表达式的值和类型就会出现在“监视”窗口的列表中。
如图所示,
若要从“监视”窗口中移去某监视项
,选择该项,然后按 DEL键;或者从快捷菜单中,选择“删除监视”
目录上页下页退出
92
( 3)在“跟踪”窗口中查看变量值在“跟踪”窗口中,将光标定位到任何一个变量、
数组或属性上,就会出现提示条,并显示它的当前值目录上页下页退出
93
6.查看事件发生的序列若要跟踪事件,可按如下操作:
在调试窗口的菜单中选择【工具】 |【事件跟踪】命令。
打开如图所示的跟踪对话框。
1、选择要跟踪的事件:系统默认的跟踪事件为 Visual
FoxPro系统定义的所有事件
,用户可从“跟踪事件”列表中选择不跟踪的事件,并单击中部的左箭头按钮将其加入“可用事件”列表中
2、启动事件跟踪:选中“
开启事件跟踪”复选框,
便可激活事件跟踪3、选择跟踪输出去向
94
结 束