本章主要内容
Sub过程 /Function
多窗体与 Sub Main
第 7章 过 程
VB应用程序是由过程组成的,过程是完成某种特殊
功能的一组独立的程序代码。两大类过程。
事件过程
Sub过程
通用过程
Function过程
事件过程是当某个事件发生时,对该事件作出响应的
程序段,它是 VB应用程序的主体
通用过程是独立于事件过程之外,可供其他过程调用的
程序段
过程调用示例
把相同的任务编成相对独立的“子过程”
当事件过程需要执行这个任务时,可使用调用语句 (如
Call)实行调用。子过程执行完后,会返回事件过程中调用语
句 Call的后续语句继续执行
通用过程又分为 Sub(子程序 )过程和 Function(函数 )过程
调用过程
……
Call SubA
……
Call SubA
……
Call SubB
……
子过程 SubA
子过程 SubB
7.1 通用过程
例 7.1 使用 Sub过程的示例 1
Private Sub Form_Load()
Show
Call mysub1(30)
Call mysub2
Call mysub2
Call mysub2
Call mysub1(30)
End Sub
程序运行结果
Private Sub mysub1(n)
Print String(n,"*")
End Sub
Private Sub mysub2()
Print "*"; Tab(30); "*"
End Sub
7.1.1 Sub过程
Form_Load()
事件过程
Call mysub1(30)
Call mysub2
Call mysub2
Call mysub2
Call mysub2
Call mysub1(30)
Mysub1过程
Mysub2过程
调用过程
在上述事件过程 Form_Load()中,通过 Call来分别调用
两个 Sub过程
在 Sub过程 mysub1(n)中,n为参数 (也称形参 ),当调
用过程 (即 Form_Load())通过 Call mysub1(30)(30称为实参 )
调用时,就把 30传给 n,这样调用后就输出 30个,*”号
过程 mysub2()不带参数,其功能是输出左右两边 的,*”

定义 格式:
[Private| Public | Static] Sub 过程名 ([参数表 ])
语句块
[Exit Sub]
End Sub
说明:
· 局部 (Private)过程、全局 (公用,Public)过程和静态 (Static)过

·
[ByVal |ByRef] 变量名 [( )][As 数据类型 ] …
ByVal表示该参数按值传递,ByRef表示该参数按地址传递
· 通过参数表传送参数
Sub过程可以获取调用过程传送的参数,也能通过参数表的
参数,把计算结果传回给调用过程
1,Sub过程的定义
Sub过程可以保存在两种模块中,窗体模块 (.frm)
和 标准模块 (.bas)
可以在代码窗口中直接键入来创建 Sub过程
选择“工具”菜单中的“添加过程”命令
2,Sub过程的建立
事件过程是通过事件驱动和由 系统自动调用 的,而 Sub过
程则 必须通过调用语句实行调用
调用 Sub过程有以下两种方法:
(1)使用 Call语句
Call 过程名 ([实参表] )
(2)直接使用过程名
过程名[实参表]
例如,调用名为 SubCal
Call SubCal(10)
SubCal 10
3,Sub过程的调用
Private Sub Form_Load()
Show
Print "VB的基本特点是,"
Call Sub_Cont
Print "面向对象的可视化编程 "
Call Sub_Cont
Print "事件驱动的编程机制 "
Call Sub_Cont
Print "结构化的设计语言 "
End Sub
在事件过程 Form_Load()中,有三处调用 Sub过程 Sub_Cont()
Private Sub Sub_Cont()
Dim resp As String
Do While True
resp = InputBox("是否继续 (y/n)? ")
If UCase(resp) = "N" Then End
If UCase(resp) = "Y" Then Exit Do
Loop
End Sub
例 7.2 使用 Sub过程示例 2
因为计算 5!和 10!都要用到阶乘 n! (n!= 1× 2× 3× … × n)
所以把计算 n!编成 Sub过程
采用 Print直接在窗体上输出结果,程序代码:
Private Sub Form_Load()
Show
Dim y As Long,s As Long
Call Jc(5,y)
s = y
Call Jc(10,y)
s = s + y
Print "5! + 10! ="; s
End Sub
程序运行结果:
5! + 10! = 3628920
Private Sub Jc(n As Integer,t As Long)
Dim i As Integer
t = 1
For i = 1 To n
t = t * i
Next i
End Sub
注意参数 n及 t的调用情况
例 7.3 计算 5! + 10!
允许用户自定义函数过程 (又称 Function过程 )
1
Function过程可返回一个值给调用程序
一般语法格式:
[Private | Public | Static] Function 函数名 ([参数表 ]) [As 数据类型 ]
[ Exit Function]
End Function
函数返回值的处理
7.1.2 Function过程
与 Sub过程相同
可以在“代码窗口”中直接输入来建立 Function过

