求算法——关于字符串映射替换的问题
比如:原字符串“(A1+D3)*A11”
有如下映射关系 A1 -> Var1
D3 -> Var2
A11 -> Var3
转换后的字符串应为“(Var1+Var2)*Var3”
请问擅长于算法的朋友,应该实现上面的转换?谢谢!!
[解决办法]
属于基本的算术式解析,给你一段四则运算解析代码示例:
Option Base 1Dim tt(20) As String '存放按+,-号分解出来的式子,只设定了20个Private Sub Command1_Click() Text2.Text = handle(Text1.Text)End SubPrivate Function handle(a) '按括号分解式子 Dim th, th2 As String '存放按括号分解出来的式子 Do While True n1 = InStr(a, "(") '查找 n2 = InStr(a, ")") Select Case True Case n1 = 0 And n2 = 0 '没有括号 Exit Do Case n1 > 0 And n2 = 0 '有 "(" 没 ")" MsgBox "表达式错误" Exit Function Case n2 > 0 And n1 = 0 '有 ") 没 "(" MsgBox "表达式错误" Exit Function Case n1 > n2 '出现") (" MsgBox "表达式错误" Exit Function Case Else Do '如果出现这种情况"((( )))",则取最里面的括号开始分解 zl = n1 n1 = InStr(n1 + 1, a, "(") Loop Until n1 > n2 Or n1 = 0 th = Mid(a, zl, n2 - zl + 1) '存放分解出来的式子 th2 = Mid(th, 2, Len(th) - 2) '去括号 a = Replace(a, th, handle1(th2)) '计算分解出来的式子,并把结果替换进去 End Select Loop handle = handle1(a) '得到最后结果End FunctionPrivate Function handle1(b) '把handle3的每个结果相加 n = handle2(b) s = 0 '累加数初值 For i = 1 To n s = s + handle3(tt(i)) '计算各乘除式的值并累加 Next i handle1 = s '得到结果End Function Private Function handle2(t) '按+,-分解式子 '添以"+"开头,方便处理 If Left(t, 1) <> "+" And Left(t, 1) <> "-" Then t = "+" & t 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 '无+、-号 tt(k) = t '取剩余部分 t = "" Case n2 = 0 Or (n1 < n2 And n1 > 0) '无-号或先遇到+号 tt(k) = Left(t, n1 - 1) '从该+号开始截取 t = Mid(t, n1) Case n1 = 0 Or (n1 > n2 And n2 > 0) '无+号或先遇到-号 tt(k) = Left(t, n2 - 1) '从该-号开始截取 t = Mid(t, n2) End Select Loop handle2 = k '分解出来的式子个数End FunctionPrivate Function handle3(x) '计算handle2分解出来的式子 f = Left(x, 1) '取出符号+或- x = "*" & Mid(x, 2) '添以"*"开头,方便处理 Sum = 1 '累乘/除的初值 Do While x <> "" n1 = InStr(2, x, "*") '从第2个字符开始查找 n2 = InStr(2, x, "/") Select Case True Case n1 = 0 And n2 = 0 '无乘除号 y = x x = "" Case n2 = 0 Or (n1 < n2 And n1 > 0) '无/号或先遇到*号 y = Left(x, n1 - 1) '取至*号前 x = Mid(x, n1) Case n1 = 0 Or (n1 > n2 And n2 > 0) '无*号或先遇到/号 y = Left(x, n2 - 1) '取至/号前 x = Mid(x, n2) End Select If Left(y, 1) = "*" Then '根据式子前面的符号进行运算 Sum = Sum * Val(Mid(y, 2)) Else Sum = Sum / Val(Mid(y, 2)) End If Loop handle3 = Val(f & Str(Sum)) '加上正负号End Function
[解决办法]
楼主需要的仅仅是字符串替换。核心问题是子串的冲突问题。解决之道就是先替换长串。
只要将字符串提取出来,按长度排序,然后逐个用 Repalce 替换即可。
如果如楼主贴中所示,字母最大不超过 F,且不必区分大小写,则还有更有趣的算法。
窗体上放一个 Sorted = True, Visible = False 的 ListBox 用来排序。(也可用其他排序算法)
Dim strSource As String
Dim strResult As String
Dim strTemp As String
Dim strArray() As String
Dim strList(1, 2) As String
Dim i, j As Integer
strSource = "(A1+D3)*A11"
strList(0, 0) = "A1"
strList(1, 0) = "Var1"
strList(0, 1) = "D3"
strList(1, 1) = "Var2"
strList(0, 2) = "A11"
strList(1, 2) = "Var3"
strTemp = Replace(strSource, "(", "")
strTemp = Replace(strSource, "(", "")
strTemp = Replace(strTemp, ")", "")
strTemp = Replace(strTemp, ")", "")
strTemp = Replace(strTemp, "*", "+")
strTemp = Replace(strTemp, "-", "+")
strTemp = Replace(strTemp, "/", "+")
strArray = Split(strTemp, "+")
List1.Clear
For i = LBound(strArray) To UBound(strArray)
strTemp = "&H" & strArray(i)
If IsNumeric(strTemp) Then List1.AddItem Val(strTemp)
Next i
strResult = strSource
For i = List1.ListCount - 1 To 0 Step -1
strTemp = Hex(List1.List(i))
For j = 0 To UBound(strList, 2)
If strTemp = strList(0, j) Then
strResult = Replace(strResult, strTemp, strList(1, j))
Exit For
End If
Next j
Next i
Debug.Print strResult
注意,你的字符串中有全角字符,需要特别处理。