main.c
#include <stdio.h>
#include <stdlib.h>
#include "eval.h"
#define BUFFERSIZE (256)
int main(void) {
char input[BUFFERSIZE];
printf("Enter your expression: ");
fflush(stdout);
fgets(input, BUFFERSIZE, stdin);
printf("Result is: %.2f\n", evaluate(input));
return EXIT_SUCCESS;
}
eval.c
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "token.h"
char * toPostfix(char * infix, char * postfix) {
char buffer[BUFFERSIZE];
int stack[STACKSIZE];
int top = 0;
struct token t;
*postfix = 0;
while ( (infix = GetNextToken(infix, &t)) ) {
if ( t.type == TOK_OPERAND ) {
sprintf(buffer, "%d ", t.value);
strcat(postfix, buffer);
}
else {
if ( top == 0 || oplist[t.value].precedence >
oplist[stack[top]].precedence ||
oplist[stack[top]].value == OP_LPAREN ) {
stack[++top] = t.value;
}
else {
int balparen = 0;
while ( top > 0 && ((oplist[stack[top]].precedence >=
oplist[t.value].precedence)
|| balparen)
&& !(!balparen
&& oplist[stack[top]].value ==
OP_LPAREN) ) {
if ( stack[top] == OP_RPAREN )
++balparen;
else if ( stack[top] == OP_LPAREN )
--balparen;
else {
sprintf(buffer, "%c ", oplist[stack[top]].symbol);
strcat(postfix, buffer);
}
--top;
}
stack[++top] = t.value;
}
}
}
while ( top > 0 ) {
if ( oplist[stack[top]].value != OP_LPAREN &&
oplist[stack[top]].value != OP_RPAREN ) {
sprintf(buffer, "%c ", oplist[stack[top]].symbol);
strcat(postfix, buffer);
}
--top;
}
return postfix;
}
double parsePostfix(char * postfix) {
struct token t;
double stack[STACKSIZE];
int top = 0;
while ( (postfix = GetNextToken(postfix, &t)) ) {
if ( t.type == TOK_OPERAND ) {
stack[++top] = t.value;
}
else {
double a, b, value;
if ( top < 2 ) {
puts("Stack empty!");
exit(EXIT_FAILURE);
}
b = stack[top--];
a = stack[top--];
switch ( t.value ) {
case OP_PLUS:
value = a + b;
break;
case OP_MINUS:
value = a - b;
break;
case OP_MULTIPLY:
value = a * b;
break;
case OP_DIVIDE:
value = a / b;
break;
case OP_MOD:
value = fmod(a, b);
break;
case OP_POWER:
value = pow(a, b);
break;
default:
printf("Bad operator: %c\n", oplist[t.value].symbol);
exit(EXIT_FAILURE);
break;
}
stack[++top] = value;
}
}
return stack[top];
}
double evaluate(char * infix) {
char postfix[BUFFERSIZE];
return parsePostfix(toPostfix(infix, postfix));
}
token.h
#ifndef PG_TOKEN_H
#define PG_TOKEN_H
#define BUFFERSIZE (256)
#define STACKSIZE (256)
#define TOK_OPERAND (0)
#define TOK_OPERATOR (1)
#define OP_PLUS (0)
#define OP_MINUS (1)
#define OP_MULTIPLY (2)
#define OP_DIVIDE (3)
#define OP_POWER (4)
#define OP_MOD (5)
#define OP_RPAREN (6)
#define OP_LPAREN (7)
#define OP_BAD (99)
struct token {
int type;
int value;
};
struct operator {
char symbol;
int value;
int precedence;
};
extern struct operator oplist[];
char * GetNextToken(char * input, struct token * t);
#endif
token.c
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "token.h"
struct operator oplist[] = { {'+', OP_PLUS, 1},
{'-', OP_MINUS, 1},
{'*', OP_MULTIPLY, 2},
{'/', OP_DIVIDE, 2},
{'^', OP_POWER, 3},
{'%', OP_MOD, 2},
{')', OP_RPAREN, 4},
{'(', OP_LPAREN, 5},
{0, 0, 0} };
char * GetNextToken(char * input, struct token * t) {
while ( *input && isspace(*input) )
++input;
if ( *input == 0 )
return NULL;
if ( isdigit(*input) ) {
t->type = TOK_OPERAND;
t->value = strtol(input, &input, 0);
}
else {
int n = 0, found = 0;
t->type = TOK_OPERATOR;
while ( !found && oplist[n].symbol ) {
if ( oplist[n].symbol == *input ) {
t->value = oplist[n].value;
found = 1;
}
++n;
}
if ( !found ) {
printf("Bad operator: %c\n", *input);
exit(EXIT_FAILURE);
}
++input;
}
return input;
}