找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 460|回复: 3

[VBA程序]:公式解析源代码,仅包含四则运算部分。

[复制链接]

已领礼包: 181个

财富等级: 日进斗金

发表于 2003-11-20 21:38:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
花了两天时间,终于将一个C#编写的公式解析程序转化为VB的代码,不过还有很多东西没有实现,比如函数和变量功能的实现,有兴趣的可以自己研究,也可以参考编译原理这本书。



  1.   [FONT=courier new]
  2. Enum tokTypes
  3.     tokNONE = 0
  4.     tokDELIMITER = 1
  5.     tokVARIABLE = 2
  6.     tokFUNCTION = 3
  7.     tokNumber = 4
  8.     tokString = 5
  9. End Enum
  10. Dim exp As String
  11. Dim expIdx As Integer
  12. Dim token As String
  13. Dim tokType As tokTypes

  14. ' 判断是否指定的分隔符
  15. Function IsDelim(ByVal c As String) As Boolean
  16.     If InStr("+-*/&()", c) Then IsDelim = True
  17. End Function

  18. ' 判断是否是字母
  19. Function IsLetter(ByVal c As String) As Boolean
  20.     If Asc(c) >= 65 And Asc(c) <= 90 Then
  21.         IsLetter = True
  22.     ElseIf Asc(c) >= 97 And Asc(c) <= 122 Then
  23.         IsLetter = True
  24.     End If
  25. End Function

  26. '判断是否是数字
  27. Function IsDigit(ByVal c As String) As Boolean
  28.     If Asc(c) >= 48 And Asc(c) <= 57 Then IsDigit = True
  29. End Function

  30. '判断是否是空格
  31. Function IsWhiteSpace(ByVal c As String) As Boolean
  32.     If c = " " Then IsWhiteSpace = True
  33. End Function

  34. '取计算单元标记
  35. Sub GetToken()
  36.     tokType = tokNONE
  37.     token = ""
  38.     If expIdx > Len(exp) Then Exit Sub
  39.     '忽略前置空格
  40.     Do While (expIdx <= Len(exp) And IsWhiteSpace(Mid(exp, expIdx, 1)))
  41.         expIdx = expIdx + 1
  42.         If expIdx > Len(exp) Then Exit Sub
  43.     Loop
  44.     '分隔符
  45.     If (IsDelim(Mid(exp, expIdx, 1))) Then
  46.         token = token + Mid(exp, expIdx, 1)
  47.         expIdx = expIdx + 1
  48.         tokType = tokDELIMITER
  49.     '函数或者变量
  50.     ElseIf (IsLetter(Mid(exp, expIdx, 1))) Then
  51.        token = token + Mid(exp, expIdx, 1)
  52.         expIdx = expIdx + 1
  53.         If expIdx > Len(exp) Then Exit Sub
  54.         Do While (IsLetter(Mid(exp, expIdx, 1)) And IsDigit(Mid(exp, expIdx, 1)))
  55.             token = token + Mid(exp, expIdx, 1)
  56.             expIdx = expIdx + 1
  57.             If expIdx > Len(exp) Then Exit Do
  58.         Loop
  59.         tokType = tokFUNCTION
  60.     '数字
  61.     ElseIf (IsDigit(Mid(exp, expIdx, 1))) Then
  62.         Do While Not (IsDelim(Mid(exp, expIdx, 1)))
  63.             token = token + Mid(exp, expIdx, 1)
  64.             expIdx = expIdx + 1
  65.             If expIdx > Len(exp) Then Exit Do
  66.         Loop
  67.         tokType = tokNumber
  68.     '字符串
  69.     ElseIf (Mid(exp, expIdx, 1) = """") Then
  70.         expIdx = expIdx + 1
  71.         Do While (Mid(exp, expIdx, 1) <> """")
  72.             token = token + Mid(exp, expIdx, 1)
  73.             expIdx = expIdx + 1
  74.             If expIdx > Len(exp) Then Exit Do
  75.         Loop
  76.         expIdx = expIdx + 1
  77.         tokType = tokString
  78.     End If
  79. End Sub

  80. Function Evaluate(ByVal expstr As String)
  81.     exp = expstr
  82.     expIdx = 1
  83.     GetToken
  84.     If (tokType = tokNONE And token = """") Then MsgBox ("No Expression Present!")
  85.     Evaluate = EvalExp2()
  86.     MsgBox Evaluate
  87. End Function

  88. '处理加法或减法
  89. Function EvalExp2() As String
  90.     Dim result As String
  91.     Dim op As String
  92.     Dim partialResult As String
  93.     EvalExp2 = EvalExp3()
  94.     op = token
  95.     Do While (op = "+" Or op = "-" Or op = "&")
  96.         GetToken
  97.         partialResult = EvalExp3()
  98.         Select Case op
  99.             Case "-":
  100.                 EvalExp2 = CDbl(EvalExp2) - CDbl(partialResult)
  101.             Case "+":
  102.                 EvalExp2 = CDbl(EvalExp2) + CDbl(partialResult)
  103.             Case "&":
  104.                 EvalExp2 = EvalExp2 + partialResult
  105.         End Select
  106.         op = token
  107.     Loop
  108. End Function

  109. '处理乘法或除法
  110. Function EvalExp3() As String
  111.     Dim op As String
  112.     Dim partialResult  As String
  113.     EvalExp3 = EvalExp5
  114.     op = token
  115.     Do While (op = "*" Or op = "/")
  116.         GetToken
  117.         partialResult = EvalExp5
  118.         Select Case op
  119.             Case "*":
  120.                 EvalExp3 = CDbl(EvalExp3) * CDbl(partialResult)
  121.             Case "/":
  122.                 EvalExp3 = CDbl(EvalExp3) / CDbl(partialResult)
  123.         End Select
  124.         op = token
  125.     Loop
  126. End Function

  127. '处理一元
  128. Function EvalExp5() As String
  129.     Dim op As String
  130.     Dim partialResult  As String
  131.     op = ""
  132.     If ((tokType = tokDELIMITER) And (token = "+" Or token = "-")) Then
  133.         op = token
  134.         GetToken
  135.     End If
  136.     EvalExp5 = EvalExp6
  137.     If (op = "-") Then EvalExp5 = -1 * EvalExp5
  138. End Function

  139. '处理括号
  140. Function EvalExp6() As String
  141.     If ((token = "(")) Then
  142.         GetToken
  143.         EvalExp6 = EvalExp2()
  144.         GetToken
  145.     Else
  146.         EvalExp6 = Atom()
  147.     End If
  148. End Function

  149. '处理数字或字符串
  150. Function Atom() As String
  151.     Select Case tokType
  152.         Case tokNumber:
  153.             Atom = token
  154.             GetToken
  155.         Case tokString:
  156.             Atom = token
  157.             GetToken
  158.     End Select
  159. End Function

  160. Sub main()
  161.     Evaluate "(3+5)*((2.5+7.5)-8/2)"
  162. End Sub
  163.   [/FONT]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 181个

财富等级: 日进斗金

 楼主| 发表于 2003-11-20 21:41:06 | 显示全部楼层
附上它的代码分析程序,是C#格式,可以参考。
没接触过C#的编程,可能转化的过程当中有些不是处理的很好,另外错误分析的部分也没处理。
附件是用WinRAR3.20版本压缩的,如果打不开,请下载新的版本。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2003-11-22 16:01:06 | 显示全部楼层
如果不想用MSC的话,可以用这个CalExp类.
我在明经曾经贴过的.这是最新版:
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 488个

财富等级: 日进斗金

发表于 2003-12-6 20:56:38 | 显示全部楼层
我想不是你自己写的吧
http://www.freevbcode.com
这上面的吧.
自己写也有自己的乐趣.^_^


顺便请教个问题:
比如一个文件里面有几个字:
比如是 ACAD , 文件里是:  41 42 41 43  (用二进制写进去)
dim a as string
dim b(3) as byte
open "1.txt" For Binary as 1#
get 1#,, a
这里a就为"ACAD"
如果get 1# ,, b
b(0 1 2 3)就分别为(65 67 65 68)
那照理 如a = b ,那a就为"ACAD",可并不这样,
我知道"ACAD"要八个字节,-->(65 0 67 0 65 0 68 0)
但那文件就4个字节它怎么a就可以是"ACAD"呢?而以byte读出,又不是了?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-11-23 00:08 , Processed in 0.386598 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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