Expression Evaluation using stack in C

In this article, you will learn about the evaluation using stack in C with its different ways and examples.

Let's evaluate a string representation of an expression. You can presume that brackets are properly matched if the expression contains them. For the sake of simplicity, assume that the only valid binary operations are +, -, *, and /. There are three ways to write arithmetic expressions:

1. Infix Notation:

The operators in infix notation are written between the operands they operate on.

For example: 5 + 8

Infix expressions are more difficult for computers because it takes more time to determine priority. Expressions are typically entered into programs using infix notation, which is how humans write, read, and understand them. Since they are more difficult to analyze, they are typically changed into one of the two remaining types.

The output of this procedure is a queue that contains the expression changed to postfix notation from an input infix expression. It is possible to alter the same method such that it outputs the outcome of the evaluation of the expression rather than a queue. The secret is to use two stacks rather than one, one for operators and one for operands.

Infix notation is the usual way to write mathematical expressions in C, which places operators between operands. Here is a basic mathematical procedure using infix notation:

Example:

Output:

Addition of 7 and 8 is: 15
Subtraction of 7 and 8 is: -1
Multiplication of 7 and 8 is: 56
Division of 7 and 8 is: 0

Explanation:

Using infix notation and the +, -, *, and / operators, we declare two integer variables, a and b, and then apply several mathematical operations on them. The console receives a printout of the results.

2. Prefix Notation:

In the prefix notation, operators are written before the operands. In prefix notation, also referred to as Polish notation, each operator is followed by each of its operands. To put it another way, the operator comes before its operands. Because the position of the operator controls which operands it operates upon, this notation does away with the requirement for brackets to denote the order of operations. The Polish mathematician Jan Ukasiewicz created the prefix notation, which is employed in a variety of mathematics and computer science situations.

  • In front of their operands, operators are positioned.
  • The operator's position clearly defines its operands. Thus, there are no ambiguities regarding the order of operations.
  • Usually, a stack-based technique is used to analyze prefix expressions.
  • For instance, think about the infix equation "2 + 3". The format for prefixes is "+ 2 3". The breakdown of this phrase is as follows:
  • Before the operands "2" and "3", the operator "+" is present, signifying addition.
  • To begin evaluating this expression, add the "+" operator to the operands "2" and "3", which will give you the number "5".

The following steps can be used to evaluate a prefix expression in C while using a stack data structure:

  1. Create an empty stack at first.
  2. The expression should be read from left to right.
  3. About each operand or operator:
  4. Put it on the stack if it is an operand.

If it is an operator, remove the necessary quantity of operands from the stack, execute the operation, and then push the outcome back onto the stack.

After executing the full phrase, the only thing on the stack will be the final result.

Example:

Let's take an example to convert infix to prefix expression in C:

Output:

The infix is: ((a/b)+c)-(d+(e*f))
The prefix is: -+/abc+d*ef

Explanation:

  1. Struct Stack: The program specifies a structure called stack to describe a stack data structure. Several conversion-related activities make use of this stack.
  2. create function(): Creating a stack is done using the create() function. It allows space for the stack's array and sets its properties to initial values, including top, maxSize, and the array's contents.
  3. isFull() and isEmpty() Functions: Both isFull() and isEmpty() functions determine if the stack is full or empty. These functions are used by the program to prevent pushing components onto full stacks or popping elements off of empty stacks.
  4. push() Function: The push() function is used to add elements to the stack.
  5. pop() Function: Using the pop() function, you can remove items from a stack.
  6. peek() Function: The peek() function is used to retrieve the top element from a stack without deleting it.
  7. Function checkIfOperand(): This function determines whether or not a character is an operand (a variable). If the character is a letter (uppercase or lowercase), indicating an operand, it returns true.
  8. precedence() Function: This function gives operators a precedence value. Greater values indicate greater precedence. It gives back the provided operator's precedence.
  9. getPostfix() Function: The getPostfix() function changes the infix expression's notation to postfix. The output is in postfix notation because it manages operators and brackets on the stack while iterating through the infix expression character by character.
  10. reverse() Function: This function reverses the string that is passed to it. It is used to temporarily flip the infix phrase for convenience in converting to prefix notation.
  11. brackets() Function: This function changes '(' to ')' and ')' to ')' in the given string. When converting to postfix notation, brackets are handled by this function.
  12. InfixtoPrefix() Function: The fundamental logic for changing infix to prefix notation is included in the InfixtoPrefix() method. It uses the function reverse() to temporarily reverse the infix expression, brackets() to handle brackets, getPostfix() to convert to postfix notation, reverses the result back to prefix notation, etc.
  13. main() Function: The program conducts the conversion from infix to prefix using the InfixtoPrefix() function in the main() function, which also contains an example infix phrase. A printout of the resulting prefix expression follows.

