第7章过程.docx
《第7章过程.docx》由会员分享,可在线阅读,更多相关《第7章过程.docx(22页珍藏版)》请在冰豆网上搜索。
第7章过程
第7章过程
使用“过程”是实现结构化程序设计思想的重要方法。
和大多数程序设计语言一样,VB也提供了“过程”的概念.用于实现模块化的设计。
模块化程序设计思想就是把一个较大的程序划分为若干个模块,每个模块完成一个或若干个功能。
用过程编程有两大好处:
(l)程序易调试:
过程可使程序分成离散的逻辑单元,每个单元都比无过程的整个程序容易调试。
(2)减少程序设计的工作量:
将一些常用功能或重复出现的程序段编写成过程,以供其它程序调用。
VB中的过程有两大类,一类由系统提供,包括已学过的内部函数和事件过程。
另一类是用户自定义过程|通用过程(Sub过程)和用户自定义函数(Function过程)两种。
§1、自定义过程(Sub过程)
§1.1自定义过程的建立
自定义过程与事件过程不同,自定义过程不是由对象的某种事件激活,也不依附于某一对象,故其创建的方法略有区别。
建立自定义过程有两种方法:
直接在“代码”编辑窗口中输入过程代码;
使用“添加过程”对话框。
一、在“代码”编辑窗口中输入
在“代码”编辑窗口中,把光标定位在已有过程的外面。
然后按如下格式输入自定义过程:
1、格式[Private|Public][Static]Sub<过程名>([<形参表>])
[<语句序列>]
[ExitSub]
[<语句序列>]
EndSub
2、说明:
(l)<过程名>使用与变量名相同的命名规则。
长度不得超过40个字符。
(2)<形参表>指明了从调用过程传递给过程的变量个数和类型,在调用时被确定的实参值所代替。
(3)形参的格式为:
[ByVal|ByRef][<变量名>|数组名()][As(类型)][,[ByVal|ByRef][<变量名>|数组名()][As(类型)]…]
其中:
ByVal表示该参数按值传递:
ByRef表示该参数按地址传递。
缺省为ByRef;
(4)过程说明符可省略。
若说明符省略,Sub过程为公用过程,即Public过程。
例如:
Suba()等同于Publicsuba()
二、使用“添加过程”对话框
使用“添加过程”对话框建立自定义过程办法:
1、打开代码编辑窗口。
2、执行“工具”菜单中的“添加过程”命令,打开“添加过程”对话框。
3、在“名称”文本框中输入过程名。
从“类型”组中选择过程类型从“范围”组中选择范围,相当于使用Public或Private关键字。
4、单击“确定”按钮。
使用本方法,建立一个过程模板,程序员可以通过修改它建立自己的工程。
§1.2、自定义过程的调用
……
主程序子程序1子程序n
一、调用自定义过程有两种方法;
使用Call语句;格式:
Call<过程名>[(<实参表>)]
直接使用过程名;格式:
<过程名>[<实参表>]
例如;以下两个语句都调用了名为Stars的过程:
Stars40,a,b,c
CallStars(40,a,b,c)
其中的40,a,b,c都是实参。
实际参数允许是常量、变量、表达式。
无参自定义过程调用方法:
Stars
CallStars
二、举例
例7_1_1计算S=5!
+6!
+8!
分析:
要计算S=5!
十6!
十8!
先要分别计算出5!
,6!
和8!
。
由于3个求阶乘的运算过程相同,可以用自定义过程来计算任意阶乘,在Sub过程中将所求结果放入到total变量中,返回主程序后将total的值加到S变量中。
这样3次调用子程序便可求得S。
程序:
Dimtotal!
PrivateSubCommand1_Click()
Dima%,b%,c%,s!
s=0
a=5
CallFact(a)
s=s+total
b=6
CallFact(b)
s=s+total
c=8
CallFact(c)
s=s+total
Print"s=";s
EndSub
'子程序Fact
SubFact(m%)
Dimi#
total=1
Fori=1Tom
total=total*i
Nexti
EndSub
例p7_1_2.键盘任输入一个偶数(>4),验证该数为两个素数之和。
分析:
(1)素数:
只能被1或其本身整除的自然数;
(2)题意:
偶数=素数+素数
X=M+L
方法:
可先选择偶数范围内的最小一个素数M,用该偶数减去该素数,再判断差是否是一素数,若是,打印X=M+L;否则,再选择偶数范围内的稍大的素数M,继续判断,一直找到所求素数。
如果该偶数范围内所有素数都试过,仍为挑出合适的素数,则证明出错。
程序:
'例7_1_2.键盘任输入一个偶数(>4),验证该数为两个素数之和。
DimflagAsBoolean
PrivateSubCommand1_Click()
Dimx#,l#,m#
Cls
FontSize=20
x=InputBox("任输入一个偶数(>4)")
Form=3Tox-1Step2
Callz7_1_2(m)
IfflagThen
l=x-m
z7_1_2l
IfflagThen
Printx;"=";m;"+";l
ExitFor
EndIf
EndIf
Nextm
Ifm>=x-1ThenPrint"命题错误!
!
!
"
EndSub
'判断素数的子程序
Subz7_1_2(a)
Dimn#
flag=True
Forn=2ToSqr(a)+1
IfInt(a/n)=a/nThen
flag=False
ExitFor
EndIf
Nextn
EndSub
例7_1_3、例5_3_4.梯形法求定积分I=
y
y=f(x)
x
ab
分析:
求定积分从几何概念上求f(x)下的面积,近似求得积分I。
即:
hn-1f(a)+f(b)n-1
I≈━━∑(yi+yi+1)=h[━━━━━+∑f(a+ih)]
2i=02i=1
试编写求半径为1的园面积。
I=
4
dX的程序。
程序:
DimI#
PrivateSubForm_Click()
Dimi1#,i2#,e#
e=10^(-Val(InputBox("输入误差精度位数:
")))
n=100
Calld_integral(n)
i2=I
Do
i1=i2
n=2*n
Calld_integral(n)
i2=I
LoopUntilAbs(i2-i1)<=e
Print"i=";i2,"n=";n
EndSub
PrivateSubd_integral(ByValn)
Dima%,b%,k&,h!
b=1
a=0
h=(b-a)/n
I=(Sqr(1-a*a)+Sqr(1-b*b))/2
Fork=1Ton-1
x=a+k*h
I=I+Sqr(1-x*x)
Nextk
I=4*I*h
EndSub
例7_1_4、(P309实验4.2打印两个三角形图案)
§2、自定义函数(Function过程)
自定义函数实际上也是一个过程,当过程的执行返回一个值时,使用自定义函数就比较简单。
§2.1、Function过程的建立
一、格式:
[Private|Public][Static]Function<函数名>([<形参表>])[As类型]
[<语句序列>]
[<函数名>=<表达式>]
[ExitFunction]
[<语句序列>]
[<函数名>=<表达式>]
EndFunction
二、说明:
(l)<形参表>格式同自定义过程;
(2)<表达式>的值是函数返回的结果。
如果过程中省略“<函数名>=<表达式>”.则
该过程返回一个默认值:
数值函数过程返回0,字符串函数过程返回空字符串,Boolean函数过程返回False。
缺省为字符类型。
§2.1、Function过程的调用
一、格式:
<函数名>([<实参表>])
Function过程的调用比较简单,可以像使用vB内部函数一样来调用Function过程。
例如:
printStar(3.6)
还可像调用Sub过程那样调用Function过程。
当用这种方法调用函数时,VB放弃返回值。
二、举例
例7_2_1计算S=5!
+6!
+8!
程序:
PrivateSubCommand1_Click()
Dims!
s=Fact(5)+Fact(6)+Fact(8)
Print"s=";s
EndSub
'自定义函数Fact
FunctionFact(m%)
Dimi#
total=1
Fori=1Tom
total=total*i
Nexti
Fact=total
EndFunction
例7_2_2求两个正整数M和N的最小公倍数。
分析:
由数学知识可知:
最小公倍数=
最大公约数。
采用“辗转相除法”的思想。
(1)用大数M除小数N,余数为R;
(2)若R=0,则N就是它们的最大公约数;
若R≠0,则M←N,N←R,重复上过程,直至R=0
(3)最后得到的N就是最大公约数。
a=m:
b=n
Do
r=aModb
a=b
b=r
LoopWhiler<>0
程序:
PrivateSubCommand1_Click()
Dimm&,n&
Cls
m=Val(InputBox("M="))
n=Val(InputBox("N="))
Ifmm=n:
n=t
Printm;"和";n;"的最小公倍数是:
";m*n/Z7_2_2(m,n)
EndSub
FunctionZ7_2_2(m,n)
Dima&,b&,r&
a=m:
b=n
Do
r=aModb
a=b
b=r
LoopWhiler<>0
Z7_2_2=a
EndFunction
例7_2_3统计1~100间的能被3或被5整除的整数的个数。
分析:
分别统计能被3、5整除数的个数,再减去能被15整除数的个数。
PrivateSubCommand1_Click()
Cls
Print"统计个数为:
";f(3)+f(5)-f(15)
EndSub
Functionf%(m%)
Dimi%,s%,k%
s=0:
k=0
Fori=1To100
Ifi\m=i/mThen
s=s+1
PrintFormat(i,"!
@@@@");
k=k+1
Ifk=10ThenPrint:
k=0
EndIf
Nexti
Print
f=s
EndFunction
例7_2_4、写一个函数过程数判断一个数是否是一个“完数”,所谓“完数”是指该数的值等于其所有因子之和。
例如:
6=1+2+36是一个完数,求1到200的所有完数。
PrivateSubForm_Click()
DimkAsInteger
Fork=1To200
Ifws(k)ThenPrintk
Nextk
EndSub
Functionws(mAsInteger)AsBoolean
DimnAsInteger,iAsInteger,sAsInteger
n=m\2
Fori=1Ton
IfmModi=0Then
s=s+i
EndIf
Nexti
Ifs=mThenws=TrueElsews=False
EndFunction
§3、过程的参数传递问题
当用户自定义函数或过程被调用时,调用语句中的实参就和定义语句中的形参一一对应起来,并以某种方式把实参传递给形参,供过程使用。
称为过程的参数传递。
VB中过程的参数传递的方式有两种:
一种是按值传递,另一种是按地址传递。
地址传递:
将形参变量的地址作为实参变量的地址。
即形参与实参使用相同的内存地址单元,对形参变量的访问实际也是对实参变量的访问。
值传递:
将实参变量的数据赋予形参变量,对形参变量的访问不会改变实参变量的值。
一、按地址传递参数
如果调用语句中的实际参数为变量,或者定义过程时选用ByRef关键字,就可以按地址传递。
系统缺省按地址传递参数。
在传址调用时,实际参数必须是变量,常量或表达式无法传址。
例7_3_1地址传递参数例(过程)。
PrivateSubCommand1_Click()
x=1:
y=1:
z=1
Print"调用子程序前的X,Y,Z值 ";x;y;z
exax,y,z
Print"调用子程序后的X,Y,Z值 ";x;y;z
EndSub
Subexa(a,b,c)
a=a+1
b=b+2
c=c+3
Print"调用子程序中的A,B,C值 ";a;b;c
EndSub
例7_3_2地址传递参数例(函数)。
例7_3_4(例7_1_1计算S=5!
+6!
+8!
)
程序:
PrivateSubForm_Activate()
Dimf1#,f2#,f3#
Callfact(5,f1)
Callfact(6,f2)
Callfact(8,f3)
Print"s=";f1+f2+f3
EndSub
Subfact(n%,f#)
f=1
Fori=1Ton
f=f*i
Nexti
EndSub
二、按值传递参数
如果调用语句中的实参是常量或表达式,或者定义过程时选用ByVal关键字,就可以按值传递。
简单变量若用括号括起作实参时,视为表达式。
例7_3_3值传递参数例(过程)。
程序:
PrivateSubCommand1_Click()
x=1:
y=1:
z=1
Print"调用子程序前的X,Y,Z值 ";x;y;z
exa(x),(y),z+0
Print"调用子程序后的X,Y,Z值 ";x;y;z
EndSub
Subexa(a,b,c)
a=a+1
b=b+2
c=c+3
Print"调用子程序中的A,B,C值 ";a;b;c
EndSub
§4、数组和下标元素的传递
在使用通用过程和函数过程时;可以将数组或数组元素作为参数进行传递。
一、格式
传递整个数组时,实参与其对应的形参均为:
<数组名>()
传递数组中的某一元素时,实参为下标元素,对应形参为简单变量。
例如:
Calltest(x(3))
二、说明:
数组传递是地址传递
三、举例
例7_4_1.[例6_1_1]产生50个[1,100]间的随机整数,将他们从大到小排序。
程序:
PrivateSubForm_Activate()
'产生50个随机数
Dima&(1To50)
Randomize
Fori=1To50
a(i)=Fix(Rnd*100+1)
PrintFormat(a(i),"!
@@@@");
IfiMod10=0ThenPrint
Nexti
Print:
Print:
Print
Calltaxis(a())
EndSub
'从小到大排序(起泡排序法)
Subtaxis(c&())
Fori=1To49
Forj=i+1To50
Ifc(i)t=c(i):
c(i)=c(j):
c(j)=t
EndIf
Nextj
Nexti
Callp_taxis(c())
EndSub
'打印
Subp_taxis(b&())
Fori=1To50
PrintFormat(b(i),"!
@@@@");
IfiMod10=0ThenPrint
Nexti
EndSub
§5、过程、函数的递归调用
在一个过程(Sub过程或Function过程)中调用另外一个过程,称为过程的嵌套调用;而过程直接或间接地调用其自身,则称为过程的递归调用。
递归使我们能过用有限的语句描述一个无穷的集合。
例如求阶乘的递归定义:
nxf(n-1)当n>1
f(n)=
1当n=1
例7_5_1求阶乘的递归s=n!
(使用函数递归)
程序:
PrivateSubForm_Activate()
Dimn%
n=Val(InputBox("n="))
Print"s=";f(n)
EndSub
PrivateFunctionf#(ByValn%)
Ifn=1Then
f=1
Else
f=n*f(n-1)
EndIf
EndFunction
例如:
n=4则4!
=4X3X2X1=24
n
F(n)
4
4*f(3)
3
3*f
(2)
2
2*f
(1)
1
1
例7_5_2求阶乘的递归s=n!
(使用过程递归)
程序:
Dimf#
PrivateSubForm_Activate()
Dimn%
n=Val(InputBox("n="))
Calls(n)
Print"s=";f
EndSub
PrivateSubs(ByValn%)
Ifn=1Then
f=1
Else
Calls(n-1)
f=n*f
EndIf
EndSub
f=4*ff=3*ff=2*ff=1*1
(4*3*2*1)(3*2*1)(2*1)
例7_5_3求斐波那契数列的前n项。
(使用函数递归)
分析:
F(n)=F(n-1)+F(n-2)n>=2
F(0)=0,F
(1)=1
程序:
PrivateSubForm_Activate()
Dimn%,i%
n=Val(InputBox("n="))
Fori=1Ton
Printf(i),
IfiMod5=0ThenPrint
Next
EndSub
PrivateFunctionf#(ByValn%)
SelectCasen
Case0
f=0
Case1
f=1
CaseElse
f=f(n-1)+f(n-2)
EndSelect
EndFunction