450 likes | 748 Vues
第 6 章 过 程. 6.1.1 过程的概念 过程是一段程序代码,是相对独立的逻辑模块。 一个完整的 VB 应用程序由若干过程和模块组成。 常用的 VB 过程有: Sub 过程和 Function 过程。 Sub 过程 ( 子过程 ) :完成一定的操作和功能,无返回值,通过程序调用和事件触发而执行,分为事件过程和通用过程。 Function 过程 ( 函数过程 ) :相当于用户自定义的函数,通过程序调用才能被执行,并且可将数据处理的结果返回。 一个过程的代码长度不要超过 64K 。. 6.1 过程. 6.1 过程. 6.1.2 过程的优点
E N D
6.1.1 过程的概念 过程是一段程序代码,是相对独立的逻辑模块。 一个完整的VB应用程序由若干过程和模块组成。 常用的VB过程有:Sub过程和Function过程。 Sub过程(子过程):完成一定的操作和功能,无返回值,通过程序调用和事件触发而执行,分为事件过程和通用过程。 Function过程(函数过程):相当于用户自定义的函数,通过程序调用才能被执行,并且可将数据处理的结果返回。 一个过程的代码长度不要超过64K。 6.1 过程
6.1 过程 6.1.2过程的优点 1.消除了重复语句行。你可以只定义一次过程,而在程序任意多次执行这一过程。 2.使程序更易阅读。由一系列小程序段组成的程序比大段、大段的程序更容易理解和区分。 3.简化了程序开发。把程序分成一些合乎逻辑的单位更易于设计、编写和调试。 4.其它程序可重复使用该通用过程。你可以轻易地将标准模块过程纳入其它编程项目中。 5.扩展Visual Basic语言。过程往往能够完成单个Visual Basic关键字无法完成的任务。
过程定义格式: [Private|Public]Sub 过程名(参数表) 语 句 [exit sub] End Sub Private表示模块级子过程,Public表示全局级子过程(缺省值) 。 过程名符合VB标识符的命名约定 参数表可以是空表,也可以放置若干个变量(形式参数) 。如: Public Sub Sum(X As Integer, Y As Integer, Z As Integer) Sub过程分为:事件过程和通用过程 6.2 过程-Sub过程(子过程)
1. 事件过程 这类过程与对象有关,对象事件触发后被调用。 事件过程的过程名由系统自动指定。 建立对象的事件过程: (1) 进入代码窗口 方法1:双击对象 方法2:“视图→代码窗口” (2) 选择“对象”和“事件过程”,系统 自动形成该事件过程的头和尾 (3) 编写该事件的程序代码 “对象” “事件过程” 6.2 过程-Sub过程
2. 通用Sub过程 这类过程不与对象相关,是用户创建的一段共享代码。 过程的名称由用户自己命 建立通用Sub过程: (1) 建立过程框架 方法1:在模块的“通用”段中输入 过程名,按回车后系统自动添加 End Sub。 方法2:“工具→添加过程” (2) 编写该过程的程序代码 6.2 过程-Sub过程
[例1] 定义一个无参数的sub过程print_Line(),用于在窗体上打印一行虚线。 Private Sub Print_Line() Dim I As Integer Print Tab(10); For I = 1 To 25 Print "-"; Next I Print End Sub 6.2 过程-Sub过程 定长
3. 过程的调用方法 (1) 通用Sub过程的两种调用方式(p114): Call 过程名(参数表) 过程名 参数表 (2) 事件过程的调用 一般由事件的触发而引起(单击、窗体加载等) 也可以象通用Sub过程那样调用,如: Private Sub Form_DblClick() Call Command1_Click End Sub 6.2 过程-Sub过程
[例1] 在窗体上打印一组学生的成绩表,并在需要的地方打印虚线。 '表格横线用通用过程Print_Line绘出,在主程序中多次调用 Private Sub Print_Line() Dim I As Integer Print Tab(10); For I = 1 To 25 Print "-"; Next I Print End Sub 6.2 过程-Sub过程
Private Sub Command3_Click() Dim math(1 To 5) As Integer Dim phy(1 To 5) As Integer Dim chem(1 To 5) As Integer, i As Integer For i = 1 To 5 '用随机函数生成表中数据 math(i) = Int(Rnd * 100 + 1) phy(i) = Int(Rnd * 100 + 1) chem(i) = Int(Rnd * 100 + 1) Next i print_line '调用画线子过程 Print Tab(10); "数学"; Tab(20); "物理"; Tab(30); "化学" print_line '调用画线子过程 For i = 1 To 5 '打印表中数据,并统计各科总分 Print Tab(10); math(i); Tab(20); phy(i); Tab(30); chem(i) Next i print_line '调用画线子过程 End Sub
[例2]定义一个通用子过程Print_Line用于打印不同长度的虚线,参数n(整型)用于指定虚线的长度[例2]定义一个通用子过程Print_Line用于打印不同长度的虚线,参数n(整型)用于指定虚线的长度 将Print_Line过程改写如下: Private Sub Print_Line(n As Integer) Dim I As Integer Print Tab(10); For I = 1 To n Print "-"; Next I Print End Sub 6.2 过程-Sub过程 n为形参 调用过程时,实参将值交给形参,由形参带入子过程中执行。 调用语句为: Print_Line 实参 或 Call Print_Line(实参) 例如,Print_Line 30 或 Call Print_Line(30)
执行结束返回主调过程 4.Sub函数的调用过程 n=10 Private Sub Print_Line(n As Integer) Dim i As Integer Print Tab(10); For i = 1 To n Print "-"; Next i Print End Sub 形参 Private Sub Command1_Click() Dim i As Integer For i = 1 To 5 Print call Print_Line (10 * i) Next i End Sub 开始执行 10 实参 子过程执行结束后,返回到主调程序
调用语句中,实参可以是常量、变量、表达式、数组调用语句中,实参可以是常量、变量、表达式、数组 Private Sub Print_Line(n As Integer) Dim I As Integer Print Tab(10); For I = 1 To n Print "-"; Next I Print End Sub Call Print_Line(30) N=30 Call Print_Line(n) A=3:b=7 Call Print_Line(a*b+10)
1.参数的种类 形参(形式参数):在子过程定义时,括号中给出的参数 例如:Private Sub Print_Line(n As Integer) 实参(实际参数):运行时,调用子过程时括号中的参数 例如 :call Print_Line (10 * i) 6.5 传递参数-Sub过程
6.5 传递参数-Sub过程 2.参数的数据类型 [Private|Public]Sub 过程名(参数表) • 参数的数据类型可以是任意数据类型,省略数据类型,缺省为variant型。 • 参数表中的参数可以是空、一个或者多个。如果有多个参数,用逗号隔开 例如: Private Sub Print_Line( ) Private Sub Print_Line(n As Integer) Private Sub add(a As Integer, b As Integer)
[例3]定义一个拥有多个参数的sub过程cal(a as single,b as single,op as string)完成计算功能,参数a、b是两个操作数,op是运算符。点击“计算”按钮,调用cal过程。
6.5 传递参数-Sub过程 4、调用时,形参与实参应一一对应(个数,位置,数据类型) Private Sub Print_Line( ) Call Print_Line 如果不对应,后果很严重 Private Sub Print_Line(n As Integer) Call Print_Line(30) Private Sub plus(a As Integer, b As Integer) Call plus(10,30) Call plus (a,b)
6.5 传递参数-Sub过程 • 调用语句中,实参可以是常量、变量、或表达式 Private Sub Print_Line(n As Integer) Dim I As Integer Print Tab(10); For I = 1 To n Print "-"; Next I Print End Sub Call Print_Line(30) N=30 Call Print_Line(n) A=3:b=7 Call Print_Line(a*b+10)
6.5 传递参数-Sub过程 • 当实参是变量时,实参和形参的数据类型必须保持一致,除非形参是variant型。 Private Sub Print_Line(n As Integer) Dim I As Integer Print Tab(10); For I = 1 To n Print "-"; Next I Print End Sub Din n as integer n=30 Call Print_Line(n) Din n as single N=30.33 Call Print_Line(n)
执行结束返回主调过程 5.形参和实参可以同名 Private Sub Print_Line(n As Integer) Dim i As Integer Print Tab(10); For i = 1 To n Print "-"; Next i Print End Sub n=10 Private Sub Command1_Click() Dim i As Integer, n as integer n=10 For i = 1 To 5 Print call Print_Line ( n) Next i End Sub 开始执行 10
6.5 传递参数-Sub过程 6.Sub子过程的参数还可以是数组[习题1].定义一个子过程,求数组中的最小值。
6.5 传递参数-Sub过程 Private Sub Form_Click() Print Dim a(1 To 10), amin As Integer, i% For i = 1 To 10 a(i) = Int(Rnd * 101 + 100) Print a(i); Next i Print s a() End Sub Public Sub s(b()) Dim i% min = b(LBound(b)) For i = LBound(b) + 1 To UBound(b) If b(i) < min Then min = b(i) Next i Print Print "min="; min End Sub
6.5 传递参数-Sub过程 • 按地址传递参数 (1)在形式参数前可以使用byRef和byVal关键字,byRef表示按地址传递 (2)缺省情况下表示按地址传递 (3)对变量的改动会被传回调用程序 (4)参数是数组时,只可以是按地址传递参数
6.5 传递参数-Sub过程 【例】编写一个两个数交换的sub过程Swap (x,y) ,供多次调用。 Public Sub Swap(x, y) Dim t t = x x = y y = t End Sub 按地址传递 Private Sub Form_Click() Dim a, b a = 10 b = 20 Call Swap (a, b) Print a,b End Sub 改变了a 和b的值
6.5 传递参数-Sub过程 • 按值传递参数 (1)在形参前使用byRVal表示按值传递 (2)传递参数时,传递的是变量的副本,过程执行结束,变量值释放。
6.5 传递参数-Sub过程 【例】编写一个两个数交换的sub过程Swap (x,y) ,供多次调用。 Public Sub Swap(byVal x, byVal y) Dim t t = x x = y y = t End Sub 按值传递 Private Sub Form_Click() Dim a, b a = 10 b = 20 Call Swap (a, b) Print a,b End Sub 会输出什么?
例6-7:以下是一个药品价格计算的子过程,子过程名为OldToNew,参数old为原来药品价格,参数New为新的药品价格。例6-7:以下是一个药品价格计算的子过程,子过程名为OldToNew,参数old为原来药品价格,参数New为新的药品价格。 Sub OldToNew(old,neww) old = old * 1.05 '药品价格上涨5% neww = Int(old) '取整以后得到新的药品价格 End Sub ····· Private Sub Form_Load() price = 100 new1 = 0 OldToNew price , new1 Print “原来价格为:”; price; "药品价格上涨5%后,价格为:"; new1 End Sub
因为old是传址变量,对old的修改自动地造成了对price的相同修改 。 将参数传递语句修改为: Sub OldToNew(ByVal old,neww) 当使用ByVal声明old 参数时,程序就会产生如图所示的正确结果:
例6-2,6-3编写一个子过程del(s1,s2),将字符串s1中出现s2子字符串删去,结果还是存放在s1中。例6-2,6-3编写一个子过程del(s1,s2),将字符串s1中出现s2子字符串删去,结果还是存放在s1中。 例如:s1=”123456789abc”,s2=”abc” 结果:s1=”123456789” 子过程定义如下: Public Sub del(s1 As String, s2 As String) Dim i% i = InStr(s1, s2) ls2 = Len(s2) Do While i > 0 ls1 = Len(s1) s1 = Left(s1, i - 1) + Mid(s1, i + ls2) i = InStr(s1, s2) Loop End Sub
6.3 函数过程 • 6.3.1函数过程的定义 Function过程的建立与Sub过程的建立相似,定义函数过程有两种方法: 1.利用“工具”菜单下的“添加过程”来定义。
2 利用代码窗口直接定义。 函数过程形式: [public]|[private]Function 函数过程名([参数列表])[As 类型] 局部变量或常数定义 语句块 [Exit Function] 函数过程体 语句块 函数名 = 返回值 End Function Private、Public及参数表的含义同Sub子过程 函数过程名:命名规则同变量名 Function过程具有函数值,类型缺省为变体型 函数名 = 返回值: 在函数体内至少对函数名赋值一次。 [Exit Function] : 表示退出函数过程。
[例] 计算 Private Sub Command1_Click() Dim I As Integer Dim e As Single, F As Long For I = 0 To 10 F = Factorial(I) '计算 I! e = e + 1 / F Next I Print "e="; e End Sub 计算阶乘的函数过程 Function Factorial(X As Integer) As Long Dim I As Integer, T As Long T = 1 For I = 1 To X '计算 X! T = T * I Next I Factorial = T End Function 4.2 过程-Function过程
1 2 传递参数,调用函数 5 继续执行 4 带回返回值 3 Private Sub Command1_Click() Dim I As Integer Dim e As Single, F As Long For I = 0 To 10 F = Factorial(I) e = e + 1 / F Next I Print "e="; e End Sub Function Factorial(X As Integer) As Long Dim I As Integer, T As Long T = 1 For I = 1 To X T = T * I Next I Factorial = T End Function
6.3 函数过程 • 6.3.2 function的调用方法:[例fun1] • 将Function返回值赋给一个变量 • 将Function过程的返回值放在表达式中 • 可作为其他过程的参数 • 像sub过程一样调用(忽略返回值时) 想一下已经学过的msgbox函数
6.3 函数过程 • 函数过程与sub过程的区别: • 函数过程返回一个与函数名相关联的值,在子过程体内不能对子过程名赋值。 • 函数过程有类型,子过程没有。 • 调用时,子过程调用是一句独立的语句。 函数过程可参与表达式运算,或作为其他过程的参数。 • 一般当过程有一个返回值,使用函数过程较直观; • 反之若过程无返回值,或有多个返回值,使用子过程较直观。[例 返回值] 子过程究竟可不可以返回值?
使用过程注意事项: 1. 确定自定义的过程是子过程还是函数过程 函数过程名有值,子过程名无值。 2.过程中形参的个数和传递方式的确定 过程中参数的作用是实现过程与调用者的数据通信。 (1)只须从主调程序获得初值,值传递。 (2)将结果返回给主调程序,地址传递。 3. 实参与形参结合时对应问题 个数、类型、位置、次序一一对应。 数组只能是地址传递。
例6-1 6-2编写一个函数,实现一个10进制整数转换成为2到16任意进制整数的功能。 界面如图。 函数过程定义如下: Function TranDec$(m%, r%) Dim StrDtoR$ Dim iB%, mr% StrDtoR = "" Do While m <> 0 mr = m Mod r m = m \ r If mr >= 10 Then StrDtoR = Chr(mr - 10 + 65) & StrDtoR '余数>=10 转换为A~F,最先求出的余数位数最低 Else StrDtoR = mr & StrDtoR '余数<10 直接连接,最先求出的余数位数最低 End If Loop TranDec = StrDtoR End Function
调用其他模块中的过程 • 在工程中的任何地方都能调用其它模块中的公用过程。公用过程三种形式: 一.窗体中的过程 所有窗体模块的外部调用必须指向包含此过程的窗体模块。如果在窗体模块 Form1 中包含 SomeSub 过程,则可使用下面的语句调用 Form1 中的过程: Call Form1.SomeSub(arguments) 二.类模块中的过程 与窗体中调用过程类似,在类模块中调用过程要调用与过程一致并且指向类实例的变量。 但是不同于窗体的是,在引用一个类的实例时,不能用类名作限定符。必须首先声明类的实例为对象变量,并用变量名引用它。 三.标准模块中的过程 从其它模块调用公共过程名时必须指定那个模块。例如,若在 Module1 中调用 Module2 中的 CommonName 过程,要用下面的语句: Module2.CommonName (arguments)
使用可选参数——参数传递 • 可选参数 • 在过程的参数列表中,参数前使用optional关键字就表示此参数可选。 • 如果指定了可选参数,则此参宿后面的其他参数也必须是可选的。 • 也可以给可选参数指定缺省值。
事件过程 ··· Call 过程一 ··· End Sub ① Sub 过程一 ··· Call 过程二(y) ··· End Sub Sub 过程二(n) ··· ··· ··· End Sub ③ ② ④ ⑤ ⑥ ⑧ ⑦ ⑨ 6.6 过程的嵌套 • VB的过程定义都是平行的关系,或者说是相对独立的存在,这在前几节的学习中我们应该可以感受的到:定义一个过程的时候,一个过程内部不能再定义另外一个过程。这里我们所说的过程嵌套,应该是过程的嵌套调用。 • 6.6.1过程的嵌套调用 • 在过程的调用中,可以使用嵌套调用。由于VB采用面向对象的程序设计技术,采用事件驱动的编程机制,所以程序的执行大多从事件过程开始。比如:在事件过程的执行过程中需要调用过程一,则系统此时会立刻去执行过程一,若在过程一的执行过程中中需要调用过程二,则系统此时会立刻去执行过程二(若在过程二的执行过程中中需要调用过程三的话依次类推),直到过程二执行完毕,系统将回到过程一执行调用过程二语句下面的语句,过程一执行完毕,系统将回到事件过程执行调用过程一语句下面的语句。一般来说,过程一和过程二,可以是子过程,也可以是函数过程。过程嵌套调用的执行原理如图所示(其中带圆圈的数值为执行步骤):
变量、过程的作用域 作用域:变量、过程随所处的位置不同,可被访问的范围。 1.过程的作用域 窗体/模块级:加Private关键字的过程,只能被定义的窗体或模块中的过程调用。 全局级:加Public关键字(缺省)的过程,可供该应用程序的所有窗体和所有标准模块中的过程调用。
2. 变量的作用域 局部变量:在过程内用声明的变量,只能在本过程中使用。 窗体/模块级变量:在“通用声明”段中用Dim语句或用Private语句 声明的变量,可被本窗体/模块的任何过程访问。 全局变量:在“通用声明”段中用Public语句声明的变量,可被本应用程序的任何过程或函数访问。
例如在下面一个标准模块文件中不同级的变量声明:例如在下面一个标准模块文件中不同级的变量声明: Public Pa As integer ' 全局变量 Private Mb As string *10 ' 窗体/模块级变量 Sub F1( ) Dim Fa As integer ' 局部变量 … End Sub Sub F2( ) Dim Fb As Single ' 局部变量 … End Sub
若在不同级声明相同的变量名,系统按局部、窗体/模块、全局次序访问如:若在不同级声明相同的变量名,系统按局部、窗体/模块、全局次序访问如: Public Temp As integer ' 全局变量 Sub Form_Load() Dim Temp As Integer ' 局部变量 Temp=10 ' 访问局部变量 Form1.Temp=20 ' 访问全局变量必须加窗体名 Print Form1.Temp, Temp ' 显示 20 10 End Sub
3. 静态变量 • 局部变量声明: • Dim 声明,随过程的调用而分配存贮单元,每次调用都对变量 • 初始化;过程体结束,变量的内容自动消失,存储单元释放。 • Static 声明,每次调用过程,变量保持原来的值。 • 例 • Private Sub Form_Click() • Dim i% ,isum% • For i = 1 To 5 • isum = sum(i) • Print isum • Next i • End Sub • Private Function sum(n As Integer) • Dim j As Integer • j = j + n • sum = j • End Function • Static j As Integer,结果? 结果为:1,2,3,4,5