Get result of an expression in c ++

1

I'm almost finishing my expression interpreter. But I have no idea how to do the most important part: The result

I would learn a lot from any idea.

main.cpp

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cmath>
#include <algorithm>

//defines
#define space ' '

//disables any deprecation warning
#pragma warning(disable : 4996)

//usings
using std::vector;
using std::string;
using std::cout;
using std::endl;

long double nabs(long double dub) {
    return -abs(dub);
}

string remove_char(string str, char c = space) {
    str.erase(std::remove(str.begin(), str.end(), c), str.end());
    return str;
}

long double parse(string str) {
    return std::stold(str);
}

bool try_parse(string str)
{
    char* end = 0;
    double val = strtod(str.c_str(), &end);
    return end != str.c_str() && val != HUGE_VAL;
}

char first_char(string str) {
    return *str.c_str();
}

bool is_opr(string str) {
    return first_char(str) == '&';
}

string &first_item(vector<string> vec) {
    return vec[0];
}

vector<string> get_types(vector<string> vec) {
    for (int i = 0; i < vec.size(); i++) {
        string &s = vec[i];
        bool doubly = try_parse(s);
        bool amp = is_opr(s);

        //if unknown
        if (!doubly && !amp) {
            s = "<unk> " + s;
            continue;
        }
        //if operator
        else if (!doubly && amp) {
            s = "<opr> " + s;
            continue;
        }
        //if number
        else if (doubly && !amp) {
            s = "<dub> " + s;
            continue;
        }

    }
    return vec;
}

/*
  |
  |
  |
  V
*/
long double get_result(vector<string> vec) {
    long double val;
    for (int i = 0; i < vec.size(); i++) {
        //código...
    }
    return val;
}

vector<string> split(string s, const char c = space)
{
    string buff{ "" };
    vector<string> v;

    for (auto n : s)
    {
        if (n != c) buff += n; else
            if (n == c && buff != "") { v.push_back(buff); buff = ""; }
    }
    if (buff != "") v.push_back(buff);

    return v;
}

string simplify(string expr) {
    string iexpr = expr;
    for (int i = 0; i < iexpr.length(); i++) {

        char& c = iexpr[i];

        if (c == '+')
            iexpr.replace(i, 1, " &ad ");
        else if (c == '-')
            iexpr.replace(i, 1, " &sb ");
        else if (c == '*')
            iexpr.replace(i, 1, " &mp ");
        else if (c == '/')
            iexpr.replace(i, 1, " &dv ");

    }
    return iexpr;
}


int main() {

    vector<string> sep_rep = get_types(split(simplify("-21 + 32 - 3 * 2")));
    for (auto str : sep_rep) {
        cout << str << endl;
    }

    std::cin.get();
    return 0;
}
    
asked by anonymous 20.06.2018 / 03:18

1 answer

0

It's been a hard time doing this.

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cmath>
#include <algorithm>

//defines
#define space ' '

//disables any deprecation warning
#pragma warning(disable : 4996)

//usings
using std::vector;
using std::string;
using std::cout;
using std::endl;

long double nabs(long double dub) {
    return -abs(dub);
}

string remove_char(string str, char c = space) {
    str.erase(std::remove(str.begin(), str.end(), c), str.end());
    return str;
}

long double parse(string str) {
    return std::stold(str);
}

bool try_parse(string str) {
    char* end = 0;
    long double val = strtold(str.c_str(), &end);
    return end != str.c_str() && val != HUGE_VALL && val != -HUGE_VALL;
}

char first_char(string str) {
    return *str.c_str();
}

bool is_opr(string str) {
    return first_char(str) == '&';
}

string &first_item(vector<string> vec) {
    return vec[0];
}

