670 likes | 776 Views
第四章 程序设计基础. 本 章 要 点. 程序 文件 程序的 控制结构 多模块程序 窗口设计 样例. Visual FoxPro 的工作方式. Visual FoxPro 系统提供有三种工作方式:即单命令方式、菜单方式及程序文件方式。 1. 单命令方式 Visual FoxPro 单命令方式是利用 Command 窗口来实现的。用户通过 Command 窗口输入命令,并执行操作。在 Command 窗口中,可以输入单个的操作命令和系统命令,完成对数据库的操作管理和系统环境的设置;也可以建立命令文件及运行命令文件。
E N D
本 章 要 点 • 程序文件 • 程序的控制结构 • 多模块程序 • 窗口设计样例
Visual FoxPro的工作方式 Visual FoxPro系统提供有三种工作方式:即单命令方式、菜单方式及程序文件方式。 1.单命令方式 Visual FoxPro单命令方式是利用Command 窗口来实现的。用户通过Command 窗口输入命令,并执行操作。在Command 窗口中,可以输入单个的操作命令和系统命令,完成对数据库的操作管理和系统环境的设置;也可以建立命令文件及运行命令文件。 Command 窗口不仅是Visual FoxPro命令的执行窗口,也是Visual FoxPro命令文件的编辑窗口。 所谓单命令方式,即输入一条命令,完成一个操作的工作方式。 要 点
2.菜单方式 在Visual FoxPro 环境下,也可以通过系统提供的菜单选项,对数据库资源进行操作管理和对系统环境进行设置;并通过菜单建立命令文件及运行命令文件。所谓菜单方式,即通过打开不同的菜单选择并完成不同的操作。我们在以前各章所讲的内容其实都可说是菜单方式。 3.程序文件方式 程序文件(简称程序)也叫做命令文件。运用程序文件方式进行数据库管理,是通过程序文件编辑工具,将对数据库资源进行操作管理的命令和对系统环境进行设置的命令,集中在一个以(.PRG)为扩展名的命令文件中,然后再通过菜单方式或命令方式运行该命令文件。所谓命令方式,即通过程序文件中的命令完成不同的操作。 要 点
4.1 程序文件 有关此Visual FoxPro程序的几点说明: 1.注释语句 【格式1】NOTE <注释内容> 【格式2】* <注释内容> 【格式3】&& <注释内容> 【功能】增强程序文件的易读性或放弃<注释内容>中语句的执行 2.命令的分行 Visual FoxPro程序是命令行的序列,每个命令都以回车键结束,一行只能写一条命令;若一条命令太长,一行写不下,也可分行书写,并在分行处加上续行符“;”,再按回车键。
4.1.1 程序文件的建立、修改与执行 1.建立或修改程序文件 可用两种方式调用系统内置的文本编辑器建立或修改程序文件: 命令方式 MODIFY COMMAND [<盘符>] [<路径>]〈程序文件名〉 菜单方式 打开“文件”菜单,选择“新建”;在“新建”窗口,选择“程序”,再选择“新建文件” 要 点
2.保存程序 程序输入、编辑完毕,单击【文件】|【保存】菜单项,或按Ctrl+W复合键,在“另存为”对话框中指定程序文件的存放位置和文件名,并单击“保存”按钮保存程序文件并退出文本编辑器。程序文件的默认扩展名是.PRG。
3.执行程序 程序文件建立后,可以用多种方式、多次执行它。下面是两种常用的方式。 (1)菜单方式 ①单击【程序】|【运行】菜单项,打开“运行”对话框; ②从文件列表框中选择要运行的程序文件,并单击“运行”命令按钮,启动运行该程序文件 (2)命令方式 【格式】DO [<盘符>][<路径>\]<文件名> 【功能】执行指定<盘符>、<路径>下的程序文件
4.1.2 程序文件中的专用命令 1、程序结尾的专用命令 执行程序文件时,将依次执行文件中的命令,直到所有命令执行完毕,或者执行到以下命令: ①CANCAL:终止程序运行,清除所有的私有变量,返回命令窗口; ②RETURN:结束程序执行,返回调用它的上级程序,若无上级程序则返回命令窗口; ③QUIT:结束程序执行并退出Visual FoxPro系统,返回操作系统
2、输入输出专用命令 ACCEPT、INPUT等命令很少使用,这里仅介绍定位输入输出 命令。 @<行,列>[SAY 表达式1][GET 变量名][DEFAULT 表达式2] 功能:在屏幕的指定行列输出SAY子句的表达式值,并可修改 GET子句的变量值。 • SAY子句用来输出数据,GET子句用来输入及编辑数据。 • GET子句中的变量必须具有初值,或用Default子句指定初值。 • GET子句的变量必须用READ命令来激活。
[例4-1]试编一程序,能根据记录号来修改某设备的价格和部门[例4-1]试编一程序,能根据记录号来修改某设备的价格和部门 (1)建立程序 *e4-1.prg CLEAR USE sb Jlh=1 && GET变量必须有初值 @2,10 SAY “请输入记录号:”GET jlh READ GO jlh @4,10 SAY “请修改第:”+STR(jlh,1)+”个设备的数据:” &&输出提示字符串 @2,10 SAY “价格”GET 价格 &&价格是字段变量,已由初值 @2,10 SAY “部门”GET 部门 READ USE
(2)运行程序 输入命令 DO e4-1后程序开始执行
3.WAIT命令 • 【格式】WAIT [<提示信息>][TO<内存变量>] [WINDOW [AT<行>,<列>]] [NOWAIT] [CLEAR|NOCLEAR] [TIMEOUT<数值表达式>] • 【功能】显示提示信息,暂停程序执行,直到用户按任意键或单击鼠标时继续执行程序。 • 若选择可选项[TO <内存变量>],将输入的单个字符作为字符型数据赋给指定的<内存变量>;若用户是按Enter键或单击鼠标,<内存变量>的值为空串。 • 若省略所有可选项,屏幕显示“键入任意键继续……”默认提示信息 [例4-2]WAIT命令输出信息提示. WAIT “请检查输入内容!”WINDOW
4.2程序的控制结构 Visual FoxPro系统提供的命令丰富,且功能强大,把这些命令和程序设计语句有效地组织在一起,就形成了实现某一特定功能的程序。 Visual FoxPro系统的程序有两个特点:一是程序控制流模式,由顺序、分支、循环三种基本结构构成。二是面向对象可视化的结构程序模块,在每个模块的内部也是由程序控制流组成。常见的控制结构如下: 1.顺序结构 顺序结构是在程序执行时,根据程序中语句的书写顺序依次执行的命令序列。Visual FoxPro系统中的大多数命令都可以作为顺序结构中的语句。 2.分支结构 分支结构是在程序执行时,根据不同的条件,选择执行不同的程序语句,用来解决有选择、有转移的诸多问题。 要 点
3.循环结构 循环结构则能够使某些语句或程序段重复执行若干次。如果某些语句或程序段需要在一个固定的位置上重复操作,使用循环是最好的选择。 4.过程结构 在许多应用程序中,有一些程序段需要反复执行多次,这些程序段不在一个固定的位置上,而是分散在程序的许多位置上重复执行,可将其与嵌入它的程序分开,形成独立的程序序列,待使用时再调入程序中,以实现不同位置上的重复操作。这样做增强了程序的可读性和模块化。我们称这种具有独立功能而且可以被其它程序调用的程序序列为过程。 要 点
分支结构 分支结构形式有如下三种: 1.简单条件语句(单向分支) 单向分支语句,即根据用户设置的条件表达式的值,决定某一操作是否执行。 (1)语句格式: IF〈条件表达式〉 〈命令行序列〉 ENDIF (2)语句功能: 该语句首先计算〈条件表达式〉的值,当〈条件表达式〉的值为真时,执行〈命令行序列〉;否则,执行ENDIF后面的第一条命令。 要 点
[例4-3]将SB.dbf中第一个非主要设备的价格减少10%。[例4-3]将SB.dbf中第一个非主要设备的价格减少10%。 *e4-3.prg use sb locate for not 主要设备 if found() display 名称, 价格 replace 价格 with 价格*(1-0.1) display 名称, 价格 endif use return
2.带else的条件语句(双向分支) 双向分支语句,即根据用户设置的条件表达式的值,选择两个操作中的一个来执行。 (1)语句格式: IF〈条件表达式〉 〈命令行序列1〉 ELSE 〈命令行序列2〉 ENDIF (2)语句功能: 该语句首先计算〈条件表达式〉的值,当〈条件表达式〉的值为真时,执行〈命令行序列1〉中的命令;否则,执行〈命令行序列2〉中的命令;执行完〈命令行序列1〉或〈命令行序列2〉后都将执行ENDIF后面的第一条命令。 要 点
宏代换函数: 格式:&<字符型内存变量>[.字符表达式] 功能:替换出字符型内存变量的值 [例4-4]宏代换示例 *e4-4.prg m=5 x=“m“&& x为字符型内存变量 ?x && 显示m ? &x && 显示5,得到了变量x的值
[例4-5]试编一程序,能打开任意一个表来浏览。[例4-5]试编一程序,能打开任意一个表来浏览。 *e4-5.prg @5, 10 SAY "请输入表名:" get bm default space(10) Read && 例如输入sb bm=alltrim(bm) && 删去两端空格 if file(“&bm..dbf”) &&文件存在返回.T.,&bm后用一个.来连接扩展名.dbf use &bm browse else wait "该文件不存在!" window endif
3.多向分支 多向分支语句,即根据多个条件表达式的值,选择执行多个操作中的一个对应执行 。 (1)语句格式: DO CASE CASE〈条件表达式1〉 <命令行序列1〉 CASE〈条件表达式2〉 <命令行序列2〉 …… CASE〈条件表达式N〉 〈命令行序列N〉] [OTHERWISE 〈命令行序列N+1〉] ENDCASE 要 点
(2)语句功能: 该语句根据给出的N个〈条件表达式〉的值,选择N+1个〈命令行序列〉中的一个执行。当所有CASE中〈条件表达式〉的值都是假时,如果有OTHERWISE项,则执行〈命令行序列N+1〉,再执行ENDCASE后面的第一条命令;否则,直接执行ENDCASE后面的第一条命令。 要 点
[例4-6]显示当前季节程序。 *e4-6.prg yue=month(date()) &&获取当前月份 do case case inlist(yue, 3,4,5) &&第一个表达式的值是其余表达式值之一就返回.T. jj="春" case inlist(yue, 6,7,8) jj="夏" case inlist(yue, 9,10,11) jj="秋" case inlist(yue, 12,1,2) jj="冬" endcase wait jj window &&当前季节显示在WAIT提示窗口内
4.使用分支语句应注意的几点 (1)IF…… ENDIF和DO CASE…… ENDCASE 必须配对使用,DO CASE与第一个CASE〈条件表达式〉之间不应有任何命令。 (2)〈条件表达式〉可以是各种表达式或函数的组合,其值必须是逻辑值。 (3)〈命令行序列〉可以由一个或多个命令组成,可以是条件控制语句组成的嵌套结构。 (4)DO CASE…… ENDCASE 命令,每次最多只能执行一个〈命令行序列〉。在多个CASE项的〈条件表达式〉值为真时,只执行第一个〈条件表达式〉值为真的〈命令行序列〉,然后执行ENDCASE的后面的第一条命令。 要 点
循环结构 1.DO WHILE循环语句 【格式1】DO WHILE <条件表达式> <语句序列> ENDDO 要 点 一个循环结构一般应具备如下的条件: (1)循环的初始条件:一般为给循环控制变量赋初值; (2)循环头:循环语句的起始,设置、判断循环条件; (3)循环尾:循环语句的结尾; (4)循环体:位于循环头和循环尾之间、循环控制重复执行的语句序列
[例4-7]试编一程序,显示SB.DBF中所有单价超过10000元的设备名称。[例4-7]试编一程序,显示SB.DBF中所有单价超过10000元的设备名称。 *e4-7.prg use sb do while not eof() if 价格>10000 ? 名称 endif skip enddo use
[例4-8]按9万元以上,1~9万元,1万元以下三级价格分档统计sb.dbf中设备的个数。[例4-8]按9万元以上,1~9万元,1万元以下三级价格分档统计sb.dbf中设备的个数。 *e4-8.prg store 0 to k1, k2, k3 use sb do while not eof() do case case 价格>90000 k1=k1+1 case 价格<10000 k3=k3+1 otherwise k2=k2+1 endcase skip enddo ? "9万元以上设备个数:"+str(k1) ? "1-9万元以上设备个数:"+str(k2) ? "1万元以下设备个数:"+str(k3) use
2.FOR循环语句 (步长循环) 【格式】 FOR <循环变量>=<初值> TO <终值> [STEP<步长>] <循环体> ENDFOR|NEXT 要 点
[例4-9]编写计算S=1+2+3+…+100的程序。 *e4-9.prg s=0 && s为累加器,初值为0 for i=1 to 100 && i为计数器,初值为1 s=s+I && 累加 next ? "s=", s
3.“指针”型循环控制语句(扫描循环) “指针”型循环控制语句,即根据用户设置的表中的当前记录指针,决定循环体内语句的执行次数据。 (1)语句格式: SCAN[〈范围〉][FOR〈条件表达式1〉 [ WHILE 〈条件表达式2〉]] 〈命令行序列〉 ENDSCAN (2)语句功能: 该语句在指定的范围内,用数据记录指针来控制循环次数。执行语句时,首先判断函数EOF()的值,若其值为“真”,则结束循环,否则,结合〈条件表达式1〉或〈条件表达式2〉,执行〈命令行序列〉,记录指针移到指定的范围和条件内的下一条记录,重新判断函数EOF()的值,直到函数EOF()的值为真时结束循环。 要 点
[例4-10]用扫描循环语句显示SB.DBF中所有单价超过10000元的设备名称。[例4-10]用扫描循环语句显示SB.DBF中所有单价超过10000元的设备名称。 *e4-10.prg use sb scan for 价格>10000 ? 名称 endscan use
4.辅助循环语句 【格式2】DO WHILE <条件表达式> <语句序列1> [LOOP] <语句序列2> [EXIT] <语句序列3> ENDDO • LOOP语句:强行返回到循环开始语句。 • EXIT语句:强行跳出循环,接着执行ENDDO后的语句
[例4-11]编程计算S=1+2+3+…+100,并求1~100间奇数的和。[例4-11]编程计算S=1+2+3+…+100,并求1~100间奇数的和。 *e4-11.prg store 0 to i,s,t do while i < 100 i=i+1 s=s+I && 累加i值 if int(i/2) = i/2 && i为偶数时条件值为.T. loop endif t=t+I && 累加奇数 enddo ?"1+2+3+...+100=", s ?"1-100奇数和为:", t
使用FOR循环语句的有关说明: ① 省略STEP <步长>,则〈步长〉为默认值1; ②〈初值〉、〈终值〉和〈步长〉都可以是数值表达式,但这些表达式仅在循环语句开始执行时计算一次。循环语句执行过程中,初值、终值和步长是不会改变的,并由此确定循环的次数; ③ 可以在循环体内改变循环变量的值,但会改变循环执行次数; ④ EXIT和LOOP命令可以出现在循环体内。执行LOOP命令时,结束本次循环,循环变量增加一个步长值,返回FOR循环头判断循环条件是否成立。执行EXIT命令时,程序跳出循环,执行循环尾后面的语句
5.多重循环 多重循环即循环的嵌套,是在一个循环结构的循环体中又包含另一个循环。我们称外层循环为外循环,被包含的循环为内循环。嵌套层数一般没有限制,但内循环的循环体必须完全包含在外循环的循环体中,不能相互交叉。正确的嵌套关系如: DO WHILE <条件表达式1> <语句序列11> DO WHILE <条件表达式2> <语句序列21> DO WHILE <条件表达式3> <语句序列3> ENDDO <语句行序列22> ENDDO <语句行序列12> ENDDO
[例4-12]在sb.dbf中找出所有价格不超过P的设备的编号、名称与价格,并要求在各行下显示一条虚线。[例4-12]在sb.dbf中找出所有价格不超过P的设备的编号、名称与价格,并要求在各行下显示一条虚线。 *e4-12.prg clear use sb @5, 10 say"请输入价格:"get jg default 0 read scan && 外循环 if 价格 < jg ? 编号 + space(3) + 名称+space(3)+str(价格,9,2) ? && 起换行作用 for i=1 to 30 && 内循环,显示由30个“-”号构成的虚线 ??“-“&& 内循环的循环体 endfor endif endscan use
6.使用循环语句时应注意的几点 (1)DO WHILE和ENDDO、FOR和ENDFOR、SCAN和ENDSCAN必须配对使用。 (2)〈命令行序列〉可以是任何FoxPro命令或语句,也可以是循环语句,即可以为多重循环。 (3)〈循环变量〉应是数值型的内存变量或数组元素。 (4)EXIT和LOOP命令嵌入在循环体内,可以改变循环次数,但是不能单独使用。EXIT的功能是跳出循环,转去执行ENDDO、ENDFOR、ENDSCAN后面的第一条命令;LOOP的功能是转回到循环的开始处,重新对“条件”进行判断,相当于执行了一次ENDDO、ENDFOR、ENDSCAN命令,它可以改变〈命令行序列〉中部分命令的执行次数。EXIT、LOOP可以出现在〈命令行序列〉的任意位置。 要 点
作业: 1、求一元二次方程AX2+BX+C=0的实根。程序文件名为zy4-1.PRG。 2、编写一密码校验程序(假设密码为ABC)。运行时屏幕显示“请输入密码”,如密码正确,提示“欢迎使用本系统”,否则提示“密码错误”。程序文件名为zy4-2.PRG。 3、假设收入(P)与税率(R)的关系如下表,编程求税金。程序文件名为zy4-3.PRG。 0 P<800 R= 0.05 800 ≤ P<2000 0.08 2000≤P<5000 0.1 P≥5000
4.3 过程及过程调用 Visual FoxPro与其他高级语言一样,支持结构化程序设计方法,允许将若干命令或语句组合在一起作为整体调用,这些可独立存在并可整体调用的命令语句组合称为过程 。 1.调用过程语句,即执行已有的过程。 语句格式: DO 〈过程名〉 WITH <参数表> 语句功能:执行以〈过程名〉为名的过程。 2.过程返回语句,即返回过程的调用处。 语句格式: RETURN[TO MASTER|TO〈过程名〉] 语句功能:将控制返回到调用程序中调用命令的下一语句。 要 点
4.3 多模块程序 • 应用程序一般都是多模块程序,可包含多个模块程序。 • 模块是可以命名的一个程序段,可指主程序、子程序和自定义程序。 。
4.3.1 子程序 调用与返回 1.调用过程语句,即执行已有的过程。 语句格式: DO〈程序名1〉[WITH <参数表>][IN〈程序名2〉] 语句功能:执行以〈过程名1〉为名的过程。 • <参数表>中的参数可以是表达式,但若为内存变量必须具有初值 • 当〈程序名1〉是IN子句〈程序名2〉中的一个过程时,DO命令调用该过程。 • 当调用子程序时参数表中的参数要传给子程序时,子程序也必须设置相应的参数接收语句。 接收参数和回送参数语句:PARAMETERS <参数表> 该语句必需是被调用程序中中第一条语句。<参数表>中的参数可以是任意合法的内存变量名。
[例4-13]设计一个计算圆面积的子程序,并要求在主程序中带参数调用它。[例4-13]设计一个计算圆面积的子程序,并要求在主程序中带参数调用它。 主程序 *e4-13.prg ymj=0 @5,10 SAY "请输入半径:" get bj default 0 read do js with bj,ymj &&调用子程序 ?"ymj=",ymj &&显示圆面积 return 子程序 *js.prg parameters r,s s=PI()*r*r && vfp的PI函数返回π值 return &&返主
主程序 … DO A … 子程序A … DO B … RETURN 子程序B … … RETURN 主程序 … DO A … 子程序A … DO B … RETURN 子程序B … … RETURN To MASTER 2.子程序嵌套 过程返回语句,即返回过程的调用处。 语句格式: RETURN[TO MASTER|TO〈程序名〉] 语句功能:将控制返回到调用程序中调用命令的下一语句。
4.3.2 自定义函数 一、自定义函数的建立 自定义函数具有如下语法结构: FUNCTION <函数名> PARAMETER <参数表> <语句序列> RETURN <表达式> • 若使用FUNCTION语句来指出函数名,表示该函数包含在调用程序中。若缺省该句,表示此函数是一个独立文件,函数名将在建立文件时确定,其扩展名默认为.PRG。 • <语句序列>组成为函数体,用于进行各种处理;简单的函数其函数体也可为空。 • RETURN语句用于返回函数值,其中的<表达式>值就是函数值。若缺省该语句,则返回的函数值为.T. • 自定义函数与系统函数调用方法相同:函数名 [<参数表>]
[例4-14]设计一个自定义函数,用来求一元一次方程AX+B=0的根。[例4-14]设计一个自定义函数,用来求一元一次方程AX+B=0的根。 *e4-14.prg 解法一:自定义函数作为一个独立的文件 *root.prg parameters a,b return iif(a=0,"无解",-b/a) ?"x=:",root(3,1) 解法二:自定义函数与其调用语句包含在同一程序中 *root1.prg clear @5,10 say "一次项系数:"get a default 1 @7,10 say "常 数 项:"get b default 0 read ?"x=:",root(a,b) funtion root parameters u,v return iif(u=0,"无解",-v/u)
二、数组参数的传递 • 在调用自定义函数或过程时,也可将数组作为参数来传送数据。 • 发送参数与接收参数都使用数组名,发送参数数组名前要加@来标记,而作为接收参数的数组不需要事先定义
[例4-14]解法三:用数组传递参数 *root2.prg clear dimension fs(2) fs(1)=1 fs(2)=0 @5,10 say "一次项系数:"get fs(1) @7,10 say "常 数 项:"get fs(2) read ?"x=:",root(@fs) && 数组名前加@可传递数组 funtion root parameters js return iif(js(1)=0,"无解",-js(2)/js(1))
4.3.3 过程 • 如果将多模块程序中的每个模块(主程序、子程序或自定义函数)分别保存为一个.PRG文件,则每执行一个模块就要打开一次文件,势必增加总的运行时间。 • VFP允许在一个.PRG文件中设置多个程序模块,并将主程序以外的每个模块定义为一个过程,这种文件可称为“过程文件”,仍使用.PRG为扩展名。 • 过程格式为: PROCEDURE <过程名> [PARAMETERS <参数名>] <命令序列> [RETURN]
[例4-15]将4-13的程序改变为过程调用 *e4-15.prg set decimals to 2 &&设置小数保留2位 ymj=0 @5,10 SAY "请输入半径:" get bj default 0 read do js with bj,ymj &&调用过程js ?"ymj=",ymj return &&程序结束语句,允许省略 procedure js &&过程js开始语句 parameters r,s s=pi()*r*r return &&过程结束语句,允许省略
[例4-16]调用过程文件中的过程实例 主程序: *e4-16.prg ymj=0 @5,10 SAY "请输入半径:" get bj default 0 read do js with bj,ymj in js1 &&调用过程文件js1中的过程js ?"ymj=",ymj 过程文件: *js1.prg procedure js parameters r,s s=pi()*r*r