实验4 程序设计(4学时)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验4 程序设计(4学时)
目的与要求
1.掌握VFP程序设计特点,程序文件的建立、修改和运行方法;
2.掌握环境设置语句的含义和基本输入输出命令的使用;
3.掌握VFP的顺序、选择和循环结构的设计方法;
4.掌握程序设计过程中参数传值和传引用的传递规则;
5.掌握子程序、过程和自定义函数的建立,以及调用与返回规则;
6.掌握内存变量的作用域属性及对参数传递的影响。

实验内容
一、实验准备
1.参照“附录一”,熟悉VFP 6.0 程序文件的建立、修改和运行方法;
2.将ftp上实验指导书文件夹中“实验项目5、6用表”文件夹下的学生表
(student.dbf)、成绩表(score.dbf)、课程表(course.dbf)以及备注文件
“student.fpt”四个文件,拷贝到C:\Program Files\Microsoft Visual
Studio\Vfp98目录下,然后完成实验。

示例与程序中用到的三个表结构
如下,各位同学可以参照这些结构还原这三个数据表之间的相互关联。

二、顺序结构程序设计
1.VFP的顺序程序设计方法。

2.完成如下程序设计:
(1)物体长度可以用公制或者英制单位表示,已知公制长度单位为毫米
(mm),英制单位长度为英寸(inch),其转换公式为1 inch = 25.4 mm,
编写程序将输入的英制长度转换为公制后输出。

(2)从键盘输入圆锥体的半径(r)和高度(h),计算其体积并输出,体积计
算公式为v = π * r * r * h / 3。

(3)求方程ax2 + bx + c = 0的根,a, b, c的值从键盘输入(假设输入的a, b,
c值满足b2– 4ac ≥ 0,不考虑虚根的情况)。

(4)由键盘输入学生名,将“student表”中该学生的奖学金增加100元,
并显示该学生修改后的奖学金。

(5)分析下面程序的输出结果。

USE student
INDEX ON 姓名TAG nameidx
ACCEPT "请输入要查找的学生姓名" TO 姓名
SEEK M -> 姓名
DISPLAY
三、选择结构程序设计
1.VFP的选择程序设计方法。

2.完成如下程序设计:
(1)输入3个不同的数,将它们按照数值降序从大到小输出。

(2)从键盘输入数字月份,然后输出该月份的英文名称的缩写,如1月
输出“Jan”、10月输出“Oct”等等。

(3)输入学生的姓名,在“student表”中查找该学生的信息,如果找到
则显示该学生的信息,并将该学生的“班级”改为“机械2班”;如
果没有找到则显示“无此人!”。

(4)求方程ax2 + bx + c = 0的根,a, b, c。

(5)(0, 1, 2, …, 9)转换
为中文大写数字(〇、一、二、…、九)。

(6)已知符号函数的定义如下,后面的程序用于计算符号函数的值,请
在(1)、(2)处填入恰当的语句。

-1 a < 0
b = 0 a = 0
1 a > 0
SET TALK OFF
(1) && 输入数据到内存变量a
DO CASE
CASE a > 0
b = 1 CASE a = 0 b = 0 (2) && 此处不允许写CASE a < 0
b = -1 ENDCASE ? b
SET TALK ON
四、循环结构程序设计
1. VFP 的循环程序设计方法。

2. 完成如下程序设计:
(1) 从键盘输入10个数,去掉10个数中的一个最大值与一个最小值,然后
输出其平均值。

(2) 分别用DO WHILE …ENDDO 循环结构和SCAN …ENDSCAN 循环结构
输出“student 表”中奖学金超过200元的男生姓名和奖学金数额。

(3) 编写口令判断程序,要求从键盘输入用户名和口令,并判断判断两者是
否分别与“student 表”中的“姓名”与“学号”字段的值完全一致,若是则显示欢迎信息;否则给予重新输入的机会,输入次数一共超过三次则显示无权使用本系统的提示。

(4) 将用户输入的一个字符串进行大小写互换,即将字符串中所有的大写英
文字母转换成小写,小写英文字母转换成大写后输出,其它字符不变。

(5) 求s = !
!3!2132n x x x x n
+++++ ,其中x 和n 的值从键盘输入,当0001.0!
≤n x n
时停止计算。

(6) 输出如下图形,其中的行数从键盘输入:
6 5 4 3 2 1 5 4 3 2 1 4 3 2 1 3 2 1 2 1 1
(7) 输出如下图形,其中的行数从键盘输入:
A ABC ABCDE ABCDEFG ABCDE ABC A
(8) 用循环计算出“score 表”中各个学生的平均成绩,再根据平均成绩用
多路选择分支结构确定其奖学金,并将“student 表”中的“奖学金”字
3. 分析程序的运行结果,并说明该程序的功能。

