590 likes | 688 Views
VB 数据库编程 第七讲 过程. 第七讲 过程. Visual Basic 的工程 过程的定义和调用 参数传递 复杂的过程参数 过程与变量的作用域. Visual Basic 的工程. vb 应用程序称为 工程 。 工程是由若干个过程构成的,而这些过程都存放在文件中。 每个文件的内容称为一个模块。 vb 的模块分为三种:窗体模块、标准模块和类模块。 窗体模块中的内容存放在以 .frm 为扩展名的文件中。标准模块中的内容存放在以 .bas 为扩展名的文件中。类模块中的内容存放在以 .cls 为扩展名的文件中。. Visual Basic 的工程.
E N D
第七讲 过程 Visual Basic 的工程 过程的定义和调用 参数传递 复杂的过程参数 过程与变量的作用域
Visual Basic的工程 vb应用程序称为工程。 工程是由若干个过程构成的,而这些过程都存放在文件中。 每个文件的内容称为一个模块。 vb的模块分为三种:窗体模块、标准模块和类模块。 窗体模块中的内容存放在以 .frm为扩展名的文件中。标准模块中的内容存放在以 .bas为扩展名的文件中。类模块中的内容存放在以.cls为扩展名的文件中。
过程的定义和调用 过程是完成特定功能的一组程序代码,这组程序代码是由若干个语句构成的。 过程用在两个方面: 一方面,如果一个应用程序要完成一个复杂任务,则通常把这个复杂任务划分为若干个小任务,并把这些小任务编写成一个个过程; 另一方面,在一个完成复杂任务的应用程序中,往往要编写一些功能完全相同或相近的程序段,为了避免程序繁琐冗长使程序简练一些,可以把这样的程序段独立开来编写成过程,然后在需要的地方调用该过程,完成相应的工作。
过程的定义和调用 过程可以分为两大类。一类是由系统提供的,包括内部函数和事件过程。对于事件过程,vb系统提供了它们的框架,用户可以根据需要填写具体的内容。另一类为用户自己定义的过程。 用户自己定义的过程有四种: 以关键字Sub定义的子过程、 以关键字Function定义的函数过程、 以关键字Property定义的属性过程和以Event定义的事件过程。在本课程中只讨论前面两种用户自定义过程。这两种过程称为通用过程。
子过程的定义和调用 一般格式: [Private|Public] [Static] Sub <name> [(<arglist>)] [<statements>] [Exit Sub] [<statements>] End Sub 其中第一行称为子过程开始语句, Sub是定义子过程的关键字。Private、Public和Static为可选关键字。 Private和Public两者取其一,默认值为Public 。 <name>是用户自定义子过程的名字,用标识符表示。 <arglist>是形式参数表,形式参数之间用逗号分隔。每个形式参数都要说明它的类型,并且要说明是数值参数还是变量参数。每个形式参数说明的一般形式: [ByVal|ByRef] 形式参数名[()] [ As 类型]
子过程的定义和调用 Private Sub triangle (Str As String,n As Integer) Dim I As Integer, J As Integer For I=1 To n For J=1 To I Print Str; Next J Print Next I End Sub 例1: 打印一个直角三角形图案的有参子过程。
子过程的定义和调用 例2:求n! 有参子过程。 Public Sub fact(Byval n As Integer,Byref fac As Long) Dim t As Long,i As Integer t=1 For i=1 To n t=t*i Next i fac=t End Sub
子过程的定义和调用 当执行程序执行到子过程调用语句调用无参过程时,vb系统转去执行子过程体中的语句,执行之后就转回刚调用子过程语句的下一个语句去执行。 例如:Call simple1 或 simple1 当执行程序执行到子过程调用语句调用有参过程时,vb系统先进行参数的传送,然后执行子过程体中的语句。执行之后就转回刚调用子过程语句的下一个语句去执行。 又如:Call triangle(“*”,5) 或 triangle “*”,5
子过程的定义和调用 例3调用例2定义的子过程。 Private Sub Command1_Click() Dim Chx As String*1, Num As Integer Chx="*" Num=8 Call triangle(Chx,Num) ’使用Call关键字的调用格式 Chx="$" triangle Chx, Num / 2 ’不用Call关键字的调用格式 End Sub Private Sub triangle (Str As String, n As Integer) Dim I As Integer, J As Integer For I=1 To n For J=1 To I Print Str; Next J Print Next I End Sub * ** *** **** ***** ****** ******* ******** $ $ $ $ $ $ $ $ $ $
子过程的定义和调用 例4用语句调用事件过程。 Private Sub Command1_Click() Print " Hello world !" Command2_Click ‘ 用语句调用事件过程 End Sub Private Sub Command2_Click() Print " How are you ?" End Sub
函数的定义和调用 当在程序中需要多次用到某一公式或要处理某一函数关系,而又没有现成的内部函数可以使用时,用户自己可以定义一些函数来使用。 自己定义的函数通常称为函数过程。 函数过程也是用特定格式组织起来的一组代码。函数过程在调用结束时带回一个值,该值称为函数过程的返回值。这个值的类型称为函数过程的类型。 要使用自己定义的函数过程来编程序需要做两件事:一是要定义函数过程;二是要调用函数过程。
函数的定义和调用 一般格式: [Public|Private][Static] Function <name> [(<arglist>)] [As <type>] [<statements>] [<name> = <expression>] ┇ [Exit Function] [<statements>] [<name> = <expression>] End Function 其中第一行称为函数过程开始语句, Function是定义函数过程的关键字。Private、Public和Static为可选关键字。 Private和Public两者取其一,默认值为Public 。 <name>是用户自定义函数过程的名字,用标识符表示。
函数的定义和调用 <arglist>是形式参数表,形式参数之间用逗号分隔。每个形式参数都要说明它的类型,而且还要说明它是数值参数还是变量参数。每个形式参数说明的一般形式: [ByVal|ByRef] 形式参数名[()] [ As 类型] 可选项[As <type>]用来说明函数返回值的类型。 最后一行的语句 “End Function”称为函数过程结束语句。函数过程开始语句和结束语句之间的语句称为函数体。 函数体内的两个语句序列[<statements>]也为可选项,它是由一系列语句组成,这些语句用来完成该函数过程要完成的特定工作。 可选项[Exit Function]是一个语句,用于强制结束函数过程的执行。
函数的定义和调用 在函数体中,应该至少有一个给函数过程名赋值的语句。最后一次给函数过程名赋的值就是该函数过程的返回值。若不给函数名赋值,则该函数会返回一个缺省值。数值型函数的缺省值为0,字符串型函数为一空串,可变类型函数为空值。 例如,把求三个数的最大值编写成一个函数过程为: Private Function max( ByVal x As Single, ByVal y As Single,ByVal z As Single) As Single Dim m As Single If x>y Then m=x Else m=y If z>m Then m=z max=m End Function
函数的定义和调用 又如,求阶乘也可以定义一个函数过程: Public Function fact(ByVal n As Integer)As Long Dim i As Integer,t As Long t=1 For i=1 To n t=t*i Next t Fact=t End Function
函数的定义和调用 要使用函数过程必须调用它,而调用函数过程的常用格式为: 函数过程名(实际参数表) 其中函数过程名用标识符表示。实际参数表中的参数一般为常数、常量、变量等,更一般为表达式,它们必须在数目、类型和排列次序上与相应函数过程定义的形式参数表中参数一致。 函数过程一般在表达式中调用。当系统在执行程序遇到函数过程调用时,先进行参数传送,然后执行函数过程体中的语句,并通过函数名把函数值带回表达式进行运算。 例如:y=max(0.75,100,85.5) s=(fact(5)+fact(7))/fact(8)
函数的定义和调用 例5定义一个计算圆面积的函数,并用事件过程调用之。 Function area(ByVal radius As Double) As Double area = 3.14159 * radius * radius End Function Private Sub Command1_Click() Dim r as double, a as double If MsgBox("要计算圆面积吗?", 4 + 32, "提示信息") = vbYes Then r = InputBox("请输入半径:", "例7_5") a = area(r) '调用函数,计算圆面积 Print "半径="; r, "面积="; a End If End Sub
函数的定义和调用 例6 先从左边文本框输入一个分数,单击命令按钮后调用自定义函数Passed对该分数判断。若该分数大于等于0且小于60,则在右边文本框显示“不及格”;若该分数大于等于60且小于等于100,则在右边文本框显示“及格”。否则,在右边文本框显示“数据错”。
函数的定义和调用 Private Function Passed(ByVal score%) As String Select Case score Case 0 To 59 Passed="不及格" Case 60 To 100 Passed="及格" Case Else Passed="数据错!" End Select End Function Private Sub Command1_Click() Text2=Passed(Val(Text1)) End Sub
参数传递 参数传递 当调用子过程或函数过程时,先要进行参数的传递。具体一点讲,调用过程时要把需处理的原始数据传送给形式参数。另外,执行过程中的语句之后的计算或处理结果也需要传递回调用程序。 在这一节要介绍如何把需处理的原始数据传递给过程和如何把执行过程体后的结果传递回调用程序。
参数传递 • 形式参数和实际参数 • 过程的参数传递有两种方式:一种是值传递方式,采用这种方式的调用称为传值调用; 另一种是地址传递方式,采用这种方式的调用称为传址调用。
参数传递 如果在过程定义中,形式参数前使用关键字ByVal,则该参数称为数值参数或传值参数。 过程调用时的参数传递过程为:系统先开辟形式参数的临时存储空间,并把实际参数的值赋给对应的形式参数。执行过程体时,对形式参数进行的任何操作与实际参数没有任何联系。过程执行完毕,系统收回形式参数的临时存储空间 。 传值调用
参数传递 Private Sub Command1_Click() Dim x%, y% x = 5 y = 10 Print " x="; x, "y="; y NoChange x, y Print " x="; x, "y="; y End Sub Private Sub NoChange(ByVal a%, ByVal b%) a = a + b b = a * b Print " a="; a, "b="; b End Sub 传值参数测试
参数传递 x 分配存储空间 y 分配存储空间
参数传递 x 分配存储空间 x=5 5 y 分配存储空间
参数传递 x 5 x=5 y 分配存储空间 y=10 10
参数传递 x 5 y 分配存储空间 10 a 分配存储空间 5 10 b 分配存储空间
参数传递 x 5 x、y 值不变 y 10 10 a a=a+b 5 15 b 10 150 b=a*b
参数传递 如果在过程定义中,形式参数前使用关键字ByRef或无关键字,则该参数称为变量参数或传址参数。 过程调用时的参数传递过程为:系统先开辟形式参数的临时存储空间,并把实际参数的地址赋给对应的形式参数。执行过程体时,对形式参数的任何操作实际上是通过间址操作对实际参数进行。过程执行完毕,系统收回形式参数的临时存储空间 。 传址调用
参数传递 Private Sub Command1_Click() Dim x%, y% x = 5 y = 10 Print " x="; x, "y="; y ISChange x, y Print " x="; x, "y="; y End Sub Private Sub ISChange(ByRef a%, ByRef b%) a = a + b b = a * b Print " a="; a, "b="; b End Sub 传址参数测试
参数传递 x 分配存储空间 y 分配存储空间
参数传递 x 分配存储空间 x=5 5 y 分配存储空间
参数传递 x 5 x=5 y 分配存储空间 y=10 10
参数传递 x 5 y 分配存储空间 10 a 分配存储空间 x 地址 y 地址 b 分配存储空间
参数传递 x 5 15 x、y 值改变 y 10 150 a a=a+b相当于x=x+y x 地址 y 地址 b b=a*b相当于y=x*y
参数传递 补充例:计算s=(5!+8!)/7!的值。 Private Sub Command1_Click() Dim f1 As Long,f2 As Long,f3 As Long,s As single Call fact(5,f1):Call fact(7,f2):Call fact(8,f3) s=(f1+f2)/f3 Print “s=”;s End Sub Sub fact(Byval n As Integer,Byref fac As Long) Dim t As Long,i As Integer t=1 For i=1 To n t=t*i Next i fac=t End Sub
参数传递 Option Explicit Function F( X%, Y% ) As Integer X = X - Y If X <> 0 Then F = X Else F = Y End If End Function Private Sub Command1_Click() Dim A as integer, B as integer Dim Text1%, Text2% A = 5 B = 2 '以下两式相同但值不同 Text1 = F( A, B ) + 2 * A Text2 = F( A, B ) + 2 * A End Sub 使用传址调用会改变实际参数的值。一个函数如果改变实际参数的值,则称这是一个有边界效应的函数或称有副作用的函数。 例9改变实际参数值的函数。 关于副作用
复杂的过程参数 数组、记录和对象都可以作为过程定义中的参数。 1. 数组元素作为参数 例10测试数组元素作为过程参数。 Option Explicit Private Sub Command1_Click() Dim a(1 To 3) As Integer, i As Integer For i = 1 To 3 a(i) = i Next For i = 1 To 3 Print " a("; i; ") = "; a(i); Next Print
复杂的过程参数 Call FunAry1(a(1), a(3)) For i = 1 To 3 Print " a("; i; ") = "; a(i); Next Print Call FunAry2(a(1), a(3)) For i = 1 To 3 Print " a("; i; ") = "; a(i); Next End Sub Public Sub FunAry2(ByVal x%, ByVal y%) x = x + 1 y = y + 1 Print " x="; x; " y="; y End Sub Public Sub FunAry1(x%, y%) x = x + 1 y = y + 1 Print " x="; x; " y="; y End Sub
复杂的过程参数 2. 数组整体作为参数 在vb中允许数组作为过程的参数。此时,在定义的过程中,形式参数表中的数组用数组名后加一对圆括号表示, 而在过程调用时,实际参数表中的数组可以只用数组名表示。也就是说,可以省略圆括号。 例11定义一个过程,循环移动数组元素。例如,对数组a的元素往前移动,即把a(i+1)移到第i个位置,而第1个元素移到最后一个位置。
复杂的过程参数 Private Sub Command1_Click() Dim j as integer Const N = 6 Dim B(1 To N) As Integer For j = 1 To 6 '数组赋初值 B(j) = j Next Print "移动前的数组:" For j = 1 To N '打印原始数组 Print B(j); Next j Print
复杂的过程参数 Call MoveAry(B()) '调用过程,移动数组元素 Print "移动后的数组:" For j = LBound(B) To UBound(B) Print B(j); Next j Print End Sub Sub MoveAry(A() As Integer) Dim L%, H%, j%, Tmp% L = LBound(A) '取数组下界 H = UBound(A) '取数组上界 If H=L Then Exit Sub Tmp=A(L) For j = L + 1 To H '第j元素前移一个位置 A(j - 1) = A(j) Next j A(H) = Tmp End Sub
复杂的过程参数 记录作为过程参数与数组作为参数的情形大致相同。当记录元素作为过程参数时,可以传值或传地址;当记录变量名作为参数时,VB传送记录变量的首地址,过程形参对实参进行间址操作,即对形参的操作实际上是对实参进行。 例13测试记录参数。 Option Explicit Private Type point x As Integer y As Integer End Type 记录参数
复杂的过程参数 Private Sub MovePoint(p As point) p.x = p.x + 10 p.y = p.y + 10 End Sub Private Sub Command1_Click() Dim pp As point pp.x = 200 pp.y = 100 Print " Point1("; pp.x; ","; pp.y; ")" MovePoint pp Print " Point2("; pp.x; ","; pp.y; ")" End Sub
复杂的过程参数 例15使用控件参数。 Sub Change_Path(ctl As Control, z As String) ctl.Path=z '给Path属性赋新值 End Sub Private Sub Command1_Click() Dim z As String z=InputBox("输入驱动器和(/或)路径:") Call Change_Path(Dir1, z) End Sub 对象参数
过程与变量的作用域 每个过程都有一个使用范围。过程的使用范围称为过程的作用域。 从作用域这个角度上来讲,过程可以分为两种:一种称为模块级过程(文件级过程);另一种称为全局级过程(工程级过程)。 在某一模块或者说在某一文件内定义的过程,若在关键字Sub或Function前加Public,则该过程称为全局级过程(工程级过程)。对于全局级过程,可以在整个应用程序中使用。也就是说,全局级过程的作用域为整个应用程序。 过程的作用域
过程与变量的作用域 说明:作用域为整个工程的过程,因其定义所在文件的性质不同,调用时的规则略有区别,其规则如下: ① 在某一.frm文件(窗体模块)中定义的工程级过程被在该文件外定义的过程调用时,必须在被调用过程名前加上窗体名称。 ② 在某一.bas文件(标准模块)中定义的工程级过程,若与其他模块中定义的工程级过程不同名,这时只要主调过程所在的文件中没有与它同名的过程,则可以直接使用过程名调用,无须在过程名前加模块名。 ③ 在不同文件(模块)中定义的工程级过程可以同名,但调用时要在过程名前一律加上模块名。
过程与变量的作用域 1.变量的作用域 每个变量都有一个使用范围,变量的使用范围称为变量的作用域。 从作用域这个角度上来讲,变量可以分为三种:第一种是过程级变量(局部级变量);第二种是模块级变量(文件级变量);第三种是工程级变量(全局级变量)。