str=" " & x & " +(" & y & " - " & z & " )* & " num &""

解决方案 »

  1.   

    这是上回Kivic(Kivic) 大哥教我的没有变量的程序,我现在还是不会改成有变量的。
    模块代码:
    '计算用户输入的表达式
    '如 "3+2*2" 结果为 "7"Public Function 计算(GS As String) As String
        Dim i, n As Integer
        Dim TempGs, Temp As String
        Dim Vl() As String '操作数
        Dim Vls As Integer '操作数的数目
        Dim Si As Integer '上一操作符的位置
        Dim Ads, Sus, Mus, Bys, Lks, Rks As Integer     '操作符的数目
        Dim Adp(), Mup(), Byp(), Lkp(), Rkp() As Integer '操作符的位置
        Dim Adn(), Mun(), Byn() As Integer '操作符的排列次序
        Dim Sig() As Integer '每一个操作符的位置
        
    On Error GoTo Err
    Do While True
        ReDim Adp(Len(GS)), Mup(Len(GS)), Byp(Len(GS)) _
            , Lkp(Len(GS)), Rkp(Len(GS)) As Integer
        ReDim Adn(Len(GS)), Mun(Len(GS)), Byn(Len(GS)) _
            , Lkn(Len(GS)), Rkn(Len(GS)), Sig(Len(GS)) As Integer
        
        ReDim Vl(Len(GS))
        
        If Len(GS) = 0 Then GoTo Err
        If Mid(GS, Len(GS), 1) <> "#" Then
        
            TempGs = GS
            For i = 1 To Len(GS) '将减化加
                
                If Mid(GS, i, 1) = "-" And i <> 1 Then
                    If Mid(GS, i - 1, 1) <> "+" And Mid(GS, i - 1, 1) <> "-" _
                        And Mid(GS, i - 1, 1) <> "*" And Mid(GS, i - 1, 1) <> "/" Then
                        TempGs = Mid(TempGs, 1, i - 1 + n) + "+" + Mid(GS, i)
                        n = n + 1
                    End If
                    
                End If
            Next i
            GS = TempGs
            
            n = 0
            For i = 1 To Len(GS) '处理负负得正
                If Mid(GS, i, 1) = "-" Then
                    If Mid(GS, i + 1, 1) = "-" Then
                        TempGs = Mid(TempGs, 1, i - 1 - n) + Mid(GS, i + 2)
                        n = n + 2
                    End If
                End If
            Next i
            GS = TempGs
            GS = GS + "#"
        End If
        
        Vls = 1
        Ads = 0: Sus = 0: Mus = 0: Bys = 0: Lks = 0: Rks = 0
        
        For i = 1 To Len(GS)
            
            Select Case Mid(GS, i, 1)
                Case "+"
                    Ads = Ads + 1
                    Adp(Ads) = i
                    Adn(Ads) = Vls
                Case "*"
                    Mus = Mus + 1
                    Mup(Mus) = i
                    Mun(Mus) = Vls
                Case "/"
                    Bys = Bys + 1
                    Byp(Bys) = i
                    Byn(Bys) = Vls
                Case "("
                    Lks = Lks + 1
                    Lkp(Lks) = i
                   
                Case ")"
                    Rks = Rks + 1
                    Rkp(Rks) = i
                    
            End Select
            
            If Mid(GS, i, 1) = "+" Or Mid(GS, i, 1) = "*" Or _
                Mid(GS, i, 1) = "/" Or Mid(GS, i, 1) = "#" Then
                
                If Si + 1 = i And Mid(GS, i + 1, 1) <> "#" _
                     Then '操作符非法连续或以操作符开头
                    GoTo Err
                Else
                    Si = i
                End If
                
                If Not IsNumeric(Vl(Vls)) And Mid(GS, i + 1, 1) <> "#" _
                     Then '操作数不是数字
                    GoTo Err
                End If
                Sig(Vls) = i
                Vls = Vls + 1
                
            Else
                If Mid(GS, i, 1) <> "(" And Mid(GS, i, 1) <> ")" Then
                    Vl(Vls) = Vl(Vls) + Mid(GS, i, 1) '制作操作数
                Else
                  If i <> 1 Then
                    If ((Mid(GS, i - 1, 1) = "(" And Mid(GS, i, 1) = ")") Or _
                       (Mid(GS, i - 1, 1) = ")" And Mid(GS, i, 1) = "(")) _
                          Then '判定括号前后符号的合法性
                        GoTo Err
                    End If
                  End If
                End If
            End If
            
        Next i
        
        If Lks <> Rks Then
            GoTo Err '左右括号数是否匹配
        End If
        
        For i = 1 To Lks
            If Lkp(i) > Rkp(i) Then GoTo Err '左右括号出现顺序错误
        Next i
        
        If Lks <> 0 Then '括号处理
          Do While True
            For i = Lks To 1 Step -1
                For n = Rks To 1 Step -1
                    Temp = 计算(Mid(GS, Lkp(i) + 1, Rkp(n) - Lkp(i) - 1))
                    If Temp <> "公式有错误" Then
                        GS = Mid(GS, 1, Lkp(i) - 1) + Temp + Mid(GS, Rkp(n) + 1)
                        Exit Do
                    End If
                Next n
            Next i
            If Temp = "公式有错误" Then GoTo Err
                '括号中有错误退出
          Loop
        Else
            If Mus <> 0 Then '乘法处理
                GS = Mid(GS, 1, Sig(Mun(1) - 1)) + Trim(Str(Val(Vl(Mun(1))) _
                    * Val(Vl(Mun(1) + 1)))) + Mid(GS, Val(Mup(1)) + Len(Vl(Mun(1) _
                    + 1)) + 1)
            Else
                If Bys <> 0 Then '除法处理
                    GS = Mid(GS, 1, Sig(Byn(1) - 1)) + Trim(Str(Val(Vl(Byn(1))) _
                        / Val(Vl(Byn(1) + 1)))) + Mid(GS, Val(Byp(1)) + Len(Vl(Byn(1) _
                        + 1)) + 1)
                Else
                    If Ads <> 0 Then '加法处理
                        GS = Trim(Str(Val(Vl(1)) + Val(Vl(2)))) + Mid(GS, Val(Adp(1)) _
                            + Len(Vl(2)) + 1)
                    Else
                        计算 = Mid(GS, 1, Len(GS) - 1)
                        Exit Function
                    End If
                End If
            End If
        End If
    Loop
        
        
    Err:
        计算 = "公式有错误"
        
    End Function
      

  2.   

    hehe...编译问题。
    首先把x,y,z,+,-,*,(,),num提取出来,建立表达式树,然后计算。
      

  3.   

    这是一个通用的函数,输入一个字符串就可以返回该字符串表达式的结果。
    如果xy都用变量表示,你还写一个函数干吗?
    需要怎么计算,直接写就可以啦,就象 Leftie(Leftie) 写的那样!
      

  4.   

    但问题在于我并不知道表达式是什么?不能确定是x还Y,是y还Y,是num还是OK,也不知长度等等。
      

  5.   

    传统的表达式计算是使用堆栈来计算,我有一个算法采用的是递归的方法。复杂的表达式-->分解成只有一个括号的混合四则运算表达式-->分解成只有一个运算符的表达式-->计算最简单的表达式-->将结果加入分解的表达式中再从复杂的表达式开始分解,直到最后的表达式中没有运算符
      

  6.   

    hehe...看看这个吧,把编译作业重做了一遍^_^Option Explicit
    '(C)LengDakun
    '表达式计算
    '1、变量识别
    '2、表达式构建
    '3、计算
    '
    '建立变量标识对照,建立逆波兰表达式。
    '  表达式由数字,变量,运算符组成
    '定义:运算符:+,-,*,/,(,)
    '      运算优先级别:(, ), */, +-
    Type ExpType
        a As Integer 'Attribute of a word
        v As Double  'Value of a word
    End TypeConst EXP_NONE = 0 'None
    Const EXP_VAL = 1  'Value
    'Const EXP_VAR = 2  'Variable
    Const EXP_OPR = 3  'OperatorPrivate Contrast(1 To 128) As String, ConMax As Integer
    Private Value(1 To 128) As Double
    Private vs As String, vo As StringSub Main()
        Dim OrgExp As String
        Dim E(255) As ExpType, Emax As Integer
        Dim i As Integer
        
        vs = "1234567890."
        vo = "()*/+-#"
        
        ConMax = 3
        Contrast(1) = "x"
        Contrast(2) = "y"
        Contrast(3) = "z"
        OrgExp = "x*y+z*2*(y-z)/3"
        For i = 1 To ConMax
            Value(i) = InputBox(OrgExp & vbCrLf & "请输入变量" & Contrast(i) & "所代表的值", , 0)
        Next i
        PreScan OrgExp, E(), Emax
        
        'MsgBox "总共发现" & Emax & "个关键字"
        OrgExp = OrgExp & vbCrLf & vbCrLf
        For i = 1 To ConMax
            OrgExp = OrgExp & Contrast(i) & "=" & Value(i) & vbCrLf
        Next i
        OrgExp = OrgExp & vbCrLf
        
        For i = 0 To Emax - 1
            If E(i).a = EXP_OPR Then
                OrgExp = OrgExp & Mid(vo, E(i).v - 1, 1) & " "
            Else
                OrgExp = OrgExp & E(i).v & " "
            End If
        Next i
        
        MsgBox OrgExp & " = " & vbCrLf & Calculate(E(), Emax)
    End SubSub PreScan(ByVal str As String, ByRef E() As ExpType, ByRef Emax As Integer)
        Dim i As Integer, j As Integer, l As Integer
        Emax = 0
        str = str & "#"
        l = Len(str)
        i = 1
        Do
            For j = 1 To ConMax
                If Mid(str, i, Len(Contrast(j))) = Contrast(j) Then '变量
                    E(Emax).a = EXP_VAL
                    E(Emax).v = Value(j)
                    Emax = Emax + 1
                    i = i + Len(Contrast(j))
                    Exit For
                End If
            Next j
            If InStr(1, vs, Mid(str, i, 1)) > 0 Then                '操作数
                For j = i + 1 To Len(str)
                    If InStr(j, vs, Mid(str, j, 1)) <= 0 Then
                        Exit For
                    End If
                Next j
                E(Emax).a = EXP_VAL
                E(Emax).v = Val(Mid(str, i, j - i + 1))
                Emax = Emax + 1
                i = j
            ElseIf InStr(1, vo, Mid(str, i, 1)) > 0 Then            '运算符
                E(Emax).a = EXP_OPR
                E(Emax).v = InStr(1, vo, Mid(str, i, 1)) + 1    'v\2=运算级别
                i = i + 1
                Emax = Emax + 1
            Else
                MsgBox "表达式错误!" & vbCrLf & str & vbCrLf & "POS:" & i
                Exit Do
            End If
        Loop While i <= l
    End SubFunction Calculate(E() As ExpType, Emax As Integer) As Double
        'x + ( y - z ) * num
        Dim i As Integer
        Dim a As Double, b As Double, c As Double, d As Integer
        
        Dim pri(2 To 16, 2 To 16) As Integer
        
        Dim v(0 To 255) As Double, vp As Integer     '操作数堆栈
        Dim o(0 To 255) As Integer, op As Integer    '运算符堆栈
        '
        '     ( ) * / + - #
        '     2 3 4 5 6 7 8
        ' ( 2 < < < < < < !
        ' ) 3 ! > > > > > >
        ' * 4 < > > > > > >
        ' / 5 < > > > > > >
        ' + 6 < > < < > > >
        ' - 7 < > < < > > >
        ' # 8 < < < < < < <
        '
        pri(2, 2) = 0: pri(2, 3) = 0: pri(2, 4) = 0: pri(2, 5) = 0: pri(2, 6) = 0: pri(2, 7) = 0: pri(2, 8) = -1
        pri(3, 2) = -1: pri(3, 3) = 1: pri(3, 4) = 1: pri(3, 5) = 1: pri(3, 6) = 1: pri(3, 7) = 1: pri(3, 8) = 1
        pri(4, 2) = 0: pri(4, 3) = 1: pri(4, 4) = 1: pri(4, 5) = 1: pri(4, 6) = 1: pri(4, 7) = 1: pri(4, 8) = 1
        pri(5, 2) = 0: pri(5, 3) = 1: pri(5, 4) = 1: pri(5, 5) = 1: pri(5, 6) = 1: pri(5, 7) = 1: pri(5, 8) = 1
        pri(6, 2) = 0: pri(6, 3) = 1: pri(6, 4) = 0: pri(6, 5) = 0: pri(6, 6) = 1: pri(6, 7) = 1: pri(6, 8) = 1
        pri(7, 2) = 0: pri(7, 3) = 1: pri(7, 4) = 0: pri(7, 5) = 0: pri(7, 6) = 1: pri(7, 7) = 1: pri(7, 8) = 1
        pri(8, 2) = 0: pri(8, 3) = 0: pri(8, 4) = 0: pri(8, 5) = 0: pri(8, 6) = 0: pri(8, 7) = 0: pri(8, 8) = 1
        
        op = 1
        o(0) = InStr(1, vo, "#") + 1
        vp = 0
        
        i = 0
        Do
            If E(i).a = EXP_VAL Then
                v(vp) = E(i).v
                vp = vp + 1
                i = i + 1
            Else
                Select Case pri(o(op - 1), E(i).v)
                Case 0
                    o(op) = E(i).v
                    op = op + 1
                    i = i + 1
                Case 1
                    If o(op - 1) = 8 And E(i).v = 8 Then
                        Exit Do
                    ElseIf o(op - 1) = 3 And o(op - 2) = 2 Then
                        op = op - 2
                    Else
                            
                        a = v(vp - 2)
                        b = v(vp - 1)
                        Select Case o(op - 1)
                        Case 4 ' *
                            a = a * b
                        Case 5 ' /
                            a = a / b
                        Case 6 ' +
                            a = a + b
                        Case 7 ' -
                            a = a - b
                        End Select
                        vp = vp - 1
                        op = op - 1
                        v(vp - 1) = a
                    End If
                Case Else
                    MsgBox "ERROR"
                    Stop
                End Select
            End If
        Loop While True
        Calculate = v(0)
    End Function
      

  7.   

    对了,那个程序没有使用逆波兰表达式,是采取代括号的中序表达式计算方法。表达式构建与变量识别同时进行,事先代换变量为数值。你可以定义Contrast()数组中的变量标识,在Value()数组中定义变量所对应的数值。
    将表达式写入OrgExp字符串,然后调用PreScan()翻译表达式,利用Calculate()计算数值。Calculate()中的pri()数组为运算符优先级表格。需要增加算符的时候请更改vo变量内容和pri()数组,注意不要改变原先运算符的位置。尤其是结束符#的位置。