(1) SET TALK OFF
k = 1 s = 0
DO WHILE k <= 10 s = s + k k = k + 1 ENDDO ? " s = ", s (2) CLEAR
a = 0
b = 0
DO WHILE a < 100 a = a + 1
IF INT( a / 2 ) = a / 2 LOOP ELSE b = b + a ENDIF ENDDO ? "b = ", b
五、过程式程序设计
1. VFP 的过程式程序设计方法。

2. 完成如下程序设计: (1) 运用公式
)!
(!!m n m n 求m
n C 之值,其中,n 、m 为从键盘输入的正整数且
n > m ,其中求阶乘和组合数的内容均设计为过程或者函数。

(2) 编写自定义函数CheckEven(Num),其功能为:若其数值型参数Num 仅
由偶数字( 0, 2, 4, 6, 8 )组成时(如86420),函数返回.T.,否则返回.F.(如68032),并编写程序调用该函数。

提示:
函数体中重复使用“Num % 10”以及“Num = Num / 10”来获得Num 的各位数字,并判断这些数字是否全为偶数。

(3)编写一个自定义函数,实现将任意的日期型表达式转换为中文大写形
式,如{^2009-12-15}转换为:“二零零九年十二月十五日”。

(4)基于“student表”和“score表”,完成一个简单的“学籍管理系统”,
要求将每一个功能作为一个单独的过程,在主控程序中按照用户输入的不同要求分别调用这些过程,其基本功能模块如下:
a.查询,按姓名或者学号,并显示该学生的信息;
b.插入,增加新的学生记录或者增加新的成绩信息;
c.删除,按学号删除该学生的信息以及“score表”中所有成绩记录;
d.修改,按学号修改该学生的成绩信息。

有余力的同学也可以在此基础上,加进“course表”,并增加操作课程的功能,完成一个比较简单的学生成绩管理系统。

附录:VFP6.0的程序设计
一、程序文件的建立、修改和运行方法
1.建立程序文件的3种方法
(1)项目管理器:代码选项卡中的程序项→新建
(2)文件菜单:新建→程序→新建文件
(3)命令窗口键入:MODIFY COMMAND
2.运行程序文件的4种方法
(1)项目管理器:运行
(2)程序菜单:运行,利用对话框选择要运行的程序
(3)命令窗口键入:DO 程序文件名
(4)选取代码行→右击快捷菜单→运行所选区域
3.程序文件的编辑修改方法
(1)项目管理器:选定程序文件→修改
(2)文件菜单→打开
(3)MODIFY COMMAND 程序文件名
二、顺序结构程序设计
顺序结构的程序运行时按照语句排列的先后顺序,一条接一条地依次执行,是程序的最基本结构。

例1:根据输入的半径值,编程计算相应的圆面积。

解题思路:
编程时,首先用输入语句输入圆半径,然后用公式计算圆面积,最后用输出语句输出圆面积
示例程序:
SET TALK OFF
CLEAR
INPUT "请输入圆的半径:" TO r
s = 3.14 * r * r
? "圆的面积是:" + ALLTRIM( STR( s, 19, 2 ) )
SET TALK ON
例2:在学生表中,根据从键盘上输入的学生姓名,显示该学生的基本情况。

解题思路:
程序首先要打开“student表”文件,然后用输入语句输入学生姓名,接着将记录指针定位在该学生,显示该学生信息,最后关闭表文件。

示例程序:
SET TALK OFF
CLEAR
USE student
ACCEPT "请输入学生姓名:" TO stuname
LOCATE FOR 姓名= stuname && 没有考虑查找失败
DISPLAY
USE
SET TALK ON
例3:编写程序,按照用户输入的表文件名与表中的记录号显示记录内容。

解题思路:
首先从键盘输入表文件名,然后打开该表文件,接下来输入记录号,然后将记录指针移至该记录并显示,最后关闭该表文件。

示例程序:
SET TALK OFF
CLEAR
ACCEPT "请输入表文件名:" TO filename
USE &filename
INPUT "请输入记录号:" TO recordno
GO recordno
DISPLAY
USE
SET TALK ON
三、选择结构程序设计
分支选择结构是根据测试条件的结果执行不同的操作,即程序中某些命令的执行受某一条件的控制,当条件成立时,执行其中的一部分命令,不成立时执行另外一部分的命令,即根据条件决定做什么操作。

VFP中实现条件分支有两种格式:
二路分支选择结构(IF…ENDIF) 和多路选择分支结构(DO CASE…ENDCASE),其中IF…ENDIF语句又可以分成带ELSE与不带ELSE 两种格式。

例1:已知一元一次方程ax + b = 0,输入a、b值后,求解x值。

解题思路:
该方程只有当a不等于零时,方程才有解x = –b / a,而当a = 0时就不用求解。

示例程序:
SET TALK OFF
CLEAR
INPUT "a = " TO a
INPUT "b = " TO b
IF a <> 0
? "x = ", -b / a
ENDIF
SET TALK ON
例2:从键盘输入学生的学号,在“score表”中计算该学生的平均成绩,并判断平均成绩是否大于60分,分别显示“平均分及格”和“平均分不及格”
信息,如果该学生的学号不在表中,则提示相应的信息。

解题思路:
从键盘输入的学号在“score表”中确实存在时,才能统计平均成绩,输入的学号一旦在“成绩表”中找不到,程序运行之后会因为找不到满足条件的记录而出错,因此必须检测输入输入的学号是否存在。

程序框架如下:
(1)打开相应的数据表文件;
(2)输入学号;
(3)查找该学号是否存在(可以使用顺序查找或索引查找);
(4)如果输入的学号在“成绩表”中存在,则进行步骤5,否则显示信
息说明该学号不存在,进行步骤6;
(5)计算该学号学生的平均成绩,并判断平均成绩是否大于等于60分,
如果是则显示“平均分及格”信息,否则显示“平均分不及格”;
(6)结束对表中信息的操作,关闭相应的表文件。

示例程序:
SET TALK OFF
CLEAR
USE score
ACCEPT "请输入学号:" TO stuno
LOCATE FOR 学号= stuno
IF FOUND( )
A VERAGE 成绩TO scravg FOR 学号= stuno
? scravg
IF scravg >= 60
?? "平均分及格!"
ELSE
?? "平均分不及格!"
ENDIF
ELSE
? "该学号不存在!"
ENDIF
USE
SET TALK ON
例3:扩充例2的程序,按平均成绩分别显示出“优”(90~100),“良”(80~89),“中”(70~79),“及格”(60~69)和“不及格”(低于60分)。

解题思路:
程序的基本框架同例2,差别只是在于步骤5,首先判断平均成绩是否大于等于90,是则显示“优”;否则再判断平均成绩是否大于等于80,是则显示“良”,否则继续判断平均成绩是否大于等于70…,依次类推,直到该平均成绩小于60,则显示“不及格”,因此要用到嵌套的IF…ENDIF结构。

示例程序1:
SET TALK OFF
CLEAR
USE score
ACCEPT "请输入学号:" TO stuno
LOCATE FOR 学号= stuno
IF EOF( )
? "该学号不存在!"
ELSE
A VERAGE 成绩TO scravg FOR 学号= stuno
IF scravg >= 90
grade = "优"
ELSE
IF scravg >= 80
grade = "良"
ELSE
IF scravg >= 70
grade = "中"
ELSE
IF scravg >= 60
grade = "及格"
ELSE
grade = "不及格"
ENDIF
ENDIF
ENDIF
ENDIF
? stuno, scravg, grade
ENDIF
USE
SET TALK ON
由于IF只能在两种情况下做出选择,如果出现两种以上的情况,则需要采用嵌套的IF语句,这样不仅增加了程序编写的难度,也影响程序的可读性。

此时可以用多分支DO CASE…ENDCASE语句来简化程序,上述程序因此也可以改写如下。

示例程序2:
SET TALK OFF
CLEAR
USE score
ACCEPT "请输入学号:" TO stuno
LOCATE FOR 学号= stuno
IF EOF( )
? "该学号不存在!"
ELSE
A VERAGE 成绩TO scravg FOR 学号= stuno
DO CASE
CASE scravg >= 90
grade = "优"
CASE scravg >= 80
grade = "良"
CASE scravg >= 70
grade = "中"
CASE scravg >= 60
grade = "及格"
OTHERWISE
grade = "不及格"
ENDCASE
? stuno, scravg, grade
ENDIF
USE
SET TALK ON
四、循环结构程序设计
循环结构指按问题的需要,多次重复执行一行或者多行语句,也就是说某些语句在某条件成立时,需要重复执行,直到条件不成立时才结束重复执行。

循环结构中特别需要注意的是:一定有控制退出循环的语句,以避免出现死循环现象。

在VFP中有三种循环语句:
步长型循环FOR…ENDFOR、条件型循环DO WHILE…ENDDO和基于数据表的循环SCAN…ENDSCAN。

在循环体中再次包含有循环语句时,统称为多重循环。

例1:输入10个数,统计大于零的数值个数并计算其总和。

解题思路:
由于是通过累加求和,因此可以用已知循环次数的程序进行计数操作来实现。

程序框架如下:
(1)给循环变量赋初值(从1开始)并预设存放累加结果的变量(初值为
0,大于0的个数sn和数值之和st);
(2)循环开始,如果循环变量的值没有超过10,则进入循环内的操作;
否则结束循环操作,直接执行(3);
(2.1)从键盘输入一个数给变量x,并判断它是否大于0,如果是
则sn = sn + 1,st = st + x,否则直接进行(2.2);
(2.2)循环变量当前值加1;
(2.3)回到循环起点,重新判断循环条件;
(3)输出显示累加的结果。

示例程序:
SET TALK OFF
sn = 0
st = 0
n = 1
DO WHILE n <= 10
INPUT "输入数据:" to x
IF x > 0
sn = sn + 1
st = st + x
ENDIF
n = n + 1
ENDDO
? "大于零的个数为:", sn
? "大于零的数值之和为:", st
SET TALK ON
例2:逐条记录输出“student表”中男学生的详细信息。

解题思路:
由于操作过程是对表文件记录逐条进行,因此可以使用DO WHILE…ENDDO结构来实现,并且用EOF( )函数测试是否已到文件尾。

显然,可以直接在LIST 或者DISPLAY 命令中使用条件语句来实现该功能,但是其输出格式并不能按照自己的需要来定制。

示例程序:
SET TALK OFF
CLEAR
USE student
LOCATE FOR 性别= "男"
DO WHILE .NOT. EOF( )
? SPACE(10), 学号, SPACE(10), 姓名, SPACE(10), 性别
CONTINUE
ENDDO
USE
SET TALK ON
例3:用SCAN…ENDSCAN统计“student表”中姓刘的女生人数。

解题思路:
由于SCAN语句可以带条件,因此直接在条件中过滤学生性别即可。

程序框架如下:
(1)首先预设存放累加结果的变量n(初值为0);
(2)打开学生表文件;
(3)用SCAN语句循环搜索满足条件的学生(姓刘的女生),每搜索到一
个,变量n = n + 1;
(4)输出显示累加结果,并关闭表文件。

示例程序:
SET TALK OFF
SET EXACT OFF
CLEAR
n = 0
USE student
SCAN FOR 性别= "女" .AND. 姓名= "刘"
n = n + 1
ENDSCAN
? "学生表中女生的人数是:", n
USE
SET TALK ON
例4:用FOR…ENDFOR实现从键盘输入一个数判断它是否为质数。

解题思路:
所谓质数,就是只能被1和它本身整除的自然数,因此根据这一特性就可利用循环来判断给定的数是否能被1到该数之间的某个数整除(不包含1和该数本身),如无一被整除,说明该数就是质数,否则不是质数。

程序框架如下:
(1)首先输入一个自然数至内存变量x;
(2)循环开始时,循环变量的初值为2,循环终值为该数减1,退出循
环后,直接跳到步骤(3);
(2.1)判断给定的数能否被循环变量整除;如果是则退出循环,说
明该数不是质数;否则继续判断能否被其他的数整除;
(2.2)循环变量递增1;
(3)输出判断结果。

示例程序:
SET TALK OFF
CLEAR
INPUT "输入任意一个数:" to x
FOR i = 2 TO x - 1
IF INT( x / i ) = x / i && 或者使用x % i = 0
EXIT
ENDIF
ENDFOR
IF i = x
? ALLTRIM( STR( x, 19 ) ) + "是质数!"
ELSE
? ALLTRIM( STR( x, 19 ) ) + "不是质数!"
ENDIF
SET TALK ON
例5:编写一个程序可以重复计算任意数的阶乘,直到按任意键结束计算。

解题思路:
显然计算某数的阶乘可以使用循环来完成,为了实现重复按照输入来计
算阶乘,于是外层使用永真循环,即采用二重循环结构来实现,从键盘输入要计算阶乘的数,退出循环的条件是按下除“Y”或“y”外的任意键。

示例程序:
SET TALK ON
CLEAR
DO WHILE .T.
INPUT "请输入数据:" TO x
t = 1
i = 1
DO WHILE i <= x
t = t * i
i = i + 1
ENDDO
? ALLTRIM( STR( x, 19 ) ) + "!=", t
WAIT "继续计算阶乘吗?(Y/N)" TO yn
IF UPPER(yn) = "Y"
LOOP
ELSE
EXIT
ENDIF
ENDDO
SET TALK ON
例6:编程输出下列图形。

1
222
33333
4444444
555555555
4444444
33333
222
1
解题思路:
平面趣味图案输出显示时,通过横向和纵向两个坐标的二重循环控制来完成。

程序框架如下:
(1)外循环除控制图案组成元素外,还要控制输出的行数。

从图中可知,输出显示的行数与给定的图案半高n(5)有关,可以归
纳出外循环的循环变量初值为1,终值为2n - 1(11)。

(2)内循环除控制图案组成元素外,还要控制输出的列数。

从图中可知,尽管每行输出的列数都不相同,但每行输出的列数与
当前的行数i有关,同样可以归纳出规律。

可以将该图案分解为两个三角形,上面三角形每行中的列数是逐行
递增的,下面三角形每行中的列数是逐行递减的,所以内循环应当
分为两部分分别处理两个三角形。

(3)内循环控制的所有列输出在同一行中,且每列之间有一空格,但是外
循环控制的所有行应当换行后,输出在不同的行中。

示例程序:
SET TALK OFF
CLEAR
n = 5
p = 2 * n - 1
FOR i = 1 TO p
IF i <= n
? SPACE( n - i + 1 )
FOR j = 1 TO 2 * i - 1
?? STR( i, 1 )
ENDFOR
ELSE
? SPACE( i - n + 1 )
FOR k = 1 TO 2 * ( 2 * n - i ) - 1
?? STR( 2 * n - i, 1 )
ENDFOR
ENDIF
ENDFOR
SET TALK ON
五、过程式程序设计
采用过程与自定义函数可以将复杂的问题简单化,实现模块化的设计。

过程没有返回值,定义的引导词为PROCEDURE,自定义函数则有一个返回值,引导词为FUNCTION;
如果过程的实参是变量则传址(传引用),如果实参是常数或者表达式则传值,但是自定义函数的调用永远传值。

例1:用子程序实现计算s = a! + b! + c!,其中a、b、c由键盘输入。

解题思路:
子程序实现的功能:接收主程序传递过来的参数,用循环结构实现求该数的阶乘,并将阶乘返回主程序。

主程序的功能为:从键盘输入a、b、c三个数,然后分别调用子程序求三个数的阶乘,并计算累加和s
示例程序:
*******主程序main.prg
SET TALK OFF
CLEAR
INPUT "a = " TO a
INPUT "b = " TO b
INPUT "c = " TO c
s = 0
ps = 1
p = a
DO fac
s = s + ps
p = b
DO fac
s = s + ps
p = c
DO fac
s = s + ps
? "s = ", s
SET TALK ON
*******子程序fac.prg
ps = 1
FOR i = 1 TO p
ps = ps * i
NEXT
RETURN
例2:编写一个自定义函数,分别将分数等级的优、良、中、及格和不及格转换成95、85、75、65和50分。

示例程序:
FUNCTION grade2score
PARAMETERS grade
DO CASE
CASE grade = "优"
score = 95
CASE grade = "良"
score = 85
CASE grade = "中"
score = 75
CASE grade = "及格"
score = 65
OTHERWISE
score = 50
ENDCASE
RETURN score
例3:编写一个自定义函数,计算出给定金额数(整数)需要的最少钞票张数。

假设钞票面额共有7 种币值:100, 50, 20, 10, 5, 2, 1元(例:金额23451元为234张100元;1张50元;1张1元,其他面额0张,共计236张)。

解题思路:
为达到钞票张数最少,先尽量多取大面额钞票,由大到小面额进行;
由于7 种面额不是等差数列,为了能用循环处理,将7 种币值存储在数组中,因为需要尽量多找大面额钞票,7 种币值应当按照面额递减存放。

示例程序:
*******主程序main.prg
SET TALK OFF
CLEAR
SET PROCEDURE TO sub.prg
DIMENSION money(7)
money(1) = 100
money(2) = 50
money(3) = 20
money(4) = 10
money(5) = 5
money(6) = 2
money(7) = 1
INPUT "请输入金额:" TO m
? ALLTRIM( STR( m, 19 ) ) + "中包含指定面额:"
n = 0 && 张数累计
p = m && 中间变量
FOR i = 1 TO 7
r = num( p, money(i) ) && 调用自定义函数求张数
IF r <> 0
? STR( money(i), 3 ) + "元的张数为:" + STR( r, 10 ) + "张。

"
p = p % money(i) && 剩余的金额
n = n + r
ENDIF
ENDFOR
? "共计" + STR( n, 8 ) + "张"
CLOSE PROCEDURE
SET TALK ON
RETURN
*******子程序sub.prg
FUNCTION num
PARAMETERS x, y
RETURN INT( x / y ) && 包含的张数
ENDFUNC。

相关文档
最新文档