Office中国论坛/Access中国论坛
标题:
再谈Eval——关于计算器的那些事
[打印本页]
作者:
roych
时间:
2023-5-14 19:48
标题:
再谈Eval——关于计算器的那些事
不久前,我遇到一个朋友,他说看到了一个Access短视频,里面有个函数,可以实时显示计算结果。我很奇怪,为什么会写这样的函数。他说,人最大的烦恼,就是不能随时实现愿望。如果什么愿望都能像这个函数一样,随时实现,你说多开心。这个函数本来打算发给你,现在看起来,我们得一起研究了。
Function Calculate(s As String) As Long
Dim ops() As Long
ReDim ops(0)
ops(0) = 1
Dim sign As Long
sign = 1
Dim ret As Long
ret = 0
Dim n As Long
n = Len(s)
Dim i As Long
i = 1
Do While i <= n
Select Case Mid(s, i, 1)
Case " "
i = i + 1
Case "+"
sign = ops(UBound(ops))
i = i + 1
Case "-"
sign = -ops(UBound(ops))
i = i + 1
Case "("
ReDim Preserve ops(UBound(ops) + 1)
ops(UBound(ops)) = sign
i = i + 1
Case ")"
ReDim Preserve ops(UBound(ops) - 1)
i = i + 1
Case Else
Dim num As Long
num = 0
Do While i <= n And IsNumeric(Mid(s, i, 1))
num = num * 10 + CLng(Mid(s, i, 1))
i = i + 1
Loop
ret = ret + sign * num
End Select
Loop
Calculate = ret
End Function
复制代码
我看了一眼,虽然可以实时显示,但还是太复杂了。我很奇怪,为什么博主不用eval函数,而是非要使用数组?
关于eval函数,很久以前写过一个帖子,用于计算学杂费之类:
http://www.office-cn.net/thread-108898-1-1.html
在我看来,使用eval函数应该会更简单些。另外,考虑到只有加减法,根据加减法结合律,小括号对加减运算没任何影响,所以干脆去掉小括号的判定,于是有了这个简单版本:
Function StrtoLong(ByVal strExpress As String) As Long
Dim strResult As String
'如果最后一个字符是运算符,剔除
If InStr(1, "+-*/^", Right(strExpress, 1)) Then
strResult = Left(strExpress, Len(strExpress) - 1)
Else
strResult = strExpress
End If
StrtoLong = Eval(strResult)
End Function
复制代码
写完这个,后来想想,既然非要使用小括号,那不如把乘、除和幂方也加上吧,便有了一个进阶版。
这里就不贴代码了。有需要的版友可以自行下载附件。
需要说明的是:
三个窗体都没有进行错误处理,
使用时请确保输入字符为指定的字符。否则会出错,导致Access”假死“
(目前我遇到的是这个情况)。
进阶版虽然支持小括号运算,但暂时还不能处理嵌套小括号的问题。这是因为需要使用正则表达式来提取小括号内部的表达式,再进行处理,可能需要用到递归算法,处理完毕后再拼接回去,过程相对复杂。而且一旦存在多个嵌套小括号的情况,复杂度将成倍增加。因此暂时不加上。
[attach]64552[/attach]
作者:
huanghyd
时间:
2023-5-14 20:05
学习了,谢谢大神分享
欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/)
Powered by Discuz! X3.3