在对表达式求值过程中用到了后缀表达式:
比如: 2+3*(1.5-6*(3-2+4)/3)
其后缀表达式为:2 3 1.5 6 3 2 – 4 + * 3 / - * +
下面直接贴出VB代码,
Option
Base
1
'
让数组的下标从 1 开始
Dim
ptr
As
String
'
遍历源字符串的指针
Dim
str
As
String
'
无空格字符串
Dim
strIndex
As
Integer
'
str迭代量
Dim
dstr()
As
String
'
存放后缀表达式各字符串
Dim
dIndex
As
Integer
'
dstr() 迭代量
Dim
Stack()
As
String
'
一个栈,在后缀表达式转换过程可以用于符号栈,在求值可以存放值
Dim
Top
As
Integer
'
指向栈顶,初始值为1
Dim
InV
As
Boolean
'
判断是否在一个超过两位数字的数字内
Dim
strlen
As
Integer
'
dstr, stack的数组维数
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
'
主要程序,用于遍历源字符串str1
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Public
Sub mainPro()
Sub mainPro(str1 As String)
' 迭代量初始化
strIndex = 1
dIndex = 0
Top = 1
InV = False
str = "" '切记要将str初始化
str1 = str1 + "#" ' 添加结束符"#"
str1 = Trim(str1) ' 清除str1两端的空格
ptr = Mid(str1, strIndex, 1)
' 消除str1里面的空格 ,其实这个初始化过程可以考虑另写一个函数
Do While ptr <> "#"
If ptr <> " " Then
str = str + ptr
End If
strIndex = strIndex + 1
ptr = Mid(str1, strIndex, 1)
Loop
str = str + "#"
strlen = Len(str) + 2 ' 取长度,然后重新定义动态数组
ReDim dstr(strlen)
ReDim Stack(strlen)
Call push("#")
strIndex = 1
ptr = Mid(str, strIndex, 1)
' 判断str第一个字符是否"+" or "-"
If ptr = "+" Or ptr = "-" Then
push (ptr)
dIndex = dIndex + 1
dstr(dIndex) = "0"
strIndex = strIndex + 1
End If
' 开始遍历str,遇到"#"停止
Do While ptr <> "#"
Select Case ptr
Case "0" To "9", "."
If InV Then
dstr(dIndex) = dstr(dIndex) + ptr
Else
dIndex = dIndex + 1
dstr(dIndex) = ptr
InV = True
End If
Case "+", "-", "*", "/"
InV = False
dealop (ptr)
Case "("
Call push(ptr)
Case ")"
Call dealclose
Case Else
MsgBox ("表达式出现未知字符")
End Select
strIndex = strIndex + 1
ptr = Mid(str, strIndex, 1)
Loop
If Top > 1 Then
Dim tmp As String
tmp = pop()
Do While tmp <> "#"
dIndex = dIndex + 1
dstr(dIndex) = tmp
tmp = pop()
Loop
End If
dIndex = dIndex + 1
dstr(dIndex) = "#"
End Sub
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Private
Sub push()
Sub push(ptr As String)
If Top > strlen Then
MsgBox ("符号栈上溢出 in push()")
End
End If
Stack(Top) = ptr
Top = Top + 1
End Sub
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Private
Function pop()
Function pop() As String
If Top <= 1 Then
MsgBox ("符号栈下溢 in pop()")
End
End If
Top = Top - 1
pop = Stack(Top)
End Function
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Private
Function getTop()
Function getTop() As String
If Top <= 1 Then
MsgBox ("栈空 in getTop()")
End
End If
getTop = Stack(Top - 1)
End Function
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Private
Sub dealop()
Sub dealop(ptr As String)
Dim stillIn As Boolean ' 判断是否正在处理当前操作符,即当前操作符优先级小于等于符号栈顶的
' 操作符时,应该将栈顶操作符出栈,放到dstr中
Dim tmp As String ' 用来存放栈顶元素
stillIn = True
Select Case ptr
Case "+"
If Mid(str, strIndex - 1, 1) = "(" Then
dIndex = dIndex + 1
dstr(dIndex) = "0"
Call push(ptr)
Else
Do While (stillIn)
tmp = getTop()
Select Case tmp
Case "*", "/", "-", "+"
dIndex = dIndex + 1
dstr(dIndex) = pop()
Case "(", "#"
Call push(ptr)
stillIn = False
Case Else
MsgBox ("运算符出错 in +")
End '结束程序
End Select
Loop
End If
Case "-"
If Mid(str, strIndex - 1, 1) = "(" Then
dIndex = dIndex + 1
dstr(dIndex) = "0"
push (ptr)
Else
Do While (stillIn)
tmp = getTop()
Select Case tmp
Case "*", "/", "+", "-"
dIndex = dIndex + 1
dstr(dIndex) = pop()
Case "(", "#"
Call push(ptr)
stillIn = False
Case Else
MsgBox ("运算符出错 in -")
End
End Select
Loop
End If
Case "*"
Do While (stillIn)
tmp = getTop()
Select Case tmp
Case "/", "*"
dIndex = dIndex + 1
dstr(dIndex) = pop()
Case "(", "#", "+", "-"
Call push(ptr)
stillIn = False
Case Else
MsgBox ("运算符出错 in *")
End
End Select
Loop
Case "/"
Do While (stillIn)
tmp = getTop()
Select Case tmp
Case "*", "/"
dIndex = dIndex + 1
dstr(dIndex) = pop()
Case "(", "#", "+", "-"
Call push(ptr)
stillIn = False
Case Else
MsgBox ("运算符出错 in /")
End
End Select
Loop
Case Else
MsgBox ("Error happen in dealop() case else")
End
End Select
End Sub
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Private
Sub dealclose()
Sub dealclose()
Dim tmp As String ' 用来存放栈顶元素
tmp = pop()
Do While tmp <> "("
dIndex = dIndex + 1
dstr(dIndex) = tmp
tmp = pop()
Loop
End Sub
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
Public
Function execute()
Function execute() As String
Dim v1 As String, v2 As String, v3 As String ' 定义运算暂存的变量
dIndex = 1
ptr = dstr(dIndex)
Do While ptr <> "#"
Select Case ptr
Case "+"
v1 = pop()
v2 = pop()
v3 = Val(v1) + Val(v2) ' 这里会将val值隐式转换成string么?
push (v3)
Case "-"
v1 = pop()
v2 = pop()
v3 = Val(v2) - Val(v1)
push (v3)
Case "*"
v1 = pop()
v2 = pop()
v3 = Val(v1) * Val(v2)
push (v3)
Case "/"
v1 = pop()
v2 = pop()
If Val(v1) = 0 Then
MsgBox ("式子中除数为 0 ")
End
End If
v3 = Val(v2) / Val(v1)
push (v3)
Case Else
push (ptr)
End Select
dIndex = dIndex + 1
ptr = dstr(dIndex)
Loop
v1 = pop() '判断最终结果绝对值是否小于1,如果
If Abs(Val(v1)) < 1 Then
v1 = Format(Val(v1), "0.######")
End If
execute = v1
End Function