Last active
September 5, 2017 08:49
-
-
Save ashutoshbsathe/752a6ed1d0a94c9f5269e91ccde9568c to your computer and use it in GitHub Desktop.
infix to postfix converter with postfix evaluator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <strings.h> | |
#include <string.h> | |
#include <limits.h> | |
#include <errno.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include "stack.h" | |
#include "cstack.h" | |
/* Reads a line of input from the user, till \n | |
* and stores it in the array arr and makes arr | |
* a string, and returns no. of characters read | |
*/ | |
int readline(char *arr, int n) { | |
char ch; | |
int i = 0; | |
while((ch = getchar()) != '\n' && i < n) | |
arr[i++] = ch; | |
arr[i] = '\0'; | |
return i; | |
} | |
#define OPERATOR 100 | |
#define OPERAND 200 | |
#define END 300 | |
#define ERROR 400 | |
typedef struct token{ | |
int type; | |
union data { | |
int num; | |
char op; | |
}data; | |
}token; | |
/* input: a postfix string, possibly with errors | |
* output: the 'next' token from string, separated on | |
* space or operator | |
* type: OPERAND, OPERATOR, END, ERROR | |
*/ | |
enum states {START, DIG, OP, STOP, ERR, SPC}; | |
token getnext(char *str, int *restart) { | |
static int currstate = START; | |
int nextstate; | |
static int i = 0; | |
token t; | |
int sum = 0; | |
char currchar, currop; | |
if(*restart == 1) { | |
i = 0; | |
currstate = START; | |
*restart = 0; | |
} | |
while(1) { | |
currchar = str[i]; | |
switch(currstate) { | |
case START: | |
switch(currchar) { | |
case '0': case '1': case '2': | |
case '3': case '4': case '5': | |
case '7': case '8': case '9': | |
case '6': | |
nextstate = DIG; | |
sum = currchar - '0'; | |
break; | |
case '+': case '-': case '*': | |
case '/': case '%': | |
nextstate = OP; | |
currop = currchar; | |
break; | |
case ' ': case '\t': | |
nextstate = SPC; | |
break; | |
case '\0': | |
nextstate = STOP; | |
break; | |
default: | |
break; | |
} | |
break; | |
case DIG: | |
switch(currchar) { | |
case '0': case '1': case '2': | |
case '3': case '4': case '5': | |
case '7': case '8': case '9': | |
case '6': | |
nextstate = DIG; | |
sum = sum * 10 + currchar - '0'; | |
break; | |
case '+': case '-': case '*': | |
case '/': case '%': | |
nextstate = OP; | |
t.type = OPERAND; | |
t.data.num = sum; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
case ' ': case '\t': | |
nextstate = SPC; | |
t.type = OPERAND; | |
t.data.num = sum; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
case '\0': | |
nextstate = STOP; | |
t.type = OPERAND; | |
t.data.num = sum; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
default: | |
nextstate = ERR; | |
t.type = OPERAND; | |
t.data.num = sum; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
} | |
break; | |
case OP: | |
switch(currchar) { | |
case '0': case '1': case '2': | |
case '3': case '4': case '5': | |
case '7': case '8': case '9': | |
case '6': | |
nextstate = DIG; | |
sum = currchar - '0'; | |
t.type = OPERATOR; | |
t.data.op = currop; | |
currop = currchar; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
case '+': case '-': case '*': | |
case '/': case '%': | |
nextstate = OP; | |
t.type = OPERATOR; | |
t.data.op = currop; | |
currop = currchar; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
case ' ': case '\t': | |
nextstate = SPC; | |
t.type = OPERATOR; | |
t.data.op = currop; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
case '\0': | |
nextstate = ERR; | |
t.type = ERROR; | |
t.data.op = currop; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
default: | |
nextstate = ERR; | |
t.type = OPERATOR; | |
t.data.op = currop; | |
i++; | |
currstate = nextstate; | |
return t; | |
break; | |
} | |
break; | |
case SPC: | |
switch(currchar) { | |
case '0': case '1': case '2': | |
case '3': case '4': case '5': | |
case '7': case '8': case '9': | |
case '6': | |
nextstate = DIG; | |
sum = currchar - '0'; | |
break; | |
case '+': case '-': case '*': | |
case '/': case '%': | |
nextstate = OP; | |
currop = currchar; | |
break; | |
case ' ': case '\t': | |
nextstate = SPC; | |
break; | |
case '\0': | |
nextstate = STOP; | |
break; | |
default: | |
nextstate = ERR; | |
break; | |
} | |
break; | |
case STOP: | |
t.type = END; | |
return t; | |
break; | |
case ERR: | |
t.type = ERROR; | |
return t; | |
break; | |
} | |
currstate = nextstate; | |
i++; | |
} | |
} | |
char ctop(cstack *s) { | |
char temp = cpop(s); | |
cpush(s, temp); | |
return temp; | |
} | |
int precedence(char op) { | |
if(op == '%') | |
return 70; | |
if(op == '*' || op == '/') | |
return 50; | |
if(op == '+' || op == '-') | |
return 30; | |
return 0; | |
} | |
/* | |
* Returns pointer to malloced memory. The caller should free it. | |
*/ | |
char *intopost(char *str) { | |
cstack cs; | |
token t; | |
char *output = (char *)malloc(128); | |
char temp[16]; | |
int restart = 1; | |
int preccurr, prectop; | |
char ch; | |
if(output == NULL) | |
return NULL; | |
cinit(&cs); | |
while(1) { | |
t = getnext(str, &restart); | |
if(t.type == OPERAND) { | |
sprintf(temp, "%d", t.data.num); | |
strcat(output, temp); | |
strcat(output, " "); | |
} else if(t.type == OPERATOR) { | |
if(!cisempty(&cs)) { | |
preccurr = precedence(t.data.op); | |
prectop = precedence(ctop(&cs)); | |
while(preccurr <= prectop) { | |
ch = cpop(&cs); | |
temp[0] = ch; | |
temp[1] = '\0'; | |
strcat(output, temp); | |
strcat(output, " "); | |
if(!cisempty(&cs)) | |
prectop = precedence(ctop(&cs)); | |
else | |
break; | |
} | |
} | |
cpush(&cs, t.data.op); | |
} else if(t.type == END) { | |
while(!cisempty(&cs)) { | |
ch = cpop(&cs); | |
temp[0] = ch; | |
temp[1] = '\0'; | |
strcat(output, temp); | |
strcat(output, " "); | |
} | |
break; | |
} else if(t.type == ERROR) { | |
free(output); | |
return NULL; | |
} | |
} | |
return output; | |
} | |
/* Evaluates the postfix expression in str | |
* and returns the result as int | |
*/ | |
int postfix(char *str) { | |
int x, y, res; | |
token t; | |
int restart = 1; | |
stack s; | |
init(&s); | |
while(1) { | |
t = getnext(str, &restart); | |
if(t.type == OPERAND) { | |
if(!isfull(&s)) | |
push(&s, t.data.num); | |
else | |
return INT_MIN; | |
} else if(t.type == OPERATOR) { | |
if(!isempty(&s)) | |
x = pop(&s); | |
else | |
return INT_MIN; | |
//a[i - 1]; i--; | |
if(!isempty(&s)) | |
y = pop(&s); | |
else | |
return INT_MIN; | |
//a[i - 1]; i--; | |
switch(t.data.op) { | |
case '+': | |
res = y + x; | |
break; | |
case '-': | |
res = y - x; | |
break; | |
case '*': | |
res = y * x; | |
break; | |
case '/': | |
res = y / x; | |
break; | |
case '%': | |
res = y % x; | |
break; | |
} | |
if(!isfull(&s)) | |
push(&s, res); | |
else | |
return INT_MIN; | |
//i--; | |
} else if(t.type == END) { | |
break; | |
} else if(t.type == ERROR) { | |
return INT_MIN; | |
} | |
} | |
if(!isempty(&s)) | |
res = pop(&s); | |
else | |
return INT_MIN; | |
if(isempty(&s)) | |
return res; | |
else | |
return INT_MIN; | |
} | |
/* Postfix evaluator: | |
* Reads an input string, and evalutes the postfix | |
* expression stored in the strinng. | |
* The string contains operators and operands sepearted | |
* by spaces. operands are separated by 1 or more spaces. | |
* operators and operands are seperated by zero or more spaces. | |
* Result: number | |
* E.g. 11 22 + | |
* Ans: 33 | |
* E.g. 11 22 33+ - | |
* Ans: -44 | |
* | |
*/ | |
int main(int argc, char *argv[]) { | |
char line[128], *p; | |
int x, y; | |
while(x = readline(line, 128)) { | |
p = intopost(line); | |
if(p != NULL) { | |
puts(p) | |
y = postfix(p); | |
if(y != INT_MIN) | |
printf("%d\n", y); | |
printf("--------------------------------------------\n\n"); | |
} | |
else | |
fprintf(stderr, "Error in expression\n"); | |
} | |
//printf("%d\n", y); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment