Skip to content

Instantly share code, notes, and snippets.

@ashutoshbsathe
Last active September 5, 2017 08:49
Show Gist options
  • Save ashutoshbsathe/752a6ed1d0a94c9f5269e91ccde9568c to your computer and use it in GitHub Desktop.
Save ashutoshbsathe/752a6ed1d0a94c9f5269e91ccde9568c to your computer and use it in GitHub Desktop.
infix to postfix converter with postfix evaluator
#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