Parsing String of symbols to Expression
Given an expression as a string str consisting of numbers and basic arithmetic operators(+, -, *, /), the task is to solve the expression. Note that the numbers used in this program are single-digit numbers and parentheses are not allowed.
Examples:
Input: str = “3/3+4*6-9”
Output: 16
Since (3 / 3) = 1 and (4 * 6) = 24.
So the overall expression becomes (1 + 24 – 9) = 16
Input: str = “9*5-4*5+9”
Output: 16
Approach: A Stack class is created to store both numbers and operators (both as characters). The stack is a useful storage mechanism because, when parsing expressions, the last item stored needs to be accessed frequently; and a stack is a last-in-first-out (LIFO) container.
Besides the Stack class, a class called express(short for expression) is also created, representing an entire arithmetic expression. Member functions for this class allow the user to initialize an object with an expression in the form of a string, parse the expression, and return the resulting arithmetic value.
Here’s how an arithmetic expression is parsed.
A pointer is started at the left and is iterated to look at each character. It can be either a number(always a single-digit character between 0 and 9) or an operator (the characters +, -, *, and /).
If the character is a number, it is pushed onto the stack. The first operator encountered is also pushed into the stack. The trick is subsequent operators are handled. Note that the current operator can’t be executed because the number that follows it hasn’t been read yet. Finding an operator is merely the signal that we can execute the previous operator, which is stored on the stack. That is, if the sequence 2+3 is on the stack, we wait until we find another operator before carrying out the addition.
Thus, whenever the current character is an operator (except the first), the previous number (3 in the preceding example) and the previous operator (+) are popped off the stack, placing them in the variables lastval and lastop. Finally, the first number (2) is popped and the arithmetic operation is carried on the two numbers (obtaining 5).
However, when * and / which have higher precedence than + and – are encountered, the expression can’t be executed. In the expression 3+4/2, the + cant be executed until the division is performed. So, the 2 and the + are put back on the stack until the division is carried out.
On the other hand, if the current operator is a + or -, the previous operator can be executed. That is when the + is encountered in the expression 4-5+6, it’s all right to execute the -, and when the – is encountered in 6/2-3, it’s okay to do the division. Table 10.1 shows the four possibilities.
Previous Operator | Current Operator | Example | Action |
---|---|---|---|
+ or – | * or / | 3+4/ | Push previous operator and previous number (+, 4) |
* or / | * or / | 9/3* | Execute previous operator, push result (3) |
+ or – | + or – | 6+3+ | Execute previous operator, push result (9) |
* or / | + or – | 8/2- | Execute previous operator, push result (4) |
Below is the implementation of the above approach:
CPP
// C++ implementation of the approach #include <cstring> #include <iostream> using namespace std; // Length of expressions in characters const int LEN = 80; // Size of the stack const int MAX = 40; class Stack { private : // Stack: array of characters char st[MAX]; // Number at top of the stack int top; public : Stack() { top = 0; } // Function to put a character in stack void push( char var) { st[++top] = var; } // Function to return a character off stack char pop() { return st[top--]; } // Function to get the top of the stack int gettop() { return top; } }; // Expression class class Express { private : // Stack for analysis Stack s; // Pointer to input string char * pStr; // Length of the input string int len; public : Express( char * ptr) { pStr = ptr; len = strlen (pStr); } // Parse the input string void parse(); // Evaluate the stack int solve(); }; void Express::parse() { // Character from the input string char ch; // Last value char lastval; // Last operator char lastop; // For each input character for ( int j = 0; j < len; j++) { ch = pStr[j]; // If it's a digit then save // the numerical value if (ch >= '0' && ch <= '9' ) s.push(ch - '0' ); // If it's an operator else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ) { // If it is the first operator // then put it in the stack if (s.gettop() == 1) s.push(ch); // Not the first operator else { lastval = s.pop(); lastop = s.pop(); // If it is either '*' or '/' and the // last operator was either '+' or '-' if ((ch == '*' || ch == '/' ) && (lastop == '+' || lastop == '-' )) { // Restore the last two pops s.push(lastop); s.push(lastval); } // In all the other cases else { // Perform the last operation switch (lastop) { // Push the result in the stack case '+' : s.push(s.pop() + lastval); break ; case '-' : s.push(s.pop() - lastval); break ; case '*' : s.push(s.pop() * lastval); break ; case '/' : s.push(s.pop() / lastval); break ; default : cout << "\nUnknown oper" ; exit (1); } } s.push(ch); } } else { cout << "\nUnknown input character" ; exit (1); } } } int Express::solve() { // Remove the items from stack char lastval; while (s.gettop() > 1) { lastval = s.pop(); switch (s.pop()) { // Perform operation, push answer case '+' : s.push(s.pop() + lastval); break ; case '-' : s.push(s.pop() - lastval); break ; case '*' : s.push(s.pop() * lastval); break ; case '/' : s.push(s.pop() / lastval); break ; default : cout << "\nUnknown operator" ; exit (1); } } return int (s.pop()); } // Driver code int main() { char string[LEN] = "2+3*4/3-2" ; // Make expression Express* eptr = new Express(string); // Parse it eptr->parse(); // Solve the expression cout << eptr->solve(); return 0; } |
Java
import java.util.Stack; public class ExpressionEvaluation { public static int evaluate(String expression) { // Create a stack to hold operands Stack<Integer> operands = new Stack<Integer>(); // Create a stack to hold operators Stack<Character> operators = new Stack<Character>(); for ( int i = 0 ; i < expression.length(); i++) { char ch = expression.charAt(i); // If the current character is a whitespace, skip it if (ch == ' ' ) { continue ; } // If the current character is a digit, push it to the operand stack if (Character.isDigit(ch)) { int num = 0 ; while (i < expression.length() && Character.isDigit(expression.charAt(i))) { num = num * 10 + Character.getNumericValue(expression.charAt(i)); i++; } i--; operands.push(num); } // If the current character is an operator, push it to the operator stack else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ) { while (!operators.empty() && hasPrecedence(ch, operators.peek())) { operands.push(applyOperation(operators.pop(), operands.pop(), operands.pop())); } operators.push(ch); } } while (!operators.empty()) { operands.push(applyOperation(operators.pop(), operands.pop(), operands.pop())); } return operands.pop(); } public static boolean hasPrecedence( char op1, char op2) { if ((op1 == '*' || op1 == '/' ) && (op2 == '+' || op2 == '-' )) { return false ; } else { return true ; } } public static int applyOperation( char op, int b, int a) { switch (op) { case '+' : return a + b; case '-' : return a - b; case '*' : return a * b; case '/' : if (b == 0 ) { throw new UnsupportedOperationException( "Cannot divide by zero" ); } return a / b; } return 0 ; } public static void main(String[] args) { String expression = "2+3*4/3-2" ; System.out.println(evaluate(expression)); } } |
Python3
# Python implementation of the approach import sys # Size of the stack MAX = 40 class Stack: def __init__( self ): # Stack: array of characters self .st = [ 0 ] * MAX # Number at top of the stack self .top = 0 # Function to put a character in stack def push( self , var): self .top + = 1 self .st[ self .top] = var # Function to return a character off stack def pop( self ): topval = self .st[ self .top] self .top - = 1 return topval # Function to get the top of the stack def gettop( self ): return self .top # Expression class class Express: def __init__( self , ptr): # Stack for analysis self .s = Stack() # Pointer to input string self .pStr = ptr # Length of the input string self . len = len ( self .pStr) # Parse the input string def parse( self ): # Last value lastval = 0 # Last operator lastop = 0 # For each input character for j in range ( self . len ): ch = self .pStr[j] # If it's a digit then save the numerical value if ch > = '0' and ch < = '9' : self .s.push( int (ch) - int ( '0' )) # If it's an operator elif ch = = '+' or ch = = '-' or ch = = '*' or ch = = '/' : # If it is the first operator then put it in the stack if self .s.gettop() = = 1 : self .s.push(ch) # Not the first operator else : lastval = self .s.pop() lastop = self .s.pop() # If it is either '*' or '/' and the last operator was either '+' or '-' if (ch = = '*' or ch = = '/' ) and (lastop = = '+' or lastop = = '-' ): # Restore the last two pops self .s.push(lastop) self .s.push(lastval) # In all the other cases else : # Perform the last operation if lastop = = '+' : self .s.push( self .s.pop() + lastval) elif lastop = = '-' : self .s.push( self .s.pop() - lastval) elif lastop = = '*' : self .s.push( self .s.pop() * lastval) elif lastop = = '/' : self .s.push( self .s.pop() / lastval) else : print ( "\nUnknown operator" ) sys.exit( 1 ) self .s.push(ch) else : print ( "\nUnknown input character" ) sys.exit( 1 ) # Evaluate the stack def solve( self ): # Remove the items from stack lastval = 0 while self .s.gettop() > 1 : lastval = self .s.pop() lastop = self .s.pop() # Perform operation, push answer if lastop = = '+' : self .s.push( self .s.pop() + lastval) elif lastop = = '-' : self .s.push( self .s.pop() - lastval) elif lastop = = '*' : self .s.push( self .s.pop() * lastval) elif lastop = = '/' : self .s.push( self .s.pop() / lastval) else : print ( "\nUnknown operator" ) sys.exit( 1 ) return int ( self .s.pop()) # Driver code if __name__ = = "__main__" : # Make expression string = "2+3*4/3-2" eptr = Express(string) # Parse it eptr.parse() # Solve the expression print (eptr.solve()) # This code is contributed by sdeadityasharma |
C#
// C# implementation of the approach using System; using System.Collections.Generic; public class ExpressionEvaluation { public static int evaluate( string expression) { // Create a stack to hold operands Stack< int > operands = new Stack< int >(); // Create a stack to hold operators Stack< char > operators = new Stack< char >(); for ( int i = 0; i < expression.Length; i++) { char ch = expression[i]; // If the current character is a whitespace, // skip it if (ch == ' ' ) { continue ; } // If the current character is a digit, push it // to the operand stack if (Char.IsDigit(ch)) { int num = 0; while (i < expression.Length && Char.IsDigit(expression[i])) { num = num * 10 + ( int )Char.GetNumericValue( expression[i]); i++; } i--; operands.Push(num); } // If the current character is an operator, push // it to the operator stack else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ) { while (operators.Count > 0 && hasPrecedence(ch, operators.Peek())) { operands.Push(applyOperation( operators.Pop(), operands.Pop(), operands.Pop())); } operators.Push(ch); } } while (operators.Count > 0) { operands.Push(applyOperation(operators.Pop(), operands.Pop(), operands.Pop())); } return operands.Pop(); } public static bool hasPrecedence( char op1, char op2) { if ((op1 == '*' || op1 == '/' ) && (op2 == '+' || op2 == '-' )) { return false ; } else { return true ; } } public static int applyOperation( char op, int b, int a) { switch (op) { case '+' : return a + b; case '-' : return a - b; case '*' : return a * b; case '/' : if (b == 0) { throw new InvalidOperationException( "Cannot divide by zero" ); } return a / b; } return 0; } public static void Main( string [] args) { string expression = "2+3*4/3-2" ; Console.WriteLine(evaluate(expression)); } } // This code is contributed by Chetan Bargal |
Javascript
// JavaScript implementation of the approach // Size of the stack const MAX = 40; class Stack { constructor() { // Stack: array of characters this .st = Array(MAX).fill(0); // Number at top of the stack this .top = 0; } // Function to put a character in stack push(value) { this .top += 1; this .st[ this .top] = value; } // Function to return a character off stack pop() { let topval = this .st[ this .top]; this .top -= 1; return topval; } // Function to get the top of the stack gettop() { return this .top; } } // Expression class class Express { constructor(ptr) { // Stack for analysis this .s = new Stack(); // Pointer to input string this .pStr = ptr; // Length of the input string this .len = this .pStr.length; } // Parse the input string parse() { // Last value let lastval = 0; // Last operator let lastop = 0; // For each input character for (let j = 0; j < this .len; j++) { let ch = this .pStr[j]; // If it's a digit then save the numerical value if (ch >= '0 ' && ch <= ' 9 ') { this.s.push(parseInt(ch) - parseInt(' 0 ')); } // If it' s an operator else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ) { // If it is the first operator then put it in the stack if ( this .s.gettop() == 1) { this .s.push(ch); } // Not the first operator else { lastval = this .s.pop(); lastop = this .s.pop(); // If it is either '*' or '/' and the last operator was either '+' or '-' if ((ch == '*' || ch == '/' ) && (lastop == '+' || lastop == '-' )) { // Restore the last two pops this .s.push(lastop); this .s.push(lastval); } // In all the other cases else { // Perform the last operation if (lastop == '+' ) { this .s.push( this .s.pop() + lastval); } else if (lastop == '-' ) { this .s.push( this .s.pop() - lastval); } else if (lastop == '*' ) { this .s.push( this .s.pop() * lastval); } else if (lastop == '/' ) { this .s.push( this .s.pop() / lastval); } else { console.log( "\nUnknown operator" ); process.exit(1); } } this .s.push(ch); } } else { console.log( "\nUnknown input character" ); process.exit(1); } } } // Evaluate the stack solve() { // Remove the items from stack let lastval = 0; while ( this .s.gettop() > 1) { lastval = this .s.pop(); let lastop = this .s.pop(); // Perform operation, push answer if (lastop == '+' ) { this .s.push( this .s.pop() + lastval); } else if (lastop == '-' ) { this .s.push( this .s.pop() - lastval); } else if (lastop == '*' ) { this .s.push( this .s.pop() * lastval); } else if (lastop == '/' ) { this .s.push( this .s.pop() / lastval); } else { console.log( "\nUnknown operator" ); process.exit(1); } } return parseInt( this .s.pop()); } } // Driver code let st; st = "2+3*4/3-2" ; let eptr = new Express(st); eptr.parse(); console.log(eptr.solve()); // This code is contributed by japmeet01 |
4
Time Complexity: O(N).
Auxiliary Space: O(N).