vector<string> get_types(vector<string> vec) {
    for (int i = 0; i < vec.size(); i++) {
        string &s = vec[i];
        bool doubly = try_parse(s);
        bool amp = is_opr(s);

        //if unknown
        if (!doubly && !amp) {
            s = "<unk> " + s;
            continue;
        }
        //if operator
        else if (!doubly && amp) {
            s = "<opr> " + s;
            continue;
        }
        //if number
        else if (doubly && !amp) {
            s = "<dub> " + s;
            continue;
        }

    }
    return vec;
}

long double interpretar_numero(string dub) {
    if (dub.substr(0, 6).compare("<dub> ") != 0) {
        throw "Não deu para interpretar como número " + dub;
    }
    return parse(dub.substr(6));
}

long double get_result(vector<string> vec) {
    if (vec.at(0).compare("<opr> &sb") == 0 || vec.at(0).compare("<opr> &ad") == 0) {
        vec.insert(vec.begin(), "<dub> 0");
    }
    long double val = interpretar_numero(vec.at(0));
    for (int i = 1; i < vec.size(); i += 2) {
        std::string op = vec.at(i);
        if (vec.size() == i + 1) throw "Esperava um número antes do fim";
        long double ot = interpretar_numero(vec.at(i + 1));

        if (op.compare("<opr> &ad") == 0) {
            val += ot;
        } else if (op.compare("<opr> &sb") == 0) {
            val -= ot;
        } else if (op.compare("<opr> &mp") == 0) {
            val *= ot;
        } else if (op.compare("<opr> &dv") == 0) {
            val /= ot;
        } else {
            throw "Esperava um operador";
        }
    }
    return val;
}

vector<string> split(string s, const char c = space) {
    string buff{ "" };
    vector<string> v;

    for (auto n : s) {
        if (n != c) {
            buff += n;
        } else if (n == c && buff != "") {
            v.push_back(buff);
            buff = "";
        }
    }
    if (buff != "") v.push_back(buff);

    return v;
}

string simplify(string expr) {
    string iexpr = expr;
    for (int i = 0; i < iexpr.length(); i++) {

        char& c = iexpr[i];

        if (c == '+') {
            iexpr.replace(i, 1, " &ad ");
        } else if (c == '-') {
            iexpr.replace(i, 1, " &sb ");
        } else if (c == '*') {
            iexpr.replace(i, 1, " &mp ");
        } else if (c == '/') {
            iexpr.replace(i, 1, " &dv ");
        }
    }
    return iexpr;
}

int main() {

    vector<string> sep_rep = get_types(split(simplify("-21 + 32 - 3 * 2")));
    for (auto str : sep_rep) {
        cout << str << endl;
    }
    try {
        cout << "R: " << get_result(sep_rep) << endl;
    } catch (const char *e) {
        cout << "Erro: " << e;
    } catch (string e) {
        cout << "Erro: " << e;
    }

    std::cin.get();
    return 0;
}

The get_result(vector<string>) function was very complicated, but what it does is:

  • If there is a plus or minus sign at the beginning, put a zero before.
  • Interprets the first element of the vector as a number and sets the corresponding value to val .
  • Interprets the following vector elements as pairs in the format [ op , ot ], where ot are numbers are in odd positions and op are operators in even positions.
  • For each pair [ op , ot ], use the op operator with the val and ot values and save the result in val .
  • If the vector does not have an odd number of strings, or if val or ot can not be interpreted as numbers or if op can not be interpreted as an operator, it throws a string as an exception .
  • The output generated is as follows:

    <opr> &sb
    <dub> 21
    <opr> &ad
    <dub> 32
    <opr> &sb
    <dub> 3
    <opr> &mp
    <dub> 2
    R: 16
    

    The reason for being 16 is that it transforms " - 21 + 32 - 3 * 2" into " 0 - 21 + 32 - 3 * 2 ". Then it interprets " 0 " as val . It does " 0 - 21 " and reaches -21 in response. It does " -21 + 32 " and arrives at 11 . It does " 11 - 3 " and arrives at 8 . And finally, it does " 8 * 2 " and arrives at 16 .

    See here working on ideone.

        
    20.06.2018 / 06:11