Parsing String of symbols to Expression
Last Updated :
30 Mar, 2023
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
Time Complexity: O(N).
Auxiliary Space: O(N).
Similar Reads
How to Parse Mathematical Expressions in a C++ String?
In C++, strings are sequences of characters stored in a char array. Strings are used to store words and text. We can also store mathematical expressions in this string. In this article, we will explore how to parse mathematical expressions in a C++ String. Example: Input:expression = (3 + 4) * 2 / (
5 min read
C++ Program to Split a String Into a Number of Sub-Strings
Splitting a string by some delimiter is a very common task. For example, we have a comma-separated list of items from a file and we want individual items in an array. Almost all programming languages, provide a function split a string by some delimiter. In C++Note: The main disadvantage of strtok()
3 min read
How to Evaluate a Postfix Expression using Stack in C++?
The type of expression in which a pair of operands is followed by an operator is called a postfix expression. In this article, we will learn how we can use the stack data structure to evaluate the value of a postfix expression in C++. Example: Input: Postfix expression: "73*4+"Output: 25Evaluating P
3 min read
How to Split a C++ String into a Vector of Substrings?
In C++, splitting a string into a vector of substrings means we have to split the given string into a substring based on a given delimiter and store each substring in a vector. In this article, we will learn how to split a string into a vector of substrings in C++. Example: Input: str= "Hello, I am
2 min read
Building Expression tree from Prefix Expression
Given a character array a[] represents a prefix expression. The task is to build an Expression Tree for the expression and then print the infix and postfix expression of the built tree. Examples: Input: a[] = "*+ab-cd" Output: The Infix expression is: a + b * c - d The Postfix expression is: a b + c
8 min read
What is an Expression and What are the types of Expressions?
Expression: An expression is a combination of operators, constants and variables. An expression may consist of one or more operands, and zero or more operators to produce a value. Example: a+b c s-1/7*f . . etc Types of Expressions: Expressions may be of the following types: Constant expressions: Co
2 min read
Infix to Postfix Conversion using Stack in C++
Infix expression is a common way of writing mathematical expressions where operators are written between the operands whereas postfix is a type of expression in which a pair of operands is followed by an operator. In this article, we will learn how to use a stack to convert an infix expression to a
3 min read
C++ Program to Perform Calculations in Pure Strings
Given a string of operations containing three operands for each operation "type of command", "first operand", and "second operand". Calculate all the commands given in this string format. In other words, you will be given a pure string that will ask you to perform an operation and you have to perfor
5 min read
Reverse substrings between each pair of parenthesis
Given a string str that consists of lowercase English letters and brackets. The task is to reverse the substrings in each pair of matching parentheses, starting from the innermost one. The result should not contain any brackets. Examples: Input: str = "(skeeg(for)skeeg)" Output: geeksforgeeks Input:
9 min read
How to Split a String by Multiple Delimiters in C?
In C, strings are arrays of characters using string manipulation often requires splitting a string into substrings based on multiple delimiters. In this article, we will learn how to split a string by multiple delimiters in C.ExampleInput:char inputString[] = "Hello,World;This|is.GeeksForGeeks";char
2 min read