1、2018/10/14,1,6.1 结构化程序设计概述 6.2 程序文件的建立、编辑与执行 6.3 程序设计辅助命令 6.4 程序的基本控制结构 6.5 子程序、过程文件与自定义函数(部分) 6.6 程序调试 (不考),第六章 目 录,2018/10/14,2,6.1 结构化程序设计概述,一组命令: Use jsqk Index On xm Tag xmcdx List jsbh,xm,csrq Seek “茅丽艳“ ? Found( ) Disp jsbh,xm,zc,bmbh,1. 在命令窗口中一一输入和执行。不能保存。,2. 将命令序列保存成.PRG文件,随时可以打开执行。,两种执行方式:
2、,2018/10/14,3,6.1.1 程序的概念程序就是计算机能够分析执行的指令集合。程序设计就是计算机用户根据问题的要求,按一定的逻辑关系,将一系列的指令组合在一起,形成一个指令序列的过程。,在Visual FoxPro中,程序文件也称为命令文件,其扩展名为.prg。,VFP的三种工作方式:菜单方式命令方式程序方式,2018/10/14,4,6.1.2 程序设计和算法1算法的概念算法就是解决问题的方法和步骤。2算法的表示算法可以有多种表示方法,常用的有自然语言法和流程图法。,判断,输入输出,处理框,1,起止框,流程线,2018/10/14,5,6.2 程序文件的建立、编辑与执行,6.2.1
3、 程序文件的建立与编辑 1菜单方式 2命令方式 格式: Modify Command , 程序文件名必须以字母开头,由字母、数字、下划线组成,其默认的扩展名为prg 。 .fxp为编译后的程序文件。 执行命令时,系统在指定路径或当前路径下查找命令中指定的文件,如果未找到,则建立新文件;如果找到了指定的文件,系统自动将该文件调入并显示在编辑窗口内。,2018/10/14,6,程序的书写规则:1)一行只能写一条命令,写完要输入回车符,表示命令结束。 2)为便于阅读,可以将长的命令分成若干行书写,但要在行尾加上分号,表示下一行是本行的继续。 3)绝大部分命令或函数都可缩写成前四个字符。,2018/1
4、0/14,7,6.2.2 程序文件的调用执行 1菜单方式单击主菜单项“程序”,在弹出的下拉菜单中选择“运行”命令。 2命令方式 格式:DO With 功能:将磁盘上“文件名”所指的命令文件调入内存并运行。 说明: 程序文件的执行中,如果发生错误,系统将给出错误信息,用户可返回编辑状态进行修改。 本命令中的可选项 With 用于执行带参数的程序。参数的作用是向将要运行的程序传递数据。,2018/10/14,8,6.3 程序设计辅助命令,6.3.1 常用输入输出命令 1数据输入命令 Input 命令 格式:Input 提示信息 To 内存变量 功能:用于接收从键盘输入的表达式,并将计算结果存入指定
5、的内存变量中。,2018/10/14,9,Input 命令说明: Input命令执行时,先在屏幕上显示提示信息,然后暂停程序的运行,等待从键盘输入数据。用户输入后,按下回车键,系统将所输入的数据送到指定的内存变量中。 Input命令能够接收任意类型的Visual FoxPro表达式,计算出结果后,再赋值给内存变量。如果输入的表达式中有字符串、日期型、逻辑型常量,则必须使用定界符。 如果内存变量未定义,将在执行此命令时建立内存变量。 Input命令每次只能为一个变量输入值。 提示信息可以省略。,2018/10/14,10,【例6.4】编写程序,由键盘输入半径,求圆面积。(在程序运行时输入半径,可
6、以实现求任意半径的圆面积,提高程序的通用性)。程序circle1.prg的内容如下:Input “半径=” To r s3.14159*r*r ? “圆面积=”,s Return,2018/10/14,11, Accept命令 格式:Accept TO 功能:将从键盘上接收的字符串存入指定的内存变量中。 说明: 执行此命令时,先在屏幕上显示提示信息,然后暂停程序运行,等待用户从键盘输入数据,并以回车键结束。系统将输入的数据存入指定的内存变量中,然后,继续运行程序。 Accept命令只能接收字符型数据,因此所有输入的数据都被作为字符型,并且不需要加定界符。 如果内存变量未定义,将在执行此命令时建
7、立内存变量,Accept命令所定义的内存变量为字符型。 可以省略。,2018/10/14,12,【例6.5】编程完成如下功能:从键盘输入某个表文件名,要求打开并显示此表中的数据。Accept “请输入表名” To xUse &xListUseReturn,INPUT语句与ACCEPT语句的区别:ACCEPT命令只能接收字符串,而INPUT语句可以接收任意类型的VFP表达式;如果输入的是字符串,ACCEPT语句不要使用字符型定界符,而INPUT语句必须用定界符括起来。,2018/10/14,13, Wait命令 格式: Wait To Window Nowait Timeout ,功能:执行该命
8、令时,暂停程序的运行,在屏幕上显示提示信息,并等待用户从键盘输入任意字符,之后将其赋值给指定的内存变量,程序继续往下执行。,2018/10/14,14,说明: 可选项提示信息含义同Accept命令的提示信息。 可选项To内存变量,将用户输入的字符存入内存变量中,若按回车,内存变量的值为空。若无此可选项,键入的值不保存。 注意:内存变量中只能保存输入的第一个字符。 如无任何可选项,系统在执行此命令后,自动显示“Press any key to continue ”,表示按任意键继续执行程序。 加Window选项时,将在屏幕右上角的提示窗口内显示提示信息;选择Nowait选项则仅显示提示信息,而不
9、暂停。Timeout表示最大等待时间,如果在数值表达式表示的时间内无键盘输入,则继续程序的执行,等待时间以秒计。,2018/10/14,15,WAIT语句主要用于下列两种情况: 暂停程序的运行,以便观察程序的运行情况,检查程序运行的中间结果。 根据实际情况输入某个字符,以控制程序的执行流程。比如,在某应用程序的“YN”选择中,常用此命令暂停程序的执行,等待用户回答“Y”或“N”,由于这时只需输入单个字符,也不用按回车键,操作简便,响应迅速。Wait “是否打印(YN )?” &用户输入Y或N,2018/10/14,16,2数据输出命令 格式:?/? 功能:计算并输出表达式的值 说明: 命令中的
10、表达式可以包含字段变量和内存变量,表达式之间以逗号分隔。 两个命令的区别在于:? 命令先换行,再开始输出,? 命令不换行即开始输出。 ? 命令后面若没有表达式表,则只进行换行操作。,2018/10/14,17,6.3.2 其它常用程序命令 1. 返回命令 格式:Return | To Master 功能:结束当前程序的执行,返回到调用它的上级程序,如果没有上级程序,则返回到命令窗口。 说明: Return通常是程序的最后一条命令,一般允许缺省。 可选项用于子程序嵌套调用时指定返回位置,详细信息请参考6.5.1节。 2终止命令 格式:Cancel 功能:终止程序运行,返回命令窗口。,2018/1
11、0/14,18,3参数定义命令参数可以在不同程序之间进行数据传递,使用参数也可以增强程序的通用性。格式1: Parameters 形式参数表 格式2: LParameters 形式参数表 功能:定义形式参数,以接收Do命令中实际参数所传送的数据。,2018/10/14,19,说明: 编辑带参数的程序文件时,必须把定义参数命令作为程序中的第一条命令,其中的参数是有效的任意变量名。参数表中可以有一个或多个参数,各参数之间用逗号分隔。程序中定义的参数又称为形式参数,Do命令中使用的参数称为实际参数。 参数不仅可以接收数据,还可以向调用程序时使用的变量回送数据。 调用程序时,形式参数的数目必须等于或多
12、于实际参数的数目,否则系统产生运行错误,如果形式参数多于实际参数,多余的形式参数取逻辑值 .F。 格式2定义的参数为“本地参数”,这种参数的使用范围与普通参数不同,与本地变量性质相同。,2018/10/14,20,【例6.8】带参数程序文件的编制与调用示例:求任意半径的圆面积。程序名 Circle2.prg,程序内容如下: Parameters r a3.14159*r*r ? “圆面积: ”,a Return 为求半径为5的圆面积,只须键入命令: Do circle With 5 则输出为:圆面积:94.25770 也可以:X=5 Do circle with 5+x,2018/10/14,
13、21,如果将程序稍作修改,变量a也设置为形式参数,程序改变为:Parameters r , aa3.14159*r*r Return 则在命令窗口依次输入以下命令: x=0 Do Circle2 with 5, x ? “面积为: ”,x 输出结果为: 面积为:78.53975,2018/10/14,22,4注释命令注释仅起说明作用,不影响程序运行。Visual FoxPro提供了两种注释的方法: 在程序行开头加“*”或“Note”,表示本行为注释行; 命令行中字符串“&” 后面的部分为注释。 例如下面带注释的程序: *本程序用来计算圆面积 Parameters r &变量r用于存放半径值 a
14、3.14159*r*r ? “圆面积: ”,a Return,2018/10/14,23,6.4 程序的基本控制结构,6.4.1 顺序结构系统按命令的顺序执行。 6.4.2 分支结构分支结构能根据指定条件的当前值在两条或多条程序路径中选择一条执行,这样,程序中便能处理多种情况的复杂问题。Visual FoxPro提供三种格式的分支结构。,2018/10/14,24,1单分支选择命令 命令格式:If 条件命令序列Endif 功能: 条件表达式的值为.T.时,执行命令序列, 然后执行Endif后的命令;条件表达式的值为.F.时,不执行命令序列, 直接执行Endif后的命令。,图6.3 单分支命令的
15、执行流程,2018/10/14,25,【例6.9】键盘输入一个实数,计算并输出其绝对值。Input 请输入一个实数 To x If x0 x= - xEndif? “其绝对值为”, xReturn,【例6.10】键盘输入一个实数,计算并输出其绝对值。 Clear &清屏 Use jsqk Wait “是否打印? (Y/N)“ To a If Upper(a)= “Y“Wait “请准备好打印机,按任意键后打印“List Endif Return,2018/10/14,26,2双分支选择命令 格式: If 条件命令序列1 Else命令序列2 Endif 功能:根据条件表达式的值在命令序列1与命令
16、序列2这两条路径中选择一条执行。条件值为.T.时,执行;条件值为.F.时,执行;然后执行Endif后的命令。,说明: If、Else 和 Endif 必须配对使用,且这三条子句应各占一行。 和中可以嵌套If命令,但不能交叉。,2018/10/14,27,【例6.11】键盘输入一个表文件名,若文件存在,则显示其记录,若不存在,则显示提示信息”文件不存在”。Clear AllAccept “请输入文件名“ To sIf File(s)Use &sDisp AllElse? “文件不存在“EndifReturn,2018/10/14,28,3. 多分支选择命令 格式: Do CaseCase条件l命
17、令序列1Case条件2 命令序列2 Case条件n命令序列n Otherwise命令序列Q Endcase,2018/10/14,29,功能:依次判断命令中列出的条件,只要找到某一条件表达式的值为.T.,就执行与之相关的命令序列,余下的条件便不再判断,有关的命令当然亦不执行。在没有一个条件取值为.T.时,若有可选项Otherwise,就执行命令序列Q,否则,什么也不执行。 说明: Do Case和第一个Case子句之间不能插入任何命令。 Do Case 和 Endcase必须配对使用,且Do Case、Case、Otherwise 和 Endcase各子句必须各占一行。 中可含有任何Visua
18、l FoxPro命令,包括可嵌套Do Case命令。,在分支结构中,几种形式可以相互嵌套。建议采用“缩进”式写法,便于程序的阅读和修改(如检查If和Endif的是否配对等)。,2018/10/14,30,【例6.14】根据gz表中的数据,计算职工应缴纳的税费。,Clear Open Database jsgl Use gz Accept 请输入职工编号: To bh & 199316、199006 Locate For jsbh=bh If Found( )x=jcgz+zwbt+zjjtDo CaseCase x1500tax=0Case x=2000tax=(x-1500)*0.05,Ca
19、se x =2500tax= (x-1500)*0.05 +(x-2000) *0.04Otherwisetax= (x-1500)*0.05 +(x-2000)*0.04+(x-2500)*0.03Endcase? “应缴税为:“+str(tax,10,2)+ “元“ Else? “查无此人“ Endif Close Database Return,2018/10/14,31,6.4.3循环结构循环结构也称为重复结构,是指程序执行过程中,其中的某段代码被重复执行若干次。被重复执行的代码段,通常称之为循环体。Visual FoxPro支持循环结构的命令包括:Do While-Enddo命令Fo
20、r-Endfor命令Scan-Endscan命令。,2018/10/14,32,1Do While命令 格式: Do While 条件命令序列Loop命令序列Exit 命令序列 Enddo,功能:首先判断条件表达式的值,若为“真”,就执行Do While与Enddo之间的命令序列(循环体),然后再判断条件表达式的值。重复刚才的过程。一旦条件取值为“假”,就跳出循环体转而执行Enddo的下一条命令。,2018/10/14,33,说明: 命令从Do While开始,到Enddo结束,两者必须成对出现。 可选项Exit能立即跳出循环,执行Enddo后的下一条命令。 可选项Loop将控制跳转到循环结构
21、的开始处,并根据条件的取值决定是否开始一次新的循环。Exit与loop可以出现在循环体内的任何位置上。 循环是否继续取决于条件表达式的当前取值。一般情况下, 循环体中应含有改变条件表达式值的命令,否则将形成死循环。 循环结构也能自身嵌套,还能与分支结构的各种形式嵌套。,2018/10/14,34,【例6.14】利用循环结构计算1到1000中偶数的和。i=0s=0Do While i=1000 &循环变量i控制循环次数s=s+I &保存累计结果i=i+2 &循环变量增值Enddo? “ 1000之内的偶数和是: “, sReturn,【例6.15 】 、 【例6.16 】,2018/10/14,
22、35,2For-Next循环命令 格式: For 内存变量表达式l To 表达式2 Step 表达式3命令序列ExitLoop Endfor | Next 功能:本命令中的内存变量(又称循环变量)类似于计数器,它的取值范围由表达式1(初值)与表达式2(终值)确定。通过判断内存变量的取值是否在指定范围之中来确定循环体是否重复执行。,2018/10/14,36,说明: 表达式3表示步长,每执行一次循环体,循环变量增加一个步长,步长值可正可负,步长值缺省,则默认为1。 循环变量的初值、终值和步长,决定了循环的执行次数,因此For循环命令通常用于循环次数能完全确定的情况。 一般情况下,For循环体中不
23、应包含改变循环变量值的命令,否则循环执行的次数也将随之改变。 Exit与Loop命令可放置在For与Endfor之间的任意位置。它们的功能与用法与Do While循环相同。如果循环可通过计数来控制,则使用For循环比用Do While循环更为方便。,2018/10/14,37,程序2: Clear All s=0 For i=100 to 1 Step -1s=s+i Endfor ? “ s= “, s Return,程序1 : Clear All s=0 For i=1 to 100s=s+i Endfor ? “ s= “, s Return,【例6.17】求自然数1到100的和。(下面
24、两段程序结果相同),2018/10/14,38,【例6.18】从键盘输入10个数,找出其中的最大值和最小值。ClearInput “请输入第一个数“ To aStore a To mina, maxaFor i=2 To 10Input “请输入下一个数“ To aIf amaxamaxa=aEndifIf amina mina=aEndifEndfor? “最大值: “ , maxa? “最小值: “, minaReturn,2018/10/14,39,3Scan-Endscan命令 格式: Scan For ExitLoop Endscan 【例6.19 】 功能:对当前表的指定记录,依次
25、重复执行循环体,每循环一次,表的指针自动下移一位。 说明:在数据库应用程序中,经常要对表中指定的记录逐个进行某种处理,Visual FoxPro专门提供了表记录扫描循环,利用它能非常方便地完成逐条扫描记录。请注意,Scan循环只能用于有表打开的情况。,2018/10/14,40,4多重循环循环可以嵌套。例如,若在循环体中又包含一个循环,即形成两层循环嵌套。按其所处的位置分别称为外循环与内循环。Visual FoxPro中循环嵌套层数最多允许128层,内循环必须完全嵌在外循环中,不能出现交叉。,2018/10/14,41,【例6.20】打印九九表。 分析:九九表是一个二维图形,必须用二重循环才能
26、输出,外循环控制打出多少行,内循环控制打出多少列。 Clear For i=1 to 9For j= 1 to i? Str(i, 1) + “ * ” + Str(j, 1) + “ = ” + Str(i*j, 2) + Space(2)Endfor? Endfor Return,2018/10/14,42,循环结构编程小结,1. 编程涉及两类与数据表无关的数学计算问题(如例题6.12、6.14)与数据表有关的数据处理问题(如例题6.13、6.19),2. 计算问题:多采用Do While-Enddo和For-Endfor结构。由循环控制变量控制循环。 Do While-Enddo中有类似
27、“i=i+1”语句,用以改变循环变量的值; For-Endfor中不需要,循环变量会自动增/减。注:循环结束后,循环控制变量必定超过终值!,3. 数据表数据处理:循环前有USE命令; Do While-Enddo的循环控制条件通常是Not Eof( ),循环体中有Skip;而Scan-Endscan中没有Skip,只用于数据表操作。,2018/10/14,43,6.5子程序、过程文件与自定义函数,6.5.1 子程序在程序设计中,如果实现某个功能的程序段需多次重复使用,可把这个程序段独立出来单独组成一个程序,称为子程序。此后凡需要完成该功能时,只要调用相应的子程序便可。,2018/10/14,4
28、4,使用子程序的另一个优点是:可以将一个较大的程序按一定的功能分解成若干个小的子程序,以简化程序的设计和调试过程,提高程序设计效率,更方便管理整个程序系统。调用子程序的程序称为上级程序或主程序。供其它程序调用的程序,即被调用的程序称为子程序。1 . 子程序调用 子程序调用使用Do命令。为使子程序具有通用性,通常子程序都带有参数。,2018/10/14,45,【例6.21】计算二项式系数,说明:设计一个子程序,用来计算任意整数的阶乘,在主程序中3次调用它,实现计算要求。子程序 p6-21f.prg Parameter m, y *参数m存放整数,y存放计算所得的阶乘值 y=1 For i=1 t
29、o my=y*i Endfor Return,主程序 p6-21.prg *建立三个变量用来存放调用子程序返回的3个不同阶乘值,赋初值为0 Store 0 to x1, x2, x3 Input “n=“ to n Input “r=“ to r If n=0 and r=0 and nrDo fact With n, x1Do fact With r, x2Do fact With n-r, x3c=x1/x2/x3? “c=” , c Endif Return,2018/10/14,46,程序P6-21.prg调用P6-21f.prg:P6-21.prg P6-21f.prg para m
30、,yDo P6-23f With n, x1 ReturnReturn,说明:在子程序中,(第一次调用)形式参数m、y接受实际参数n、x1(变量)传送的值;调用结束时又将结果返回对应的实际参数中(x1保存n!)。m ny x1,返回结果,2018/10/14,47,2. 子程序嵌套(不考)主程序与子程序的概念是相对的,子程序还可以调用它自己的子程序,即子程序可以嵌套调用,在这种情况下,被调用的子程序执行Return命令时,返回到调用它的上级程序处。,Return返回上一级程序;Return To Master返回主程序。,2018/10/14,48,6.5.2 过程与过程文件子程序通常是单独建
31、立的程序文件,如果程序系统中使用了较多的子程序,势必会产生许多程序文件,造成管理的困难。Visual FoxPro还支持另一种形式的子程序:过程。过程的功能和调用方式与子程序完全相同,不同之处在于格式和保存方式。每个子程序保存为一个独立程序文件,而多个过程可以保存在一个程序文件中。,2018/10/14,49,1. 过程的定义过程的定义方式有两种,其一,将多个过程保存成一个独立的程序文件;其二,直接与主程序保存在一起,这种情况下,习惯上常把它写在主程序的后面。过程的定义格式如下:Procedure ReturnProcedure Return说明:每个过程以Procedure开头,以Retur
32、n结尾。,2018/10/14,50,2. 过程的调用 打开过程文件 格式:Set Procedure To Additive 功能:打开一个或多个过程文件。 说明:有Additive选项时,打开新的过程文件时,并不关闭之前已经打开的,否则打开新过程文件时,自动关闭原来打开的。 关闭过程文件 格式1:Close Procedure 格式2:Set Procedure To 格式3:Release Procedure 功能:格式1、格式2关闭所有打开的过程文件;格式3关闭指定的过程文件。例题6.22、6.23,2018/10/14,51,6.5.3 自定义函数(不考),2018/10/14,52
33、,6.5.4 变量的作用域(不考相关程序)变量能够合法使用的程序范围就叫做变量的作用域。在Visual FoxPro中,根据变量的作用域,可将内存变量划分为: 全局变量 局部变量 本地变量,2018/10/14,53,1. 全局变量在主程序和任何子程序(包括过程和自定义函数)中都可使用的变量称为全局变量。它只能用下面两种方法之一定义: 在命令窗口中定义的变量,尽管它们不从属于某一个应用程序,但它们都是全局变量。 在任何程序模块中,用Public命令定义的变量也是全局变量。格式: Public 内存变量表 全局变量有以下特点: 全局变量可以在任何程序代码中使用,包括主程序和各级子程序。 全局变量
34、必须使用Release、Clear All、Clear Memory命令释放,否则,在程序运行结束后,全局变量仍然存在。 在程序模块中建立的全局变量,必须先定义后使用,定义后的初值为逻辑假 .F.。,2018/10/14,54,2. 局部变量在某个程序(包括主程序和子程序、自定义函数、过程)内部用赋值命令建立的变量称为局部变量。局部量只在定义它的程序模块及其下级程序中有效,该程序模块执行结束后,局部变量也被自动清除。 局部变量有以下特点: 局部变量只能在建立它的程序和其下级子程序中使用,在除此之外的程序模块中使用时,会产生找不到变量的错误。 局部变量在定义它的程序模块开始执行时建立,该程序模块
35、执行结束时自动被释放,因此其存在有时间性。 使用局部变量可以使各程序模块相互独立,互不影响,不会因局部变量的相同名称而引起混乱,这对于大型系统的团队开发特别有利。,2018/10/14,55,3. 屏蔽型局部变量 Visual FoxPro还支持一种特殊的局部变量:屏蔽型局部变量,其定义格式为:Private 或者:Private All Like | Except 该命令的作用是:如果在较高层的程序模块中定义了与屏蔽型局部变量同名的变量时,则高层程序模块中的同名变量被隐藏,即这些高层中的同名变量在当前程序模块及其下层子程序中暂时无效,待当前程序模块执行结束返回上层程序模块时,被隐藏起来的同名
36、变量会自动恢复并保持原来的值。,2018/10/14,56,4本地变量 本地变量是指用Local命令建立的变量,它不同于一般局部变量,本地变量只能在建立它的程序模块中使用,不能在其下级程序模块中使用。本地变量在程序模块执行时建立,结束时被释放。 格式:Local 功能:定义本地变量,并赋初值为逻辑假 .F.。 说明:Local命令不能缩写为Loca,避免与Locate命令的缩写混淆。,2018/10/14,57,6.6 程序调试(不考),6.6.1 程序调试的一般方法 发现程序中的错误,通常有下面两种做法: 动态检查:通过在计算机执行程序来发现其中的错误。 静态检查:用执行程序以外的办法。例如用阅读程序的方法来发现其中的错误。调试就是用动态检查的方法来发现并纠正程序中的错误,以保证程序的可靠性。,