VB利用堆栈实现表达式计算

9 篇文章 1 订阅
4 篇文章 0 订阅
VB利用堆栈实现表达式计算
    前几天对上学期老师的课件进行了深入学习后,我觉得有必要写个程序实践下,验证表达式计算设计十分正确。于是诞生了如下的程序。
    需要说明一点,这里的代码都是自主设计的,未参考网上的任何代码,所以,此代码拥有完全自主知识产权。
    版权所有,转载请注明出处:SunSoft
Form1.frm文件内容:
VERSION 5.00
Begin VB.Form Form1 
   Caption         =   "表达式计算"
   ClientHeight    =   3195
   ClientLeft      =   60
   ClientTop       =   345
   ClientWidth     =   4680
   LinkTopic       =   "Form1"
   ScaleHeight     =   3195
   ScaleWidth      =   4680
   StartUpPosition =   3  '窗口缺省
   Begin VB.TextBox Text2 
      Height          =   2415
      Left            =   2760
      MultiLine       =   -1  'True
      ScrollBars      =   2  'Vertical
      TabIndex        =   4
      Top             =   720
      Width           =   975
   End
   Begin VB.TextBox Text1 
      Height          =   2415
      Left            =   720
      MultiLine       =   -1  'True
      ScrollBars      =   2  'Vertical
      TabIndex        =   3
      Top             =   720
      Width           =   1215
   End
   Begin VB.CommandButton Command2 
      Caption         =   "Command2"
      Height          =   615
      Left            =   3840
      TabIndex        =   2
      Top             =   480
      Width           =   735
   End
   Begin VB.TextBox SourceText 
      Height          =   270
      Left            =   120
      TabIndex        =   1
      Top             =   120
      Width           =   3615
   End
   Begin VB.CommandButton Command1 
      Caption         =   "Calc"
      Height          =   300
      Left            =   3840
      TabIndex        =   0
      Top             =   120
      Width           =   735
   End
   Begin VB.Label Label2 
      Caption         =   "数字栈"
      Height          =   255
      Left            =   2040
      TabIndex        =   6
      Top             =   720
      Width           =   615
   End
   Begin VB.Label Label1 
      Caption         =   "操作符"
      Height          =   255
      Left            =   0
      TabIndex        =   5
      Top             =   720
      Width           =   615
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)  '声明
Dim opNum As New StackClass
Dim opChar As New StackClass

Private Sub Command1_Click()
    Dim sTxt As String
    Dim strNumFix As String
    Dim curChar As String
    Dim i As Long
    Dim ops1 As String, ops2 As String, opC As String
    '初始化堆栈
        opNum.Clear
        opChar.Clear
        Call UpdateShow
    '堆栈初始化结束
    sTxt = SourceText.Text
    For i = 1 To Len(sTxt)
        curChar = Mid(sTxt, i, 1)
        If IsSymbol(curChar) = True Then
            '看看数字预备区有没有
            If strNumFix <> "" Then
                opNum.Push strNumFix
                Call UpdateShow
                strNumFix = ""
            End If
redo:
            If IsHigh(curChar, opChar.Peek) = 1 Then 'if new come char is higher then push it to stack
                opChar.Push curChar '如果等级高的控制符,则进入
                Call UpdateShow
            ElseIf IsHigh(curChar, opChar.Peek) = 0 Then
                'Debug.Print "结果是:" & opNum.Pop
                'Exit Sub
                If curChar = "#" And opChar.Peek = "#" Then
                    opChar.Pop
                    Call UpdateShow
                    Debug.Print "输出结果是:" & opNum.Pop
                    Exit Sub
                End If
            ElseIf IsHigh(curChar, opChar.Peek) = -1 Then 'if low then ready to calculate
                ops2 = opNum.Pop
                Call UpdateShow
                ops1 = opNum.Pop
                Call UpdateShow
                opC = opChar.Pop
                Call UpdateShow
                opNum.Push CStr(Calc(ops1, ops2, opC))
                Call UpdateShow
                If curChar = ")" And opChar.Peek = "(" Then
                    opChar.Pop  '如果操作数是),就把(弹出来
                    Call UpdateShow
                    GoTo moveon
                End If
                GoTo redo
