设为首页收藏本站Access中国

Office中国论坛/Access中国论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

返回列表 发新帖
查看: 930|回复: 1
打印 上一主题 下一主题

[模块/函数] 再谈Eval——关于计算器的那些事

[复制链接]
跳转到指定楼层
1#
发表于 2023-5-14 19:48:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
不久前,我遇到一个朋友,他说看到了一个Access短视频,里面有个函数,可以实时显示计算结果。我很奇怪,为什么会写这样的函数。他说,人最大的烦恼,就是不能随时实现愿望。如果什么愿望都能像这个函数一样,随时实现,你说多开心。这个函数本来打算发给你,现在看起来,我们得一起研究了。
  1. Function Calculate(s As String) As Long
  2.     Dim ops() As Long
  3.     ReDim ops(0)
  4.     ops(0) = 1

  5.     Dim sign As Long
  6.     sign = 1

  7.     Dim ret As Long
  8.     ret = 0
  9.    
  10.     Dim n As Long
  11.     n = Len(s)

  12.     Dim i As Long
  13.     i = 1

  14.     Do While i <= n
  15.         Select Case Mid(s, i, 1)
  16.         
  17.             Case " "
  18.                 i = i + 1
  19.             Case "+"
  20.                 sign = ops(UBound(ops))

  21.                 i = i + 1

  22.             Case "-"
  23.                 sign = -ops(UBound(ops))
  24.                 i = i + 1

  25.             Case "("

  26.                 ReDim Preserve ops(UBound(ops) + 1)

  27.                 ops(UBound(ops)) = sign

  28.                 i = i + 1

  29.             Case ")"

  30.                 ReDim Preserve ops(UBound(ops) - 1)

  31.                 i = i + 1

  32.             Case Else
  33.                 Dim num As Long
  34.                 num = 0

  35.                 Do While i <= n And IsNumeric(Mid(s, i, 1))

  36.                     num = num * 10 + CLng(Mid(s, i, 1))

  37.                     i = i + 1
  38.                 Loop
  39.                 ret = ret + sign * num
  40.         End Select
  41.     Loop

  42.     Calculate = ret

  43. End Function
复制代码
我看了一眼,虽然可以实时显示,但还是太复杂了。我很奇怪,为什么博主不用eval函数,而是非要使用数组?
关于eval函数,很久以前写过一个帖子,用于计算学杂费之类:
http://www.office-cn.net/thread-108898-1-1.html
在我看来,使用eval函数应该会更简单些。另外,考虑到只有加减法,根据加减法结合律,小括号对加减运算没任何影响,所以干脆去掉小括号的判定,于是有了这个简单版本:
  1. Function StrtoLong(ByVal strExpress As String) As Long
  2.     Dim strResult As String
  3.     '如果最后一个字符是运算符,剔除
  4.     If InStr(1, "+-*/^", Right(strExpress, 1)) Then
  5.         strResult = Left(strExpress, Len(strExpress) - 1)
  6.         
  7.     Else
  8.         strResult = strExpress
  9.     End If

  10.     StrtoLong = Eval(strResult)
  11. End Function
复制代码
写完这个,后来想想,既然非要使用小括号,那不如把乘、除和幂方也加上吧,便有了一个进阶版。
这里就不贴代码了。有需要的版友可以自行下载附件。
需要说明的是:
  • 三个窗体都没有进行错误处理,使用时请确保输入字符为指定的字符。否则会出错,导致Access”假死“(目前我遇到的是这个情况)。
  • 进阶版虽然支持小括号运算,但暂时还不能处理嵌套小括号的问题。这是因为需要使用正则表达式来提取小括号内部的表达式,再进行处理,可能需要用到递归算法,处理完毕后再拼接回去,过程相对复杂。而且一旦存在多个嵌套小括号的情况,复杂度将成倍增加。因此暂时不加上。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 分享淘帖 订阅订阅
2#
发表于 2023-5-14 20:05:08 | 只看该作者
学习了,谢谢大神分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-4-27 07:58 , Processed in 0.081702 second(s), 26 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表