也可以选择“工具”菜单中的“添加过程”命令来
建立 Function过程 (选择“函数”类型 )
2,Function过程的建立
把求两个数中的大数编成 Function过程,过程名为 Max
本例采用 InputBox函数输入三个数,判断出最大数后采用
Print直接输出在窗体上。 程序代码:
Private Sub Form_Load()
Show
Dim a As Single,b As Single,c As Single
Dim s As Single
a = Val(InputBox("输入第一个数 "))
b = Val(InputBox("输入第二个数 "))
c = Val(InputBox("输入第三个数 "))
s = max(a,b)
Print "最大数是,"; max(s,c)
End Sub
Function max(m,n) As Single
If m > n Then
max = m
Else
max = n
End If
End Function
例 7.4 输入三个数,求出它们的最大数
(1)
像使用 VB内部函数一样,只需写出函数名和相应的参数
s = Max(a,b)
Print Max(s,c)
(2)用 Call语句调用
与调用 Sub过程一样来调用 Function
Call Max(a,b)
当用这种方法调用 Function过程时,将会放弃返回值
3,Function过程的调用
分析,英文字母有大小写之分,只要将该字符转换为
大写,再判断是不是处于‘ A?~‘ Z?范围内,若是,则是英
文字母,否则不是
本例采用 InputBox函数来输入字符,判断后结果直接输
出在窗体上。
例 7.5 判断输入字符是不是英文字母
Private Sub Form_Load()
Dim s As String
Show
s = InputBox("请输入一个字符 ")
If Checha(s) Then
Print "***输入的字符是英文字母 ***"
Else
Print "***输入的字符不是英文字母 ***"
End If
End Sub
Function Checha(inp As String) As Boolean
Dim upalp As String
upalp = UCase(inp)
If "A" <= upalp And upalp <= "Z" Then
Checha = True
Else
Checha = False
End If
End Function
查看当前模块中有哪些 Sub过程和 Function过程 ;
要查看的是其他模块中的过程
4,查看过程
参数传递可以实现调用过程和被调过程之间的信息交换
两种方式,按值传递和按地址传递
7.2.1 形参与实参
形式参数 (简称形参 )
在被调过程中的参数。出现在 Sub过程和 Function过程中
形式参数可以是变量名和数组名
实际参数 (简称实参 )
在调用过程中的参数。过程调用时实参数据会传递给形参
形参表和实参表中的对应变量名可以不同,但实参和形参
的个数、顺序以及数据类型必须相同
7.2 参数传递
定义过程和调用过程的示例:
调用过程,Call Mysub(100,"计算机 ", 1.5)
定义过程,Sub Mysub(t As Integer,s As String,y As Single)
“形实结合,是按照位置结合的,即第一个实参值 (100)传送
给第一个形参 t,第二个实参值 (“计算机” )传送给第二个形参 s,
第三个实参值 (1.5)传送给第三个形参 y
数组可以作为形参出现在过程的形参表中
输入若干个 (不超过 100)个学生的成绩,求出平均分、最
高分及最低分
本例采用 InputBox函数来输入成绩,计算结果直接输出
到窗体上
例 7.6 求出学生成绩的平均分、最高分及最低分
Private Sub Form_Load()
Dim jc(100) As Integer,x As Integer,n As Integer,_
sum As Long,max As Integer,min As Integer
n = 0
Do While True
x = Val(InputBox("请输入第 " & n + 1 & _
"个学生的成绩 (-1结束 )"))
If x = -1 Then Exit Do
n = n + 1
jc(n) = x
Loop
If n > 0 Then
Call Caljc(n,jc(),sum,max,min)
Else
End
End If
Show
Print "平均分,"; Format(sum / n,"###.0")
Print "最高分,"; max
Print "最低分,"; min
End Sub
Sub Caljc(k As Integer,darray() As Integer,_
s As Long,m As Integer,n As Integer)
Dim i As Integer
s = darray(1), m = darray(1), n = darray(1)
If k = 1 Then Exit Sub
For i = 2 To k
s = s + darray(i)
If m < darray(i) Then m = darray(i)
If n > darray(i) Then n = darray(i)
Next i
End Sub
1,按地址传递
VB默认的数据传递方式
按地址传递 (关键字 ByRef):把实参变量的内存地址传
递给被调过程 (如 Sub过程 ),即 形参与实参使用相同的内存
地址单元,这样通过过程就可以改变变量本身的值
例 7.3中,Form_Load()事件过程是通过,Call Jc(5,y)”
和,Call Jc(10,y)”来调用过程 Jc(n,t)的,其中采用的第二个
参数就是按地址来传送数据的
7.2.2 按地址传递和按值传递
按值传递 (关键字 ByVal):通过常量传递实际参
数,即 传递参数值而不是传递它的地址
因为通用过程不能访问实参的内存地址,因而
在通用过程中对形参的任何操作都不会影响实参
2,按值传递
设置两个通用过程 Test1和 Test2,分别按值传递和按地址传递
Private Sub Form_Load()
Dim x As Integer
Show
x = 5
Print "执行 test1前,x="; x
Call test1(x)
Print "执行 test1后,test2前,x="; x
Call test2(x)
Print "执行 test2后,x="; x
End Sub
Sub test1(ByVal t As Integer)
t = t + 5
End Sub
Sub test2(s As Integer)
s = s - 5
End Sub
运行结果
执行 Test1前,x=5
执行 Test1后,Test2前,x=5
执行 Test2后,x=0
例 7.7 参数传递方式示例
7.3.1 过程的嵌套调用
在一个过程 (Sub过程和 Function过程 )中调用另外一个过程
例 7.8 输入两个数 n,m,求组合数 Cnm 的值
Cnm = n!m!(n-m)!
7.3 过程的嵌套与递归调用
Private Sub Form_Load()
Show
m = Val(InputBox("输入 m的值 "))
n = Val(InputBox("输入 n的值 "))
If m > n Then
MsgBox "输入数据错误 ",0,"检查错误 "
End
End If
Print "组合数是,"; Calcomb(n,m)
End Sub
Private Function Calcomb(n,m)
Calcomb = Jc(n) / (Jc(m) * Jc(n - m))
End Function
Private Function Jc(x)
t = 1
For i = 1 To x
t = t * i
Next i
Jc = t
End Function
程序中,采用了过程的嵌套调用方式。
在事件过程 Form_Load()中调用了 Calcomb
过程,而在 Calcomb过程中调用了三次 jc
过程。
一个过程调用过程本身,就称为过程的递归调用
采用递归方法来解决问题时,必须符合以下两个
(1)可以把要解的问题转化为一个新的问题,而这个新的
问题的解法仍与原来的解法相同;
(2)有一个明确的结束递归的条件 (终止条件 ),否则过程
将永远“递归”下去
7.3.2 过程的递归调用
可用下列的递归公式
1 n=1
n× (n-1)! n>1
本递归中,终止条件是 n=1
n! =
例 7.9 采用递归方法求 n! (n>0)
Private Sub Form_Load()
Dim n As Integer,m As Double
Show
n = Val(InputBox("输入 1~ 15之间的整数 "))
If n < 1 Or n > 15 Then
MsgBox "错误数据 ",0,"检查数据 "
End
End If
m= fac(n)
Print n; "!= "; m
End Sub
Private Function fac(n) As Double
If n > 1 Then
fac = n * fac(n - 1) '递归调用
Else
fac = 1 'n=1时,结束递归
End If
End Function
说明,当 n>1时,在 Fac过程中调用 Fac过程,然后 n减 1,再次调用 Fac过
程,这种操作一直持续到 n=1为止。例如,当 n=3时,求 Fac(3)变成求
3× Fac(2),求 Fac(2)变成求 2× Fac(1),而 Fac(1)为 1,递归结束。以后再逐层
返回,递推出 Fac(2)及 Fac(3)的值
注意,在某次调用 Fac过程时并不是立即得到 Fac(n)的值,而是一次又一
次地进行递归调用,到 Fac(1)时才有确定的值,然后通用过程逐层返回中依次
算出 Fac(2),Fac(3)的值
Form_Load过程
m=Fac(3)
Fac过程
调用
Fac(3)值为 6
参数 n为 3
Fac=3*Fac(2)
Fac过程
调用
Fac(2)值为 2
参数 n为 2
Fac=2*Fac(1)
Fac过程
调用
Fac(1)值为 1
参数 n为 1
Fac=1
递归调用过程 (n=3)
求两个正整数 n和 m的最大公约数,解题方法见例 5.8
也可采用递归调用方法来求解,递归终止条件是余数为 0
Private Sub Form_Load()
Show
m = Val(InputBox("输入 m的值 "))
n = Val(InputBox("输入 n的值 "))
Print m; "和 "; n; "的最大公约数是,"; gys(n,m)
End Sub
Private Function gys(n,m)
p = n Mod m
If p = 0 Then '终止条件
gys = m
Else
gys = gys(m,p) 'm→n,p→m,再调用
End If
End Function
例 7.10 用递归方法求两个正整数 n和 m的最大公约数
变量的作用域 (空间 )和生存期 (时间 )
7.4.1 代码模块的概念
应用程序通常包括 窗体文件 (.frm)、模块文件 (.bas)和类模块 (.cls)
应用程序
工程文件
(.vbp)
窗体模块
文件 (.frm)
Sub
过程
Function
过程 事件过程声明部分
类模块
文件 (.cls)
标准模块
文件 (.bas)
Sub
过程
Function
过程声明部分
Sub Main
过程
7.4 变量的作用范围
变量根据所处的位置或被定义不同,其作用范围也不同
局部变量、模块级变量和全局变量
1,局部变量
在一个过程内部用 Dim或 Static声明的变量称为局部变量。只
能在本过程中有效。在一个窗体中,不同过程中定义的局部变量
Private Sub Command1_Click()
Dim Count As Integer
Dim Sum As Integer
.,,
End Sub
Private Sub Command2_Click()
Dim Sum As Integer
.,,
End Sub
这两个同名变量 Sum没有任何联系
7.4.2 变量的作用域
模块级变量可以在一个窗体的不同过程中使用
在窗体模块的声明部分中声明该变量
如果用 Private或 Dim来声明,则该变量只能在本窗体 (或
本模块 )
以 Public声明的变量,允许在其他窗体和模块中引用
2,模块级变量
全局变量可以被应用程序中任何一个窗体和模
块直接访问。
全局变量要在标准模块文件 (.bas)中的声明部分
用 Global或 Public语句来声明。
格式:
Global 变量名 As
Public 变量名 As 数据类型
3,全局变量
生存期,也即变量能够保持其值的时间
分为 动态变量 和 静态变量
1,动态变量
动态变量是指程序运行进入变量所在的过程时,才分配给
该变量的内存单元,经过处理退出该过程时,该变量占用的内存
单元自动释放,其值消失。当再次进入该过程时,所有的动态变
量将重新初始化。
使用 Dim关键字 在过程中声明的局部变量属于动态变量
7.4.3 变量的生存期
静态变量是指程序进入该变量所在的过程,经过处理退出
该过程时,其值仍被保留,即变量所占的内存单元没有释放。
使用 Static关键字 在过程中声明的局部变量属于静态变量
例 7.11 使用 Static Sub语句的示例
Static Sub Subtest()
Dim t As Integer 't为静态变量
t = 2 * t + 1
Print t
End Sub
Private Sub Command1_Click()
Call Subtest '调用子过程 Subtest
End Sub
1,静态变量
运行后,多次单击命令按钮 Command1,
1
3
7
……
将 Static Sub改为 Private Sub后,运行过程中多次单击命
令按钮 Command1,执行结果为:
1
1
1
……
7.5.1 多窗体处理
在多窗体程序中,每个窗体可以有自己的界面和程序代码,
完成不同的操作
1,添加窗体
通过“工程”菜单中的“添加窗体”命令来实现
2,删除窗体
选择“工程”菜单中的“移除”命令
3,保存窗体
选择“文件”菜单中的“保存”或“另存为”命令
4,设置启动窗体
在“工程属性”对话框中设置
7.5 多窗体与 Sub Main过程
Load语句:
UnLoad语句
Show方法:
Hide方法,隐藏窗体。即不在屏幕上显示,但仍在内存
中,因此它与 UnLoad的作用是不一样的
5,有关语句和方法
创建 3个窗体和 1个标准模块
(1)主窗体 (Form1)
本窗体上建立了,输入参数, (Command11)、,画
圆, (Command12)和,结束, (Command13)三个命令按钮
设置为启动窗体
例 7.12 多窗体应用示例
Private Sub Command11_Click() '主窗体“输入参数”按钮
Form1.Hide '隐藏主窗体
Form2.Show '显示“输入参数”窗体
End Sub
Private Sub Command12_Click() '主窗体“画圆”按钮
Form1.Hide '隐藏主窗体
Form3.Show '显示“画圆”窗体
End Sub
Private Sub Command13_Click() '主窗体“结束”按钮
Unload Form1
Unload Form2
Unload Form3
End
End Sub
(2)“输入参数”窗体 (Form2)
这是在主窗体上单击了“输入参数”按钮后弹出的窗体,
用于输入圆的坐标位置 (x,y)和半径 (r)。窗体上建立了 3个文本
框 (Text21,Text22和 Text23)和 1个“返回”命令按钮
(Command21)
Private Sub Command21_Click() '“输入参数”窗体的“返回”按

