逆ポーランド記法電卓 VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Module RpnCalc
Enum OPERATION As Integer
PLUS
MINUS
MULTIPLY
DIVIDE
INVERSION
CLEAR
ENTER
QUIT
End Enum
Class CalcStack
Private Const StackSize As Integer = 10
Private mValues As Double()
Private mCount As Integer
Public Sub New()
mValues = New Double(StackSize - 1) {}
mCount = 0
End Sub
Public Sub Push(value As Double)
If mCount >= StackSize Then
Throw New Exception("Stack がオーバーフローしました。")
End If
mValues(mCount) = value
mCount += 1
End Sub
Public Function Pop() As Double
If mCount <= 0 Then
Throw New Exception("Stack が空です。")
End If
mCount -= 1
Return mValues(mCount)
End Function
Public ReadOnly Property Count() As Integer
Get
Return mCount
End Get
End Property
Public Function ElementAt(idx As Integer) As Double
If idx < 0 OrElse idx >= mCount Then
Throw New Exception("パラメータ正しくありません。")
End If
Return mValues(mCount - idx - 1)
End Function
End Class
Class RpnCalc
Private mStack As New CalcStack()
Private Function Input() As OPERATION
Dim numbers As String = ""
Dim ope As OPERATION = OPERATION.ENTER
While True
Dim kinfo As ConsoleKeyInfo = Console.ReadKey()
If ("0"c <= kinfo.KeyChar AndAlso kinfo.KeyChar <= "9"c) OrElse kinfo.KeyChar = "."c Then
numbers += kinfo.KeyChar
Else
If kinfo.KeyChar = "+"c Then
ope = OPERATION.PLUS
ElseIf kinfo.KeyChar = "-"c Then
ope = OPERATION.MINUS
ElseIf kinfo.KeyChar = "*"c Then
ope = OPERATION.MULTIPLY
ElseIf kinfo.KeyChar = "/"c Then
ope = OPERATION.DIVIDE
ElseIf kinfo.KeyChar = "!"c Then
ope = OPERATION.INVERSION
ElseIf kinfo.Key = ConsoleKey.C Then
ope = OPERATION.CLEAR
ElseIf kinfo.Key = ConsoleKey.Q Then
ope = OPERATION.QUIT
End If
Exit While
End If
End While
If Not String.IsNullOrWhiteSpace(numbers) Then
mStack.Push(Double.Parse(numbers))
End If
Return ope
End Function
Private Sub ShowCalculator()
Const body As String = vbLf &
"*** RPN Calculator *******************************" & vbLf &
"* +:加 -:減 *:乗 /:除 !:符号 c:削除 q:終了 *" & vbLf &
"* *"
Console.WriteLine(body)
For i As Integer = mStack.Count To 1 Step -1
Console.WriteLine("* {0:00}: {1}", i, mStack.ElementAt(i - 1))
Next
Console.Write(">")
End Sub
Public Sub Run()
While True
Dim ope As OPERATION
Try
ShowCalculator()
ope = Input()
If ope = OPERATION.INVERSION OrElse ope = OPERATION.CLEAR Then
Dim n As Double = mStack.Pop()
If ope = OPERATION.INVERSION Then
mStack.Push(n * (-1.0))
End If
ElseIf ope = OPERATION.PLUS OrElse ope = OPERATION.MINUS OrElse ope = OPERATION.MULTIPLY OrElse ope = OPERATION.DIVIDE Then
Dim n1 As Double = mStack.Pop()
Dim n2 As Double = mStack.Pop()
If ope = OPERATION.PLUS Then
mStack.Push(n1 + n2)
ElseIf ope = OPERATION.MINUS Then
mStack.Push(n2 - n1)
ElseIf ope = OPERATION.MULTIPLY Then
mStack.Push(n1 * n2)
ElseIf ope = OPERATION.DIVIDE Then
If n1 = 0.0 Then
Console.WriteLine(vbLf & "Divide by Zero!")
Else
mStack.Push(n2 / n1)
End If
End If
ElseIf ope = OPERATION.QUIT Then
Exit While
End If
Catch ex As Exception
Console.WriteLine(vbLf & ex.Message)
End Try
End While
End Sub
End Class
Sub Main()
Dim calc As New RpnCalc()
calc.Run()
End Sub
End Module