3. Postfix Notation:

Reverse Polish Notation (RPN), also referred to as postfix notation, is a mathematical notation where each operator is followed by each of its operands. In other words, the operator comes after its operands. This notation does away with the requirement for brackets to specify the order of operations because the position of the operator controls which operands it operates upon. The Polish mathematician Jan Usiewicz created the postfix notation, which is widely used in computer science and calculators today.

Postfix notation:

  • Operators are positioned after their operands.
  • There are no misunderstandings regarding the order of operations because the operator's location explicitly identifies its operands.
  • Typically, a stack-based technique is used to evaluate postfix expressions.
  • Take the infix statement "2 + 3" as an example. "2 3 +" is how it's expressed in postfix notation. An explanation of this phrase is provided below:
  • The operands "2" and "3" are placed before the operator "+".
  • To evaluate this expression, you would start by adding the "+" operator to the operands "2" and "3", which would give you the number "5".

Utilizing a stack data structure and the general techniques below, you can evaluate a postfix expression in C.

  1. Create a new stack.
  2. Take a left-to-right reading of the expression.
  3. As an operator or an operand, each element is:
  4. Push it to the top of the stack if it's an operand.
  5. If it's an operator, remove the necessary number of operands off the stack, execute the operation, and then push the outcome back onto the stack.
  6. Once the entire expression has been processed, the only thing on the stack will be the final result.

Example:

Let's take an example to convert infix to postfix expression in C:

Output:

ASSUMPTION: The infix expression contains single-letter variables and single-digit constants only.
Enter Infix expression: 3+4-2*1/8
Postfix Expression: 34+21*8/-

Explanation:

  1. Stack Data Structure: The program makes use of an array-based stack to store operators transiently throughout the conversion process. The global array stack is used to implement the stack, and a variable of the integer type int top is used to track the entry at the top.
  2. push() Function: Use the push() function to add an item to the stack. Before pushing something, it looks for stack overflow.
  3. pop() Function: Use the pop() function to remove an item from the stack. Before returning the popped item, it checks for stack underflow.
  4. is_operator() Function: The is_operator() function checks whether the given character is an operator (, *, /, +, -). If an operator, it gives back 1; otherwise, it gives back 0.
  5. precedence() Function: This function gives operators a precedence value. Greater values indicate greater precedence. It gives back the provided operator's precedence.
  6. InfixToPostfix() Function: The fundamental component of the program is the InfixToPostfix() function. It changes a postfix expression from an infix expression. The actions comprise:
    • The infix expression is made easier to process by having a '(' at the beginning and a ')' at the conclusion.
    • Going through each letter in the infix expression in turn:
    • It is immediately added to the postfix expression if it is an operand (a digit or a letter).
    • It gets pushed onto the stack if it is an open parenthesis, "(".
    • If it's an operator, the program determines its precedence before adding operators from the stack to the postfix expression until it finds one with a lower precedence or an open parenthesis '('. After that, it moves the active operator up onto the stack.
    • If the parenthesis is close (')', the program pops operators from the stack and adds them to the postfix expression until it reaches an open parenthesis ('('), which is also popped from the stack.
    • It checks for invalid infix expressions by making sure the stack is empty after processing all characters. The conversion was successful if the stack was empty. If not, it leaves after indicating an invalid infix expression.
  7. main Function(): The user is prompted to input an infix expression in the main() method. It is converted to postfix notation by using the InfixToPostfix() After that, the final postfix expression is printed.