[References: Yan Weimin. Data Structure (c)]
Expression evaluation is a basic problem in programming language compilation. Its implementation is a typical example of stack applications.
After one day, we have a good algorithm to share with you.
Table 3.1 defines the priority relationship between operators:
Using System;
Using System. Collections;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;
Using System. Text. RegularExpressions;
Namespace EvaluateExpression
{
Class EvaluateExpression
{
Private static string Precede (string t1, string t2) // the priority of the two symbols is determined based on table 3.1.
{
String f = string. Empty;
Switch (t2)
{
Case "+ ":
Case "-":
If (t1 = "(" | t1 = "#")
F = "<";
Else
F = "> ";
Break;
Case "*":
Case "/":
If (t1 = "*" | t1 = "/" | t1 = ")")
F = "> ";
Else
F = "<";
Break;
Case "(":
If (t1 = ")")
Throw new ArgumentOutOfRangeException ("expression error ");
Else
F = "<";
Break;
Case ")":
Switch (t1)
{
Case "(": f = "="; break;
Case "#": throw new ArgumentOutOfRangeException ("expression error ");
Default: f = ">"; break;
}
Break;
Case "#":
Switch (t1)
{
Case "#": f = "="; break;
Case "(": throw new ArgumentOutOfRangeException ("expression error ");
Default: f = ">"; break;
}
Break;
}
Return f;
}
Private static bool In (string c) // determines whether c is an operator
{
Switch (c)
{
Case "+ ":
Case "-":
Case "*":
Case "/":
Case "(":
Case ")":
Case "#": return true;
Default: return false;
}
}
Private static int Operate (int a, string operator, int B)
{
Int c = 0;
Switch)
{
Case "+": c = a + B; break;
Case "-": c = a-B; break;
Case "*": c = a * B; break;
Case "/": c = a/B; break;
}
Return c;
}
Public static int Calculate (string exp) // operator priority algorithm used to evaluate arithmetic expressions. Set OPTR and OPND as the operator stack and arithmetic stack respectively.
{
Expr S = new expr (exp); // pack the passed expression into a class object for easy calculation
String C = string. Empty;
Int oper1, oper2;
String theta = string. Empty;
Stack OPTR = new Stack ();
OPTR. Push ("#");
Stack OPND = new Stack ();
C = S. GetS (); // obtain the component in the expression
While (C! = "#" | OPTR. Peek (). ToString ()! = "#")
{
If (! In (C) // stack an operator instead of an operator
{
OPND. Push (C );
C = S. GetS ();
}
Else
Switch (Precede (OPTR. Peek (). ToString (), C ))
{
Case "<": // The top element of the stack has a low priority.
OPTR. Push (C );
C = S. GetS ();
Break;
Case "=": // parentheses and receive the next character
OPTR. Pop ();
C = S. GetS ();
Break;
Case ">": // return the stack and import the calculation result to the stack.
Theta = OPTR. Pop (). ToString ();
Oper2 = Convert. ToInt32 (OPND. Pop ());
Oper1 = Convert. ToInt32 (OPND. Pop ());
OPND. Push (Operate (oper1, theta, oper2). ToString ());
Break;
} // Switch
} // While
Return Convert. ToInt32 (OPND. Peek ());
}
Private class expr // expression class, used to take each component in the expression
{
// Member
Private string exp;
Private int length; // The GetS () method service.
// Constructor
Public expr (string exp)
{
This. exp = exp;
Length = exp. Length;
If (! IsRight () {Console. WriteLine ("the expression is incorrect"); return ;}
}
// Method
Public string GetS () // obtain the string in the expression
{
String ch, token, f;
Ch = token = f = string. Empty;
If (length = 0)
Throw new ArgumentOutOfRangeException ("expression obtained ");
While (length! = 0)
{
Ch = exp. Substring (exp. Length-length, 1 );
If (IsNumeric (ch) // indicates that the first time a number is obtained
{
Token + = ch;
Length --;
}
Else // not a number
{
If (IsNumeric (token ))
{
F = token;
Break;
}
Else // It indicates that the first query is not a number.
{
If (ch = "")
{
Length --;
Continue;
}
Length --; // if the value is not a number
F = ch;
Break;
}
}
}
Return f;
} // GetS
Private bool IsRight () // determine whether the expression is legal: (1) whether there is a space in the middle of the two numbers
{
Bool f = true;
String ch = string. Empty;
Int I = 0;
Int j = 0;
For (int p = 0; p <exp. Length; p ++)
{
Ch = exp. Substring (p, 1 );
If (IsNumeric (ch ))
{
If (j = 1) return false;
I = 1;
Continue;
}
If (ch = "")
{
If (I = 1) j = 1; continue;
}
I = j = 0;
}
Return f;
}
Private bool IsNumeric (string input) // determines whether the number of strings is
{
Bool flag = true;
String pattern = (@ "^ \ d + $ ");
Regex validate = new Regex (pattern );
If (! Validate. IsMatch (input ))
{
Flag = false;
}
Return flag;
}
} // Class: expr
}
}
A test code is provided:
Using System;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;
Namespace EvaluateExpression
{
Class Program
{
Static void Main (string [] args)
{
Console. WriteLine ("arithmetic expression, ended! ");
String expression = "3022*(17-12)/2 #";
Console. WriteLine (Convert. ToString (EvaluateExpression. Calculate (expression )));
Console. ReadLine ();
}
}
}