moveon:
            End If
        Else '非符号
            strNumFix = strNumFix & curChar
        End If
    Next i
    
End Sub

Private Sub Command2_Click()
MsgBox IsHigh("+", "+")
End Sub

Private Sub Form_Load()
Me.Show
opNum.Clear
opChar.Clear
End Sub
Function IsSymbol(ByVal strS As String) As Boolean
    IsSymbol = True
    Select Case strS
        Case "+"
        Case "-"
        Case "*"
        Case "/"
        Case "("
        Case ")"
        Case "#"
        Case Else
            IsSymbol = False
    End Select
End Function
Function IsHigh(ByVal sNew As String, ByVal sOld As String) As Integer
'1大于,-1小于,0等于
Select Case sNew
Case "+"
    Select Case sOld
        Case "("
            IsHigh = 1
            Exit Function
        Case "#"
            IsHigh = 1
            Exit Function
        Case Else
            IsHigh = -1
            Exit Function
    End Select
Case "-"
    Select Case sOld
        Case "("
            IsHigh = 1
            Exit Function
        Case "#"
            IsHigh = 1
            Exit Function
        Case Else
            IsHigh = -1
            Exit Function
    End Select
Case "*"
    Select Case sOld
        Case "("
            IsHigh = 1
            Exit Function
        Case "#"
            IsHigh = 1
            Exit Function
        Case "+"
            IsHigh = 1
            Exit Function
        Case "-"
            IsHigh = 1
            Exit Function
        Case Else
            IsHigh = -1
            Exit Function
    End Select
Case "/"
    Select Case sOld
        Case "("
            IsHigh = 1
            Exit Function
        Case "#"
            IsHigh = 1
            Exit Function
        Case "+"
            IsHigh = 1
            Exit Function
        Case "-"
            IsHigh = 1
            Exit Function
        Case Else
            IsHigh = -1
            Exit Function
    End Select
Case "("
    Select Case sOld
        Case "+"
            IsHigh = 1
            Exit Function
        Case "-"
            IsHigh = 1
            Exit Function
        Case "*"
            IsHigh = 1
            Exit Function
        Case "/"
            IsHigh = 1
            Exit Function
        Case "("
            IsHigh = 1
            Exit Function
        Case Else
            IsHigh = -1
            Exit Function
    End Select
Case ")"
    IsHigh = -1
    Exit Function
Case ""
    IsHigh = -1
    Exit Function
Case "#"
    Select Case sOld
        Case "#"
            IsHigh = 0
            Exit Function
        Case ""
            IsHigh = 1
            Exit Function
        Case "+"
            IsHigh = -1
            Exit Function
        Case "-"
            IsHigh = -1
            Exit Function
        Case "*"
            IsHigh = -1
            Exit Function
        Case "/"
            IsHigh = -1
            Exit Function
        Case ")"
            IsHigh = -1
            Exit Function
    End Select
End Select
End Function
Function Calc(ByVal op1 As String, ByVal op2 As String, ByVal options As String) As Double
On Error Resume Next
Calc = 0
Select Case options
    Case "+"
        Calc = CDbl(op1) + CDbl(op2)
    Case "-"
        Calc = CDbl(op1) - CDbl(op2)
    Case "*"
        Calc = CDbl(op1) * CDbl(op2)
    Case "/"
        Calc = CDbl(op1) / CDbl(op2)
End Select
End Function
Sub Delay(ByVal msec As Long) '函数:msec为毫秒数
DoEvents
Sleep msec
End Sub
Sub UpdateShow()
    DoEvents
    Text1.Text = opChar.ViewStack
    DoEvents
    Text2.Text = opNum.ViewStack
    DoEvents
    Call Delay(500)