X = Val(Text21.Text)
Y = Val(Text22.Text)
R = Val(Text22.Text)
Form2.Hide '隐藏“输入参数”窗体
Form1.Show '显示主窗体
End Sub
(3)“画圆”窗体 (Form3)
这是在主窗体上单击了“画圆”按钮后弹出的窗体。窗
体上建立了 1个图片框和 2个命令按钮,如图 7.10所示。用户可
以单击“画圆” (Command31)命令按钮,使之按给定参数在图
片框上画圆。
Private Sub Command31_Click() '“画圆”窗体的“画圆”按钮
Picture1.Cls
Picture1.Circle (X,Y),R
End Sub
Private Sub Command32_Click() '“画圆”窗体的“返回”按钮
Form3.Hide '隐藏“画圆”窗体
Form1.Show '显示主窗体
End Sub
(4)标准模块 (Modulel)
由于在各窗体之间需要使用公共变量来传送数据,所以
建立一个标准模块 Modulel,对用到的 全局变量 X,Y和 R进
行声明
运行程序后,首先显示主窗体。在主窗体上,用户可通
过“输入参数”和“画圆”两个按钮来选择进入不同的窗体,
例如单击“输入参数”按钮,则主窗体消失,显示“输入参
数”窗体。在“输入参数”窗体或“画圆”窗体上,单击
“返回”按钮,又可以隐藏当前窗体和重现主窗体
程序一般从 启动窗体的 Form_Load过程 开始执行
有时在程序启动时不加载任何窗体,而是首先执行一段
程序代码,此时可把要执行的程序代码放在 Sub Main过程
中,并指定 Sub Main为“启动对象”。 应用程序在运行时
会先执行 Sub Main过程
在一个工程中只能有一个 Sub Main
设置 Sub Main过程为“启动对象”的方法,在“工程属
性”对话框的“通用”选项卡中,从“启动对象”下拉列表
框中选中,Sub Main”
7.5.2 Sub Main过程
建立两个窗体 (Form1及 Form2)和 1个
标准模块 (Module1)。标准模块包含一个
Sub Main过程。如图 7.12所示
两个窗体分别显示当前日期和时间
运行程序时首先判断当前时间是否超
过 12时,若超过,则显示窗体 Form2;否
则显示窗体 Form1
例 7.13 使用 Sub Main过程示例
(1)Sub Main过程
编写的 Sub Main过程代码如图 7.12所示。再设置 Sub
Main过程为“启动对象”
(2)窗体 Forml
本窗体显示当前日期,其 Form_Load事件过程代码如下:
Private Sub Form_Load()
Show
Print "这里是窗体 Form1"
Print "当前日期, "; Date
End Sub
(3)窗体 Form2
本窗体显示当前时间,其 Form_Load事件过程代码如下:
Private Sub Form_Load()
Show
Print "这里是窗体 Form2"
Print "现在时间, "; Time
End Sub
程序运行时,先执行 Sub Main过程,即取出当前时数 t,
再根据条件,t<=12”来决定是显示 Form1,还是显示 Form2
不需要加载任何窗体 (这种情况极少 )时,可把执
行的代码直接写入 Sub Main过程中
例 7.14 绘制一个圆,使之从小变大,再从大变小
分析,为了得到一个圆大小变动的 动画效果,先在某一位
置上绘制一个圆,显示一段时间 (延时 )后抹除,接着在下一
位置上依此处理,直到指定位置为止
抹除方法是采用底色 (背景色 )来掩盖图形
采用 Circle方法可以画一个圆
延时时间:利用 Timer函数,该函数返回系统时钟从午夜
开始计算的秒数 (带两位小数 )
Private Sub Delayloop(delaytime) '延迟过程
loopfinish = Timer + delaytime
Do While Timer < loopfinish '利用空循环实现延

