550 likes | 652 Views
第九章 程序设计基础. 教学目标. 要求了解程序的概念、程序文件的建立与运行。 要求掌握程序的顺序、选择、循环三大控制结构及多模块程序。 重点:掌握 if 语句、 do case 语句、 for … endfor 语句、 scan … endscan 语句、 do while … enddo 语句的使用。 难点:三种循环语句的区别及利用循环结构编写程序、参数的传递、变量的作用域。. 授课内容. 9.1 程序文件 9.2 程序的控制结构 9.3 多模块程序. 9.1 程序文件.
E N D
教学目标 • 要求了解程序的概念、程序文件的建立与运行。 • 要求掌握程序的顺序、选择、循环三大控制结构及多模块程序。 • 重点:掌握if语句、do case语句、for …endfor语句、scan…endscan语句、do while…enddo语句的使用。 • 难点:三种循环语句的区别及利用循环结构编写程序、参数的传递、变量的作用域。
授课内容 • 9.1 程序文件 • 9.2 程序的控制结构 • 9.3 多模块程序
9.1 程序文件 • Visual FoxPro系统提供有三种工作方式:单命令方式、菜单方式及程序文件方式。 (1)单命令方式 所谓单命令方式,即输入一条命令,完成一个操作的工作方式。 (2)菜单方式 所谓菜单方式,即通过打开不同的菜单选择并完成不同的操作。 (3)程序文件方式 所谓命令方式,即通过程序文件中的命令完成不同的操作。
9.1.1程序的概念 程序是能够完成一定任务的命令的有序集合。这些命令被存放在称为程序文件或命令的文本文件中。当运行此程序文件时,系统会按照一定的次序自动执行包含在程序文件中的命令。 与其他方式相比,采用程序方式有如下优点:(1)可以利用编辑器,方便地输入、修改和保存程序文件。(2)可以用多种方式、多次运行程序文件。(3)可以在一个程序文件中调用另一个程序。
在编写程序文件时应注意以下几点: (1)命令注释 程序中可以插入注释,以提高程序的可读性。注释行以符号“*”或“NOTE”开头,它是一条非执行命令,仅在程序中显示。命令行后也可添加注释,这种注释以符号“&&”开头。 (2)命令分行 程序中每条命令都以回车键结尾,一行只能写一条命令。若命令需分行,应在一行终了时输入续行符“;”,然后按回车键。 (3)SET TALK ON/OFF命令 许多数据处理命令在执行时都会返回一些有关执行状态的信息,这些信息通常会显示在Visual FoxPro主窗口、状态栏或用户自定义窗口里。SET TALK命令用以设置是(ON)或否(OFF)显示这些信息。默认值为ON。 (4)求解的基本逻辑 Visual FoxPro程序大多用于数据处理,在编写程序时必须先分析清楚问题,才能用计算机来求解。解决问题的基本逻辑是:先输入数据,按着处理数据,最后输出结果。 (5)程序的通用性 程序的通用性指程序对多种场合的适应性,通用性好的程序应用范围较广。
9.1.2 程序文件的建立与运行 1、建立、编辑程序文件 (1)命令方式 [格式] MODIFY COMMAND〈程序文件名〉 [功能] 打开程序编辑窗口,建立或修改命令文件。 (2)菜单方式 打开“文件”菜单,选择“新建”;在“新建”对话框,选择“程序”,再选择“新建”;在Visual FoxPro用户界面打开程序编辑窗口,输入程序文件,并保存,此时建立程序文件的操作结束。
2、运行程序文件 程序在执行之前,必须经过编译操作,未经过编译的程序称为源程序。可以通过下面三种方式来运行程序。 (1)命令方式 在命令窗口中,输入如下命令,则程序文件被调用。 DO 〈程序文件名〉 (2)菜单方式下的“边编译边运行”方式 在Visual FoxPro系统主菜单下,打开“程序”菜单,选择“运行”;在弹出的“运行”对话框,输入或选择要执行的程序文件名,单击“运行”按钮即可。或先打开源程序文件,然后单击工具栏上的按钮来运行程序。 (3)菜单方式下的“先编译后运行”方式 打开源程序,选择菜单栏“程序”菜单中的“编译”命令,系统开始编译源程序并进行语法检查。如果有错误将给出错误信息,用户根据错误提示进行修改,直到编译没有错误后,生成.FXP文件,然后执行该文件。
3、程序中的常用命令 (1)清屏命令 [格式] CLEAR [功能] 清除屏幕上或窗口中显示的内容。 (2)注释命令 [格式] *|NOTE [功能] 在程序中插入注释行,以提高程序的可读性。 (3)字符串输入命令 [格式] ACCEPT[<提示信息>] TO <内存变量> [功能] 执行该语句时,在屏幕上显示由<提示信息>所规定的提示信息,然后等待用户从键盘上输入数据,并将其赋予内存变量。
[例9-1] 编写程序,在“学生情况表”中按姓名查找某一指定学生的基本情况。 程序如下: *EX9-2.PRG CLEAR USE 学生情况表 ACCEPT “请输入学生姓名:”TO XM LOCATE FOR 姓名=XM DISPLAY USE
(4)表达式输入命令 [格式] INPUT[<提示信息>] TO <内存变量> [功能] 将从键盘输入的数据赋给内存变量。 说明: ① INPUT命令可以接受任何类型的数据,若是字符型数据,必须使用单引号、双引号或方括号括起来。 ② 内存变量的类型取决于输入数据的类型。
[例9-2] 编写程序显示“学生情况表”中所有入学成绩大于某一给定值的学生基本情况。 程序如下: *EX9-3.PRG CLEAR USE 学生情况表 INPUT “请输入入学成绩:”TO GRADE LIST FOR 入学成绩>GRADE USE
(5)单字符输入命令 [格式] WAIT[<提示信息>] [TO <内存变量>][WINDOWS] [功能] 执行该命令时等待用户输入,只要用户按下键盘上的任一个键,立即执行下一条命令。 (6)定位输入输出命令 [格式] @<行,列>[SAY<表达式1>][GET<变量名>] [DEFAULT <表达式2>] [功能] 在屏幕的指定行、列输出SAY子句的表达式值,并可修改GET子句的变量值。 (7)返回命令 [格式] RETURN [功能] 结束一个程序的执行,并使控制返回调用程序或交互状态。
(8)终止程序运行命令 [格式] CANCEL [功能] 终止命令文件的运行,并关闭所有打开的文件(清除内存变量),返回命令窗口。 (9)打开/关闭对话功能命令 [格式] SET TALK ON/OFF [功能] 执行程序时,系统是否将每条命令的运行结果提供给用户。
(10)设置打印机状态命令 [格式] SET PRINT ON/OFF [功能] 屏幕显示的结果是否送打印机输出。 (11)设置屏幕状态命令 [格式] SET CONSOLE ON/OFF [功能] 打开或关闭屏幕显示状态。 (12)退出Visual FoxPro命令 [格式] QUIT [功能] 终止程序的运行并退出Visual FoxPro。
9.2 程序的控制结构 常见的控制结构如下: 1、顺序结构 顺序结构是在程序执行时,根据程序中语句的书写顺序依次执行的命令序列。Visual FoxPro系统中的大多数命令都可以作为顺序结构中的语句。 2、选择结构 选择结构是在程序执行时,根据不同的条件,选择执行不同的程序语句,用来解决有选择、有转移的诸多问题。
3、循环结构 循环结构则能够使某些语句或程序段重复执行若干次。如果某些语句或程序段需要在一个固定的位置上重复操作,使用循环是最好的选择。 4、过程结构 在许多应用程序中,有一些程序段需要反复执行多次,这些程序段不在一个固定的位置上,而是分散在程序的许多位置上重复执行,可将其与嵌入它的程序分开,形成独立的程序序列,待使用时再调入程序中,以实现不同位置上的重复操作。这样做增强了程序的可读性和模块化。我们称这种具有独立功能而且可以被其它程序调用的程序序列为过程。
9.2.1 顺序结构 [例9-3] 根据输入的学生姓名,显示“学生情况表”中学生的基本信息。 程序如下: *EX9-4.PRG SET TALK OFF CLEAR USE 学生情况表 ACCEPT "请输入查找学生的姓名: "TO XM LOCATE FOR 姓名=XM @6,10 SAY "学生姓名:"+姓名 @7,10 SAY "性别:"+性别 @8,10 SAY "学院:"+学院 @9,10 SAY "入学成绩:"+STR(入学成绩,3) USE SET TALK ON RETURN
9.2.2 选择结构 1、单向选择 [格式] IF〈条件表达式〉 〈命令序列〉 ENDIF [功能]该语句首先计算〈条件表达式〉的值,当〈条件表达式〉的值为真时,执行〈命令序列〉;否则,执行ENDIF后面的第一条命令。
[例9-4] 从键盘输入两个数A、B,要求输出两个数中的大者。 程序如下: *EX9-5.PRG SET TALK OFF CLEAR @3,8 SAY "请输入变量A的数值" GET A DEFAULT 0 @4,8 SAY "请输入变量B的数值" GET B DEFAULT 0 READ IF A<B C=A A=B B=C ENDIF @6,8 SAY "两者中大者是" GET A RETURN
2、双向选择 [格式] IF〈条件表达式〉 〈命令序列1〉 ELSE 〈命令序列2〉 ENDIF [功能] 该语句首先计算〈条件表达式〉的值,当〈条件表达式〉的值为真时,执行〈命令序列1〉中的命令;否则,执行〈命令序列2〉中的命令;执行完〈命令序列1〉或〈命令序列2〉后都将执行ENDIF后面的第一条命令。
[例9-5] 由铁路托运行李,假设每张车票可按每公斤0.5元托运50公斤以内的行李,如果超过50公斤时,超过的部分每公斤加价0.3元,编写计算运费的程序。 设W为行李重量,X为托运行李的运费,计算公式如下: X=0.5×W 当X≤50公斤 X=0.5×50+0.8×(W-50) 当W>50公斤 程序如下: *EX9-6.PRG CLEAR INPUT "请输入行李的重量为:" TO W IF W<=50 X=0.5*W ELSE X=0.5*50+0.8*(W-50) ENDIF ? "行李的重量为"+STR(W,6,2)+"公斤,其运费为:"+STR(X,6,2)+"元" RETURN
3、IF语句的嵌套 [格式] IF〈条件表达式1〉 〈命令序列1〉 ELSE IF〈条件表达式2〉 〈命令序列2〉 ELSE IF〈条件表达式3〉 〈命令序列3〉 …… ENDIF ENDIF ENDIF 该嵌套结构的执行过程是:依次判断条件表达式的取值,若某个条件表达式的取值为真,则执行相应的命令序列,然后退出其嵌套结构。
[例9-6]从键盘输入三个数,输出其中最大的数。[例9-6]从键盘输入三个数,输出其中最大的数。 程序如下: *EX9-7.PRG SET TALK OFF CLEAR INPUT “请输入第一个数X=”TO X INPUT “请输入第二个数X=”TO Y INPUT “请输入第三个数X=”TO Z IF X>=Y .AND. X>=Z MAX=X ELSE IF Y>=X .AND. Y>=Z MAX=Y ELSE MAX=Z ENDIF ENDIF ? “MAX=”,MAX SET TALK ON RETURN
4、多向选择 如果分支过多,使用IF语句嵌套容易出错,对此Visual FoxPro提供了多向选择语句,最适宜解决这类问题。 [格式] DO CASE CASE〈条件表达式1〉 〈命令序列1〉 [CASE〈条件表达式2〉 〈命令序列2〉 …… CASE〈条件表达式n〉 〈命令序列n〉] [OTHERWISE 〈命令序列n+1〉] ENDCASE [功能] 该语句根据给出的n个〈条件表达式〉的值,选择n+1个〈命令序列〉中的一个执行。当所有CASE中〈条件表达式〉的值都是假时,如果有OTHERWISE项,则执行〈命令序列n+1〉,再执行ENDCASE后面的第一条命令;否则,直接执行ENDCASE后面的第一条命令。
[例9-7] 百货公司为了促销,采用购物打折的优惠办法。若每位顾客一次性购物: -1000元以上者,九五者折优惠 -2000元以上者,九者折优惠 -3000元以上者,八五者折优惠 -5000元以上者,八者折优惠 编写程序,输入购物款数,计算并输出优惠价。 程序如下: *EX9-8.PRG SET TALK OFF CLEAR INPUT “请输入购物款数 ”TO X DO CASE CASE X<1000 Y=X CASE X<2000 Y=X*0.95 CASE X<3000 Y=X*0.9 CASE X<5000 Y=X*0.85 OTHERWISE Y=X*0.8 ENDCASE ? “应付款数”,Y RETURN
9.3.3 循环结构 1、“当”型循环控制语句 [格式] DO WHILE 〈条件表达式〉 〈命令序列〉 ENDDO [功能] 该语句通过〈条件表达式〉的值来控制循环。执行语句时,反复判断〈条件表达式〉的值,当〈条件表达式〉的值为“真”时,执行〈命令序列〉;否则,结束循环,并执行ENDDO 后面的第一条命令。
[例9-8] 以显示方式输出1到10的数字。 程序如下: *EX9-9.PRG SET TALK OFF CLEAR ? " 数字" I =1 DO WHILE I<=10 ? I I = I +1 ENDDO
[例9-9] 鸡兔同笼问题。设鸡和兔共有头38个,脚138个,问鸡和兔各为多少只? *EX9-10.PRG SET TALK OFF CLEAR CLEAR cocks=0 foots=0 DO WHILE foots<>138 cocks=cocks+1 rabbits=38-cocks foots=2*cocks+4*rabbits ENDDO ? "鸡的数量为:",cocks ? "兔的数量为:",rabbits
[例9-10] 分别统计“学生情况表”中入学成绩大于600分的男女同学的人数。 程序如下: *EX9-11.PRG SET TALK OFF CLEAR STORE 0 TO M,F USE 学生情况表 DO WHILE .NOT.EOF() DO CASE CASE (入学成绩>600) .AND. 性别="男" M=M+1 CASE (入学成绩>600) .AND. 性别="女" F=F+1 ENDCASE SKIP ENDDO ? "男同学人数为:",M ? "女同学人数为:",F USE SET TALK ON
2、“指针”型循环控制语句 [格式] SCAN[〈范围〉][FOR〈条件表达式〉] 〈命令序列〉 ENDSCAN [功能] 该语句在指定的范围内,用数据记录指针来控制循环次数。执行语句时,首先判断函数EOF()的值,若其值为“真”,则结束循环,否则,结合〈条件表达式〉,执行〈命令序列〉,记录指针移到指定的范围和条件内的下一条记录,重新判断函数EOF()的值,直到函数EOF()的值为真时结束循环。
[例9-11] 分别统计“学生情况表”中入学成绩大于600分的男同学人数。 程序如下: *EX9-12.PRG SET TALK OFF CLEAR USE 学生情况表 S=0 SCAN FOR 入学成绩>600 .AND. 性别="男" S=S+1 ENDSCAN ? "男同学人数为:",S USE SET TALK ON
3、“计数”型循环控制语句 [格式] FOR〈循环变量〉=〈循环变量初值〉TO〈循环变量终值〉[STEP〈循环变量步长〉] 〈命令序列〉 ENDFOR [功能] 该语句用〈循环变量〉来控制〈命令序列〉的执行次数。执行语句时,首先将〈循环变量初值〉赋给〈循环变量〉,然后判断〈循环变量〉是否大于或小于〈循环变量终值〉,若结果为“真”,则结束循环,执行ENDFOR 后面的第一条命令;否则,执行〈命令序列〉,〈循环变量〉自动按〈循环变量步长〉增加或减少,再重新判断〈循环变量〉当前的值是否大于或小于〈循环变量终值〉,直到其结果为真。当步长值为1时,STEP子句可以省略。
[例9-12] 求1!+2!+3!+…+10!的值。 程序如下: *EX9-13.PRG SET TALK OFF CLEAR S=0 P=1 FOR I=1 TO 10 P=P*I S=S+P ENDFOR ? “S=”,S SET TALK ON RETURN
4、使用循环语句时应注意的几点 (1)DO WHILE和ENDDO、FOR和ENDFOR、SCAN和ENDSCAN必须配对使用。 (2)〈命令序列〉可以是任何Visual FoxPro命令或语句,也可以是循环语句,即可以为多重循环。 (3)〈循环变量〉应是数值型的内存变量或数组元素。 (4)EXIT和LOOP命令嵌入在循环体内,可以改变循环次数,但是不能单独使用。EXIT的功能是跳出循环,转去执行ENDDO、ENDFOR、ENDSCAN后面的第一条命令;LOOP的功能是转回到循环的开始处,重新对“条件”进行判断,相当于执行了一次ENDDO、ENDFOR、ENDSCAN命令,它可以改变〈命令序列〉中部分命令的执行次数。EXIT、LOOP可以出现在〈命令序列〉的任意位置,但一般包含有选择语句中使用。
[例9-13] 求0~100之间奇数之和。 程序如下: *EX9-14.PRG SET TALK OFF CLEAR X=0 Y=0 DO WHILE X<100 X=X+1 IF INT(X/2)=X/2 LOOP ELSE Y=Y+X ENDIF ENDDO ? "0~100之间的奇数之和为:", Y SET TALK ON
[例9-14] 计算1+2+3+…+100的和。 程序如下: *EX9-15.PRG SET TALK OFF CLEAR N=1 S=0 DO WHILE .T. IF N>100 EXIT ENDIF S=S+N N=N+1 ENDDO ? “0~100之间的之和为:”,S SET TALK ON
9.3 多模块程序 9.3.1 子程序 1、无参数子程序的调用与返回 对于两个具有调用关系的程序文件,通常称调用程序为主程序,被调用程序为子程序。 (1)调用子程序命令 [格式] DO 〈子程序名〉 [功能] 主程序执行时遇到DO命令,就转向执行以〈子程序名〉为名的子程序。 (2)返回主程序命令 [格式] [RETURN] [功能]子程序执行到RETURN语句(或缺省该语句),就会返回到主程序,执行调用命令的下一个语句。
2、参数子程序的调用 (1)调用参数子程序命令 [格式] DO 〈子程序名〉[WITH<实参表>] [功能] 调用子程序时参数表中的参数要传给子程序,子程序中必须设置相应的参数接受语句。<实参表>中的参数可以是常量、变量和表达式,其值将成为子程序中对应<形参表>的值。 (2)接受参数和回送参数值的命令 [格式] PARAMETERS<形参表> [功能] 接受调用命令中的实参值,并在调用后返回对应参数的计算值。
3、返回主程序语句 主程序和子程序的概念是相对的。子程序还可以调用其他的子程序,即子程序的嵌套调用。 [格式] RETURN[TO MASTER|TO <程序文件名>] [功能] 返回调用子程序的主程序。
[例9-15] 用带参数传递数据的方法编写计算M!/(N!(M-N)!的程序。 程序如下: *主程序EX9-16.PRG SET TALK OFF CLEAR Z=0 INPUT “请输入M的值(M>N):” TO M INPUT “请输入N的值(N>0):” TO N DO SUB1 WITH M &&调用子程序SUB1计算M! C=Z DO SUB1 WITH N C=C/Z DO SUB1 WITH M-N C=C/Z ? ‘C=’,C RETURN *计算阶乘的子程序SUB1.PRG PARAMETERS K Z=1 FOR I=1 TO K Z=Z*I ENDFOR RETURN
9.3.2 自定义函数 1、自定义函数格式 [格式] FUNCTION <自定义函数名> [PARAMETERS <形参表>] <函数体> RETURN <表达式> [功能] 定义一个用户自定义函数。 2、自定义函数的调用 [格式] 函数名([<实参表>]) [功能] 调用自定义函数。
[例9-16] 用函数编写求1~10的立方数。 程序如下: *程序EX9-17.PRG CLEAR ? " 原数"," 立方数" FOR i=1 TO 10 ? i,cube1(i) ENDFOR RETURN *计算立方函数 FUNCTION cube1 PARAMETERS v RETURN v*v*v
9.3.3 过程 1、过程的定义 [格式] PROCEDURE <过程名> [PARAMETERS <形参表>] <过程体> RETURN [TO MASTER] [功能] 在过程文件中标识一个过程的开始。
2、过程文件 过程文件也是扩展名为.prg的命令文件,所以其创建方法与普通的命令文件相同。 [格式]PROCEDURE <过程名1> <过程体1> RETURN PROCEDURE <过程名2> <过程体2> RETURN …… PROCEDURE <过程名n> <过程体n> RETURN
3、过程文件的打开 在程序中若想调用过程文件中的过程时,首先必须用下列命令打开过程文件。 [格式] SET PROCEDURE TO <过程文件名1>[,<过程文件名2>,…][ADDITIVE] [功能] 打开过程文件。
4、过程调用 [格式] DO <过程名> [WITH<实参表>] [功能] 调用由〈过程名〉指定的过程。 5、过程文件的关闭 主程序调用过程文件结束后,过程文件不会自动关闭,任何时候都可以再次调用。若要关闭过程文件必须用以下命令。 [格式1] SET PROCEDURE TO [格式2] CLOSE PROCEDURE [功能] 关闭所有打开的过程文件。
[例9-17] 用主程序调用过程的方法编写求圆面积和球体积的程序。 程序如下: *主程序EX9-18.PRG CLEAR MJ=0 TJ=0 INPUT “请输入半径:” TO R SET PROCEDURE TO PROFILE DO YMJ WITH MJ,R DO QTJ WITH TJ,R ? “半径为”+STR(R,2)+ “的圆面积=”,MJ ? “半径为”+STR(R,2)+ “的球体积=”,TJ CLOSE PROCEDURE RETURN *过程文件PROFILE.PRG PROCEDURE YMJ PARAMETERS S,R S=PI()*R*R RETURN PROCEDURE QTJ PARAMETERS S,R S=4/3*PI()*R^3 RETURN
[例9-18] 用主程序调用过程的方法编写求s=1!+2!+3!+4!+5!的程序。 程序如下: *主程序EX9-19PRG CLEAR SET TALK OFF s=0 FOR m=1 TO 5 t=1 DO fac WITH m,t s=s+t ENDFOR ? “s=”,s RETURN PROCEDURE fac(m,y) FOR k=1 TO m y=y*k ENDFOR RETURN
9.3.4 变量的作用域 1、全局变量 在任何程序或过程中都可以使用的变量叫全局变量。 [格式] PUBLIC <内存变量表> [功能] 定义<内存变量表>中的各内存变量为全局变量。 2、私有变量 程序中未加任何说明而直接定义使用的内存变量都是私有变量。 [格式] PRIVATE <内存变量表> [功能] 将<内存变量表>中的各变量定义为私有变量。