End Sub
-----------------------------StackClass.cls文件内容----------------------------
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "StackClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private Stack() As String
Private itemCount As Long
Private Sub Class_Initialize()
    ReDim Stack(0)
    Stack(0) = "#"
End Sub
Public Sub Push(ByVal inString As String)
    ReDim Preserve Stack(itemCount + 1)
    Stack(itemCount + 1) = inString
    itemCount = itemCount + 1
End Sub

Public Function Pop() As String
    If itemCount >= 1 Then
        Pop = Stack(itemCount)
        ReDim Preserve Stack(itemCount - 1)
        itemCount = itemCount - 1
    Else
        Pop = ""
    End If
End Function
Public Function Peek() As String
    If itemCount = 0 Then
        Peek = ""
        Exit Function
    End If
    Peek = Stack(itemCount)
End Function

Sub Clear()
    itemCount = 0
    ReDim Stack(itemCount)
    Stack(itemCount) = "#"
End Sub

Public Function Count()
    Count = itemCount
End Function
Public Function ViewStack() As String
    Dim kOut As String
    Dim i As Long
    If itemCount = 0 Then ViewStack = "": Exit Function
    For i = 1 To itemCount
        kOut = kOut & Format(i, "00") & " " & Stack(i) & vbCrLf
    Next i
    ViewStack = kOut
End Function
 
表达式计算说明 很久就想编一个这样的计算器,只可惜一直没什么思路,最近突然灵感来了,所以就写下 这个程序。现在还在测试阶段,所以功能不是很完善。 程序功能:基本的表达式运算,可以自定义函数跟常量,分别保存在 “常数.txt” 和 “函数.txt”,方便自己添加。双击相应的函数名或常数名就可以将函数或常量添加到表达式中。 计算过程只能当表达式只有一行时有效。 实例1:计算sqr(19+tan(98)*tan(91)-sin(122)*(5*5-(19-11)))/2 计算过程sqr(19+tan(98)*tan(91)-sin(122)*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*tan(91)-sin(122)*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*-57.2899616307588-sin(122)*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*-57.2899616307588-.848048096156426*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*-57.2899616307588-.848048096156426*(5*5-8))/2 =sqr(19+-7.11536972238419*-57.2899616307588-.848048096156426*17)/2 =20.3032618253667/2 =10.1516309126834 实例2:计算 a=34 b=55 c=a+1 圆的面积(c) a*b c=a+b 圆的面积(c) 以下是计算结果: 圆的面积(c)=3848.4510006475 a*b=1870 圆的面积(c)=24884.5554090847 内置函数: !(x) - x 的阶乘 lg(x),log(x) 以10为底的对数 ln(x) 以 e为底x的对数 pow(x,y) x的y方次幂 prime(x) 判定x是否是素数,如果是直接将s2返回,否则将其各因子用连乘返回 sqr(x),sqrt(x) - x 的二次方根 arcsin(x) - x 的反正弦 arccos(x) - x 的反余弦 arcsec(x) - x 的反正割 arccsc(x) - x 的反余割 atn(x),arctg(x) - x 的反正切 arcctg(x) - x 的反余切 sin(x) - x 的正弦 cos(x) - x 的余弦 sec(x) - x 的正割 csc(x) - x 的余割 tg(x),tan(x) - x 的正切 ctg(x) - x 的余切 harcsin(x) - x 的反双曲正弦 harccos(x) - x 的反双曲余弦 harcsec(x) - x 的反双曲正割 harccsc(x) - x 的反双曲余割 harctg(x),harctan(x) - x 的反双曲正切 harcctg(x) - x 的反双曲余切 hsin(x) - x 的双曲正弦 hcos(x) - x 的双曲余弦 hsec(x) - x 的双曲正割 hcsc(x) - x 的双曲余割 htg(x),htan(x) - x 的双曲正切 hctg(x) - x 的双曲余切 有什么意见或建议可以跟我联系Email: ldm.menglv@gmail.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值