Loop
End Sub
7.6 程序举例
Private Sub Form_Load()
Show
Form1.BackColor = QBColor(15) '设置背景颜色
Call Pict(30,1600,30) '从小变大
Call Pict(1600,30,-30) '从大变小
End Sub
Private Sub Pict(a,b,c)
For i = a To b Step c
Call Plot(i,4) '显示圆
Delayloop 0.1 '延迟 0.1秒
Call Plot(i,15) '抹除
Next i
End Sub
Private Sub Plot(r,clr)
Form1.Circle (2400,1600),r,QBColor(clr) '画圆
End Sub
Private Sub Form_Load()
Show
Randomize
Form1.BackColor = QBColor(15) '设置背景颜色
For i = 1 To 200 '控制进行 200次
clr = Int(15 * Rnd) '产生 0~ 14颜色码
x = 400 + Int(4000 * Rnd) '产生圆心 x坐标值
y = 400 + Int(4000 * Rnd) '产生圆心 y坐标值
r = 300 + Int(500 * Rnd) '产生圆半径 r值
Call Plot(x,y,r,clr) '画圆
Delayloop 0.1 '延时 0.1秒
Call Plot(x,y,r,15) '抹除
Next i
End Sub
Private Sub Plot(x,y,r,clr)
Form1.Circle (x,y),r,QBColor(clr) '画圆
End Sub
例 7.15 变幻圆 随机产生圆的有关参数
在窗体上建立 3个文本框,使之以不同效果显示文
字,2008年世界奥运会将在中国北京市举行,
第一个文本框 Text1从左到右逐字显示,直到把整行文字
显示出来;
第二个文本框 Text2使文字从左到右作水平移动;
第三个文本框 Text3以闪动方式显示文字
设计阶段 运行阶段
例 7.16 动态文字
Dim txt As String,n As Integer,k As Integer
Private Sub Form_Load()
n = 0
txt = "2008年世界奥运会将在中国北京市举行 "
k = Len(txt)
Text1.ForeColor = RGB(255,0,0) '红色
Text2.ForeColor = RGB(0,0,0) '黑色
Text3.ForeColor = RGB(0,0,255) '蓝色
End Sub
Private Sub Timer1_Timer()
n = n + 1 ?模块级变量 n是关键参数
If n <= k Then
Text1.Text = Left(txt,n)
Text2.Text = Space(2 * (k - n)) + Left(txt,n)
Else
n = 0
Text1.Text = ""
Text2.Text = ""
End If
If n Mod 2 = 0 Then
Text3.Text = txt 'n为偶数时显示
Else
Text3.Text = "" 'n为奇数时清除
End If
End Sub
接收一个算术四则运算式,计算并显示该运算式的值,如
,2*10/4+40/5-3*2”,应得结果 7
(1)解题方法
先按加、减号分解出若干个只有乘除运算的式,再对各个式
子进行乘或除运算,然后把各个式子的值相加或相减,则可求出
整个运算式的值
对于运算式,2*10/4+40/5-3*2”,先分解出 3 个乘除式,即,+2*10/4”、
,+40/5”和,-3*2”(分别保存在数组元素中,如 s(1),s(2),s(3)),再分别求出
这些乘除式的值,即为,+5”、,+8”
和,-6”,并对这些值进行加或减
运算,则可求出最后结果 7
(2)创建应用程序的用户
界面和设置对象属性
例 7.17 计算四则运算式
(3)编写程序代码
功能要求,用户在文本框 Text1中输入四则运算式,单击“计
算”按钮 (Command1)后,在文本框 Text2中输出计算结果
Dim s(20) As String '数组 s存放按 +,-号分解出来的式子
Private Sub Command1_Click()
n = handle1(Text1.Text) '分解出 n个式子
total = 0 '累加数初值
For i = 1 To n
m = handle2(s(i)) '计算各乘除式的值
total = total + m '各式累加
Next i
Text2.Text = total '显示结果
End Sub
Function handle1(ByVal t) As Single
If Left(t,1) <> "+" And Left(t,1) <> "-" Then
t = "+" + t '使以 "+"开头,方便处理
End If
k = 0
Do While t <> ""
n1 = InStr(2,t,"+") '找 +号
n2 = InStr(2,t,"-") '找 -号
k = k + 1
Select Case True
Case n1 = 0 And n2 = 0 '无 +,-号
s(k) = t '取剩余部分
t = ""
Case n2 = 0 '无 -号
s(k) = Mid(t,1,n1 - 1) '取到 +号前
t = Mid(t,n1) '从该 +号开始截取
Case n2 < n1 Or n1 = 0 '先遇到 -号或无 +号
s(k) = Mid(t,1,n2 - 1) '取到 -号前
t = Mid(t,n2) '从该 -号开始截取
Case n1 < n2 '先遇到 +号
s(k) = Mid(t,1,n1 - 1) '取到 +号前
t = Mid(t,n1) '从 +号开始截取
End Select
Loop
handle1 = k '分解出来的式子个数
End Function
Function handle2(x) As Single
f = Left(x,1) '取出符号 +或 -
x = "*" + Mid(x,2) '前头加 *,方便处理
Sum = 1 '累乘 /除的初值
Do While x <> ""
m1 = InStr(2,x,"*") '找 *号
m2 = InStr(2,x,“/”) ?找 /号
Select Case True
Case m1 = 0 And m2 = 0 '已无乘除号
y = Mid(x,1)
x = ""
Case m1 = 0 Or (m1 > m2 And m2 > 0)
y = Mid(x,1,m2 - 1) ?取至除号前
x = Mid(x,m2)
Case m2 = 0 Or (m2 > m1 And m1 > 0)
y = Mid(x,1,m1 - 1) ?取至乘号前
x = Mid(x,m1)
End Select
If Left(y,1) = "*" Then ‘乘除运算
Sum = Sum * Val(Mid(y,2))
Else
Sum = Sum / Val(Mid(y,2))
End If
Loop
If f = "+" Then '带回 +,-号
handle2 = Sum
Else
handle2 = -Sum
End If
End Function