VFP程序设计3
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
财管第25—28学时(程序设计3,4次)
前两次课已交待了程序设计的三种结构,后三次课通过系列例题强化概念、补充知识、介绍算法。
一、程序流程
例1、CASE语句从上到下执行,只要一个语句块符合条件,就退出分支程序。
复习概念:IF和CASE分支语句只执行一个分支模块
例1、case语句成绩,如果首句为合格,则90分无法做到优秀
set talk off
clear
input"请输入成绩:" to a && 输入95,或输入1000
do case
case a>=60 &&结果是"合格"。
纠正方法是将case a>90放在首行,或在此写成&&case a>=60 and a<75
?"合格"
case a>90
?"优秀"
endcase
set talk on
return
例2、FOR循环结构(指定次数循环)复习
概念①:FOR循环变量不必先赋值,首次执行初值,前行赋值也无用。
概念②:循环终值执行
概念③:不指定步长默认为1。
概念④:步长如果为正数,则循环变量的初值必须小于终值;反之亦反。
set talk off
clear
X=0 &&循环变量不需要先赋值,但其它变量仍需先赋值才以使用。
for i=1 to 5 &&循环终值仍可执行,共循环5次。
x=x+i
endfor
?X &&X=15
set talk on
return
该循环结构:首先将初值赋给循环变量I,然后再检查循环变量是否超过终值。
循环次数等于循环变量的初值与终值之差的绝对值除步长再加1(因为循环初值必执行)
思考题①:如果“?X”放在“x=x+I”之前,结果是0,1,3,6,10
思考题②:如果“?X”放在“endfor”之前,结果是1,3,6,10,15
例3、DO while循环结构(当循环)复习
概念①:循环变量必须先赋值
概念②:循环终值不执行
概念③:步长必须指定。
set talk off
clear
X=0
i=0
do while i< 5
x=x+i
i=i+1
enddo
?X &&10(各次循环分别是:0,1,3,6,10)
set talk on
return
思考题①:如果“?X”放在“x=x+I”之前,结果是0,0,1,3,6
思考题②:如果“?X”放在“enddo ”之前,结果是1,3,6,10,15
例4、FOR循环完成循环后,循环终值=终值+步长
for i=1 to 10
?I &&如step1,则1,2,3,…10;若step 3,则1,4,7,10
endfor
?I && I=11。
若step 3,I=13
步长所在位置的理解方式:
for i=1 to 10 setp x(step x写在此用于检查格式,step –1则不执行循环)……...
I=I+step 1(或I=I+step x) &&只有写在此,才可理解循环初值必执行。
Endfor
循环结束后, I=循环变量终值+1(或I=循环变量终值+step x)
FOR循环变量步长实际位置的理解:step的位置应在endfor的上一行
例5、DO while循环完成循环后,循环终值=终值
set talk off
clear
i=0
do while i< 10
?I &&0,1,2,3 (9)
i=i+1
enddo
?I && I=10
set talk on
return
作业与思考:DO while循环和FOR循环的互相替换。
例6、循环辅助子句LOOP(显示奇偶数)
LOOP概念:无条件地回到循环首句,不再执行LOOP到endfor之间的语句。
也可以理解为直接执行endfor语句,再回到循环首句。
步骤1、首先For循环中只放一个?i,则显示1,2,3...20个记录//
步骤2、再介入if 语句,只显示奇数
set talk off
clear
for i=1 to 20
&& loop如果放在此处,则循环语句永远不会执行
if mod(i,2)=0
loop
endif
?i && 只显示1,3,5....19奇数
endfor
set talk on
return
思考1:loop放在for i=1 to 20之下一行。
结果是:循环体永不执行。
思考2:“?I”放在if语句块的loop后面。
结果是:虽执行语句,但不显示结果。
因符合条件的被loop,不符合条件的到endif.
思考3:如何显示偶数?应将?I语句放在if mod(i,2)=0之后,在loop语句之前
例7、循环辅助子句EXIT(救活死循环)
EXIT概念:无条件地跳出本层循环,不再执行EXIT到endfor、包括也不执行endfor语句。
(注意:不能跳出外层循环)
步骤1、先不写IF语句,死循环
步骤2、加入IF语句模块,就可以解除死循环。
set talk off
clear
i=0
do while .t.
i=i+1
?i
if i>=40
exit
endif
enddo
set talk on
return
例8、循环嵌套1
set talk off
clear
for i=1 to 4
for j=1 to 5
&& 内循环终值大于初值n次,则对外循环的一个值执行n+1次。
? i && 11111222223333344444
endfor
endfor
set talk on
return
例9、循环嵌套2(步长负值):实验10的program8打印三角形的程序流程:set talk off
clear
for x=1 to 5 &&将此句改为for x=5 to 1 step-1
??space(2*(5-x))
for y=1 to 2*x &&尖三角形,将此句改为for y=1 to 2*x-1 即可
??"#"+space(1) && 或“,space(0.5)”因逗号占半个字符。
注意:space()的值是字符型
endfor
?
endfor
set talk on
return
思考1、变为倒三角形
答案:将外循环for x=1 to 5改为for x=5 to 1 step-1即可。
思考2、变为尖三角形:
答案:将内循环for y=1 to 2*x改为for y=1 to 2*x-1 即可
例10、对数据表的记录进行倒扫描
A、当循环
set talk off
clear
use xsxx
go bottom
?" 记录号","姓名","性别"
do while not bof()
?recn(),姓名,性别
?"-----------------"
skip-1 &&如无此句,只显示最后一条记录,且是死循环。
enddo
use
set talk on
return
概念:此循环变量不需要在循环体加步长,当循环在循环变量的值为数字时,需要先赋初值,并且在循环体内注明步长,否则是死循环。
B、FOR循环:step-1控制循环次数;skip-1控制记录定位
set talk off
clear
use xsxx
go bottom
?" 记录号","姓名","性别"
for i=1 to 10000 step -1
?recn(),姓名,性别
?"-----------------"
skip-1
endfor
use
set talk on
return
思考①:如果无skip-1。
答:一直显示第10号记录“严冰”
思考①:如果无step-1。
答:则不显示
二、应用编程
例11、编程显字母
题目:显示26个大写字母(小写字母的ASCII码为97-122)
步骤1、显示A—Z大写字母
步骤2、每5个字母一行:释放被注释的语句
set talk off
clear
&& n=0
for i=65to 90 && ASCII码值65为A,97为Z
&& n=n+1
?? chr(i) && 同行显示//chr( )是将ASCII码值转换为字符的函数
&& if mod(n,5)=0
&& ?
&& endif
next
set talk on
return
例12、编程实现倒序字母排列——步长为负值
set talk off
clear
accept"请输入字符串:"to zfc &&从键盘输入字符串
n=len(zfc) && 测试字符串长度,以确定循环数nzfc="" && 定义新字符串变量(字符类型)for i=n to 1 step -1
nzfc=substr(zfc,i,1) &&从第I位取1个字符显示,而I从N开始??nzfc
next
set talk on
return
试题:此程序功能,应答:将字符串倒过来排。
例13、编程分母累加.prg (注释句为do while方式的语句)
题目:1+1/2+1/3+1/4+1/5....+1/99+1/100
set talk off
clear
&& i=0
s=0
for i=1 to 100
&&do while i<100 && 从0开始循环,共100次
&& i=i+1
s=s+1/i
next
&&enddo
?s && 5.1874
set talk on
return
例14、编程分母累间加减(注释句为do while方式的语句)
题目:讲解1-1/2+1/3-1/4+1/5....-1/99+1/100
set talk off
clear
&& i=0
s=0
for i=1to 100
&&do while i<100 && 从0开始循环,共100次
&& i=i+1
s=s+(-1)^(i+1)/i && ^的优先级高,I可直接放在除号之下
&&/此句亦可分解为A段或B段程序
next
&&enddo
?s && 0.6882
set talk on
return
A段程序
if mod(i,2)=0
s=s-1/i
else
s=s+1/i
endif
B段程序
if int(i/2)=i/2
s=s-1/i
else
s=s+1/i
endif
三、常见算法
㈠、穷举算法
例15、穷举水仙花方法1
水仙花数:是指一个n(>=3)位数字的数,该数本身等于各位数字立方之和,如:153=1+125+27
题目:使用For循环嵌套的方法编写程序,将100-999以内的”水仙花数”打印出来。
步骤1、明瞭三重循环的运算结果,将三个循环的终值分别定为2,3,4。
再在循环体内写入:?a,b,c
结果是:100,101,102,103,104;110,111,112,113,114。
,234 步骤2、
set talk off
clear
for a=1 to 9 && 外循环执行一次,内循环执行全部,此3个for
循环相当于100—999
for b=0 to 9
for c=0 to 9 && 第一个循环是a=1,b=0,c=0 即100
if a*100+b*10+c=a^3+b^3+c^3
?a*100+b*10+c && 3位数的水仙花共有153,370,371,407共4个endif
endfor
endfor
endfor
set talk on
return
思考①:求0—999的水仙花。
答案:将最外循环的初值定为0
思考②:求100—9999的水仙花。
答案:
1、增加一个内循环for d=0 to 9,且外循环为0—9(仍是4个,因为1000到9999之间无水仙花)
2、if a*1000+b*100+c*10+d=a^3+b^3+c^3+d^3
?a*1000+b*100+c*10+d
例16、穷举水仙花方法2
题目:使用函数方法编写程序,将100-999以内的”水仙花数”打印出来。
set talk off
clear
for i=100 to 999
a=int(i/100) &&1,2,3,4,5,6,7,8,9 即到200时才等于2
b=int((i-a*100)/10) &&0,1,2,3,4,5,6,7,8,9 即到110时才等于1
c=int(i-a*100-b*10) &&0,1,2,3,4,5,6,7,8,9 即到101时才等于1
if i=a^3+b^3+c^3
?i && 3位数的水仙花共有153,370,371,407共4个
endif
endfor
set talk on
return
例17、穷举水仙花方法3
题目:使用函数编写程序,将100-999以内的”水仙花数”打印出来。
set talk off
clear
n=0 && 水仙花个数
for i=100 to 999
s=str(i,3)
a=val(left(s,1))
b=val(subs(s,2,1))
c=val(right(s,1))
if i=a^3+b^3+c^3
?i && 3位数的水仙花共有153,370,371,407共4个n=n+1
endif
endfor
?n && 共4个
set talk on
return
例18、求素数
素数就是质数。
它除了能表示为它自己和1的乘积以外,不能表示为任何其它两个整数的乘积。
例如,15=3*5,所以15不是素数;又如,12=6*2=4*3,所以12也不是素数。
另一方面,13除了等于13*1以外,不能表示为其它任何两个整数的乘积,所以13是一个素数。
set talk off
clear
n=0
flag=.f.
input"请输入素数的上限范围:" to x
for i=1 to x
flag=.t. && flag=.t.必须要放在循环体内头部,否则到i=4时,
flag=.f.,以后的素数就无法显示了。
for j=2 to i-1 && 因为1和i均可被1与其本身相除,在内循环中只
要与2—i-1中的数相除即可。
I=1,2时,内循环不执行。
if mod(i,j)=0 && 如果i能与内循环中的数整除,则该i不是素数 flag=.f.
exit && 只要遇到第一个能整除的情况,即跳出内循环,换
一个外循环的i值。
endif
endfor
if flag
?i,"是素数"
n=n+1
endif
endfor
?n && 素数的个数
set talk on
return
思考1:为什么for j=2 to i 只有一个素数“1”
答:除了1在内循环不执行而结果是素数外,其他任何数均可被其本身相除,而J的终值=I,在内循环中的MOD值都为0,结果都是.f.,故都不是素数。
思考2、为什么内循环初值是1时,无所谓“素数”?
答:内外循环初值相同,则所有的数MOD(I,j)=0,在循环的初值处即被枪毙,跳出内循环。
例19、搬运砖头
【问题描述】36 块砖, 36 人搬。
男搬 4 ,女搬 3 ,两个小儿抬一砖。
要求一次全搬完。
问需男、女、小儿各若干?
【问题分析】题目要我们找出符合条件的男生、女生和小孩的人数。
对于男生来说,至少要有一人;每个男生可以搬4 块砖,那么 36 块砖最多 9 个男生足够,共有 9 种不同取值。
同样,女生有 12 种不同取值。
两个小孩抬一块砖,至少要有两个小孩,最多 36 个,并且小孩的人数必须是个偶数,所以小孩的人数可以取 18 种不同的值。
最坏情况下,男生、女生和小孩的人数可以是9 × 12 × 18 = 1944 种不同组合。
假设男生人数为 x ,女生人数为 y ,小孩人数为z 。
可以构建一个三重循环求出最终结果。
set talk off
clear
for x=1 to 9
for y=1 to 12
for z=2 to 36 step 2
if x*4+y*3+z/2=36 and x+y+z=36
?x,y,z && 3,3,30
exit
endif
endfor
endfor
endfor
?x,y,z && 结果为10,13,38 说明Exit只能跳出当前(本层)循环
set talk on
return
注意:如果没有and子句,则有多种排列,但不符合36个人的要求。
例20、穷举百鸡百钱
“百鸡百钱”问题,公鸡五文钱一只,母鸡三文一只,小鸡一文三只,拿100文钱,要求公鸡、母鸡、小鸡都要,数量不多不少正好一百只。
写出“百鸡百钱”需要符合的条件
假设公鸡数量为X只,母鸡数量为Y只,小鸡数量为Z只,则判断条件为:X+Y+Z=100(只)
5*X+3*Y+Z/3=100(元)。
程序代码:
set talk off
clear
for x=1 to 19 &&根据各鸡都要的原则,其实本句循环终值最大为19
for y=1 to 31 && 本句循环终值最大为31
for z=3 to 93 step 3 && 本句循环终值最大为93
if x*5+y*3+z/3=100 and x+y+z=100
&& 如果没有and子句,则有许多种排列。
?x,y,z && 三种情况:4,18,78//8,11,81//12,4,84
exit
endif
endfor
endfor
endfor
?x,y,z && 21,34,102 说明Exit不能跳出外层循环set talk on
return
㈡、递推算法:
例21、递推算法斐波那契数列.prg
斐波那契数列:第1项的值为1,第2项的值为2,从第3项起为其前两项之和。
列出20项斐波那契数列。
【问题分析】
开始的条件:x(1)=1 x(2)=2,从第3项起其迭代表达式为x(i)=x(i-1)+x(i-2)
复习:数组变量
dimension x(20,2) &&在命令窗口定义一个二维数组,20行,2列。
list memo like x* &&在主窗口列出数组变量元素。
x(19,1)=2 &&向数组元素赋值
?x(19,1) &&已经赋值 2
list memo like x* &&只有x(19,1)被赋值
set talk off
clear
dimension x(20)
for i=1 to 20
x(i)=i &&为x(1),x(2)赋值,否则后句无法执行。
&&之后的x(i)值将在后面被刷新。
if i>2
x(i)=x(i-1)+x(i-2)
endif
?x(i) && 1,2也在内,其实应当从3开始才算是斐波那契数列endfor
set talk on
return
如果斐波那契数列:第1项的值为0,第2项的值为1,从第3项起为其前两项之和。
列出20项斐波那契数列。
程序是:
set talk off
clear
dimension x(20)
for i=0 to 19
x(i+1)=i &&为x(1),x(2)赋值,否则后句无法执行。
&&之后的x(i)值将在后面被刷新。
if i>1
x(i+1)=x(i)+x(i-1)
endif
?x(i+1) && 1,2也在内,其实应当从3开始才算是斐波那契数列endfor
set talk on
return
例22、猴子吃桃。
有一群猴子摘来了一批桃子,猴王规定每天只准吃一半加一只(即第二天吃剩下的一半加一只,以此类推),第九天正好吃完,问猴子们摘来了多少桃子?set talk off
clear
s=0
dimension x(9)
x(9)=2
&& 人工推算第9天未吃之前一定是2只桃子,由此递推第1天未吃之前是多少只挑子,即求x(1)。
?"x(9)=",x(9) &&把第9天的实际桃数放在第一行.
for i=8 to 1 step -1
x(i)=x(i+1)*2+2
&& +2:x(i+1)*2是昨天的半数少一个,因此昨天的桃子应是x(i+1)*2+2 s=s+x(i)
?"x("+str(i,1)+")=",x(i),x(i)-x(i+1)
endfor
?" 当天初桃数"," 当天吃桃数"
?"桃子总数为:",x(1) && 1022
set talk on
return
程序运行结果为:
㈢、排序算法:
冒泡排序法是一种非常有趣的排序方法.在排序过程中,每一次仅进行相邻的两个数据的比较,较小的数据每次只能向上移动一个位置,缓慢地向上升到頂部,其过程就像气泡逐渐上升,故而得名。
例23、冒泡排序由大到小
set talk off
clear
dime a(10)
for i=1 to 10
a(i)=int(50+51*rand()) &&产生从51-101之间的整数
??a(i) &&按次序显示各个数组元素的值
endfor
? && 换行,以下程序用于排序
?
for i=1 to 9 && 外循环a(1)-a(9)与内循环的a(2)-a(10)进行比较。
for j=i+1 to 10
&& 每个a(i)与内循环进行全面比较,但每一轮下来,该a(i)就是最大的数,该数不再参与此后的比较,因此内循环的起始值为i+1
if a(i)<a(j)
k=a(i)&& 将a(i)保存在K之中
a(i)=a(j)
a(j)=k
endif
endfor
endfor
for i=1 to 10
??a(i)
&& 将排序后的a(i)值同行显示,以与前已显示的未排序的a(i)进行比较. endfor
set talk on
return
例24、冒泡排序找最大数与位置,由大到小排序
set talk off
clear
dime a(5,5)
for i=1 to 5
for j=1 to 5
a(i,j)=int(100+900*rand()) &&产生一个100—1000的随机整数。
??a(i,j)
endfor
?
endfor
max=a(1,1)
p=1
q=1
for i=1 to 5
for j=1 to 5
if max<a(i,j)
max=a(i,j)
p=i
q=j
endif
endfor
endfor
?max,p,q
set talk on
return
补充内容
Return语句三个作用:
1.Return:返回调用点
2.Return To 某个子程序
3.Return to master 到主程序。
一、For循环的各量变化概念
例8for循环累加器.prg (高斯数学题,结果为5050)
程序如下:
note :讲解累加器的各值变化,步长,for循环句式
set talk off
clear
s=0
for i=1 to 100
s=s+i
endfor && endfor 与next同样作用,可以互相代替.
?s
set talk on
return
讲解要点:
1、结构:for…..endfor|next
2、步长与循环次数
for i=1 to 100 && 本句尾有默认的可少省略的"step 1"//讲解"step -x"时循环初值必须大于末值,即i=100 to //讲解循环次数=int((循环大值-循环小值)/步长)+1
3、赋值概念与数学等式在概念上的区别
s=s+i && 是赋值的意思,如果从数学角度则本句不可理解,讲不通//
二、For循环步长、初值与终值、循环变量值的变化
1、默认步长step
2、终值小于初值,则步长必须为负值,否则不执行
set talk off
clear
for i=10 to 1 step -1
?I && 10,9 (1)
endfor
?I && 0。
如果for I=1 to 10,则此处为11,说明循环首句仍
执行了,只不过不符合条件,循环语句未执行。
set talk on
return
3、循环结束时,循环变量的值=循环终值+步长
思考题:打印奇数,偶数
打印奇数
set talk off
clear
for i=1 to 10 step 2
?i
endfor
set talk on
return
显示偶数
set talk off
clear
for i=1 to 10
if mod(i,2)=0
?i
else
loop
endif
endfor
set talk on
return
三、For循环与Do循环的共性、互变以及指针的区别
仍以高斯数学题为例。
1、共性:循环条件的判断均为逻辑值,值为T时,执行循环语句
2、互变与区别:将For循环改为Do循环方法
⑴循环的首尾语句For…/endfor 改为do while…./enddo
⑵do循环需要加上指针移动语句。
(区别1)
⑶do循环需要对循环变量赋初值,要注意该例满足100次循环。
(区别2)
⑷区别3:do 循环指定对一个值进行判断,适用于表的查询,如not eof()
而for循环的值是一个范围。
set talk off
clear
use xsxx
do while not eof()
locat for 姓名="丁明"
disp
exit
enddo
set talk on
return
㈢扫描循环scan—endscan:专用于数据库的循环操作命令
例2、数据计算
set talk off
clear
cj=0 && 成绩
rs=0 && 人数
use xsxx
?" 记录号","姓名","性别"
scan for 性别="女"
cj=cj+入学成绩
rs=rs+1
?recn(),姓名,性别
?"-----------------" &&显示5位女生
endscan
?cj,cj/rs && 显示5位女生的入学成绩合计,以及平均入学成绩
set talk on
return
例3、DO while 循环对数据表的操作
note :用同一个程序说明For循环,do循环与Scan循环的共性与特点
set talk off
clear
use xsxx
?" 记录号","姓名","性别"
do while not eof()
?recn(),姓名,性别
?"-----------------"
skip && Do循环不能自动移动指针,如果将Skip屏蔽,
则死循环"许淳明"
enddo
set talk on
return
例4、FOR 循环对数据表的操作
注意::For循环对表的操作不能自动移动指针,仍需要Skip
note :用同一个程序说明For循环,do循环与Scan循环的共性与特点
set talk off
clear
use xsxx
?" 记录号","姓名","性别"
for i=1 to 10
?recn(),姓名,性别
?"-----------------"
skip &&FOR自动增加循环变量,但不能移动指针,此Skip仍需要. endfor
set talk on
return。