mirror of https://github.com/TheAlgorithms/C
165 lines
4.4 KiB
C
165 lines
4.4 KiB
C
/**
|
|
* @file
|
|
* @brief [Infix to Postfix converter](https://www.includehelp.com/c/infix-to-postfix-conversion-using-stack-with-c-program.aspx) implementation
|
|
* @details
|
|
* The input infix expression is of type string upto 24 characters.
|
|
* Supported operations- '+', '-', '/', '*', '%'
|
|
* @author [Kumar Yash](https://github.com/kumaryash18)
|
|
* @see infix_to_postfix.c
|
|
*/
|
|
|
|
#include <stdio.h> /// for IO operations
|
|
#include <string.h> /// for strlen(), strcmp()
|
|
#include <ctype.h> /// for isalnum()
|
|
#include <stdlib.h> /// for exit()
|
|
#include <stdint.h> /// for uint16_t, int16_t
|
|
#include <assert.h> /// for assert
|
|
|
|
/**
|
|
* @brief array implementation of stack using structure
|
|
*/
|
|
struct Stack {
|
|
char stack[10]; ///< array stack
|
|
int top; ///< stores index of the top element
|
|
};
|
|
struct Stack st; ///< global declaration of stack st
|
|
|
|
/**
|
|
* @brief Function to push on the stack
|
|
* @param opd character to be pushed in the stack
|
|
* @returns void
|
|
*/
|
|
void push(char opd) {
|
|
if(st.top == 9) { // overflow condition
|
|
printf("Stack overflow...");
|
|
exit(1);
|
|
}
|
|
st.top++;
|
|
st.stack[st.top] = opd;
|
|
}
|
|
|
|
/**
|
|
* @brief Function to pop from the stack
|
|
* @returns popped character
|
|
*/
|
|
char pop() {
|
|
char item; ///< to store the popped value to be returned
|
|
if(st.top == -1) { // underflow condition
|
|
printf("Stack underflow...");
|
|
exit(1);
|
|
}
|
|
item = st.stack[st.top];
|
|
st.top--;
|
|
return item;
|
|
}
|
|
|
|
/**
|
|
* @brief Function to check whether the stack is empty or not
|
|
* @returns 1 if the stack IS empty
|
|
* @returns 0 if the stack is NOT empty
|
|
*/
|
|
uint16_t isEmpty() {
|
|
if(st.top == -1) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Function to get top of the stack
|
|
* @returns top of stack
|
|
*/
|
|
char Top() {
|
|
return st.stack[st.top];
|
|
}
|
|
|
|
/**
|
|
* @brief Function to check priority of operators
|
|
* @param opr operator whose priority is to be checked
|
|
* @returns 0 if operator is '+' or '-'
|
|
* @returns 1 if operator is '/' or '*' or '%'
|
|
* @returns -1 otherwise
|
|
*/
|
|
int16_t priority(char opr) {
|
|
if(opr == '+' || opr == '-') {
|
|
return 0;
|
|
}
|
|
else if(opr == '/' || opr == '*' || opr == '%') {
|
|
return 1;
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Function to convert infix expression to postfix expression
|
|
* @param inf the input infix expression
|
|
* @returns output postfix expression
|
|
*/
|
|
char *convert(char inf[]) {
|
|
static char post[25]; ///< to store the postfix expression
|
|
int i; ///< loop iterator
|
|
int j = 0; ///< keeps track of end of postfix string
|
|
for(i = 0; i < strlen(inf); i++) {
|
|
if(isalnum(inf[i])) { // if scanned element is an alphabet or number
|
|
post[j] = inf[i]; // append in postfix expression
|
|
j++;
|
|
}
|
|
else if(inf[i] == '(') { // if scanned element is opening parentheses
|
|
push(inf[i]); // push on stack.
|
|
}
|
|
else if(inf[i] == ')') { // if scanned element is closing parentheses,
|
|
while(Top() != '(') { // pop elements from stack and append in postfix expression
|
|
post[j] = pop(); // until opening parentheses becomes top.
|
|
j++;
|
|
}
|
|
pop(); // pop opening parentheses
|
|
}
|
|
else { // if scanned element is an operator
|
|
while( (!isEmpty()) && (priority(inf[i]) <= priority(Top())) ) { // pop and append until stack becomes
|
|
post[j] = pop(); // empty or priority of top operator
|
|
j++; // becomes smaller than scanned operator
|
|
} // '(' has priority -1
|
|
push(inf[i]); // push the scanned operator
|
|
}
|
|
}
|
|
while(!isEmpty()) { // pop and append residual operators from stack
|
|
post[j] = pop();
|
|
j++;
|
|
}
|
|
post[j] = '\0'; // end postfix string with null character
|
|
return post;
|
|
}
|
|
|
|
/**
|
|
* @brief Self-test implementations
|
|
* @returns void
|
|
*/
|
|
static void test() {
|
|
/* check sample test case
|
|
input- "(A/(B-C)*D+E)"
|
|
expected output- "ABC-/D*E+"
|
|
*/
|
|
assert(strcmp(convert("(A/(B-C)*D+E)"), "ABC-/D*E+") == 0); /// this ensures that the algorithm works as expected
|
|
/* input- "7-(2*3+5)*(8-4/2)"
|
|
expected output- "723*5+842/-*-"
|
|
*/
|
|
assert(strcmp(convert("7-(2*3+5)*(8-4/2)"), "723*5+842/-*-") == 0); /// this ensures that the algorithm works as expected
|
|
printf("All tests have successfully passed!\n");
|
|
}
|
|
|
|
/**
|
|
* @brief Main function
|
|
* @returns 0 on exit
|
|
*/
|
|
int main() {
|
|
st.top = -1; /// initialize
|
|
test(); /// run self-test implementations
|
|
char inf[25]; ///< to store input infix expression
|
|
printf("Enter infix: ");
|
|
scanf("%s", inf);
|
|
printf("Postfix: %s", convert(inf));
|
|
return 0;
|
|
}
|