Evaluate Expression in C++

This command line tool accepts an argument that’s an equation that uses the 4 basic math operations (plus parenthesis). This might not compile on Windows depending on your library and compiler for the reason that it uses a C99 function strtold().

This program uses the Shunting-yard algorithm for analyzing the infix math expression. The expression is calculated during the process and therefore is never converted into reverse polish notation.

I recommend compiling this on linux. Here’s the code:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <stack>
using namespace std;

long double getnum(char *src);
void mathop(stack<long double> *out, char op);
int op_power(char op);
int is_op(char c);

void help(char *fname) {
    printf(
            "Basic math analyzer - by Jakash3\n"
            "Supports: +, -, *, /, (, and )\n"
            "Usage: %s \'equation\'\n"
            ,fname
          );
          exit(1);
}

int main(int argc, char **argv) {
    if (argc!=2) help(argv[0]);
    stack<char> ops;
    stack<long double> out;
    int i, len=strlen(argv[1]);
    for (i=0; i<len; i++) {
        if (isdigit((argv[1])[i]) || (argv[1])[i]=='.') {
            out.push(getnum(argv[1]+i));
            while (isdigit((argv[1])[i]) || (argv[1])[i]=='.') i++;
            i--;
        } else if (is_op((argv[1])[i])) {
            if (!ops.empty()) {
               while (op_power((argv[1])[i]) <= op_power(ops.top())) {
                   mathop(&out,ops.top()); ops.pop();
                   if (ops.empty()) break;
               }
            }
            ops.push((argv[1])[i]);
        } else if ((argv[1])[i]=='(') {
            ops.push((argv[1])[i]);
        } else if ((argv[1])[i]==')') {
            while (ops.top()!='(') { mathop(&out,ops.top()); ops.pop(); }
            ops.pop();
        }
    }
    if (!ops.empty()) { while(!ops.empty()) { mathop(&out,ops.top()); ops.pop(); } }
    printf("%Lf\n",out.top());
    return 0;
}

void mathop(stack<long double> *out, char op) {
    long double tmp1, tmp2;
    tmp2 = out->top(); out->pop();
    tmp1 = out->top(); out->pop();
    if (op=='+') out->push(tmp1 + tmp2);
    else if (op=='-') out->push(tmp1 - tmp2);
    else if (op=='*') out->push(tmp1 * tmp2);
    else if (op=='/') out->push(tmp1 / tmp2);
}

long double getnum(char *src) {
    int i=0, j;
    while (isdigit(src[i]) || src[i]=='.') i++;
    char *str_num = (char*)malloc(i+1);
    for (j=0; j<=i; j++) str_num[j]=src[j];
    str_num[i+1]='';
    long double ret=strtold(str_num,0);
    free(str_num);
    return ret;
}

int op_power(char op) {
    if (op=='+' || op=='-') {
        return 1;
    } else if (op=='*' || op=='/') {
        return 2;
    } else {
        return 0;
    }
}

int is_op(char c) {
    if (c=='+' || c=='-' || c=='*' || c=='/') return 1;
    return 0;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: