Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // CalcExpression.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
- //
- #include <iostream>
- #include <string>
- #include <vector>
- #include <algorithm>
- #include <stack>
- #include <map>
- #include <functional>
- #include <numeric>
- using namespace std;
- enum class term_t { var, constant, func, oper, op_br, cl_br};
- struct term
- {
- std::string name;
- term_t type;
- };
- std::vector<term> parse_string_to_terms(const std::string& expr)
- {
- std::vector<term> res;
- auto it = expr.begin();
- while (it != expr.end())
- {
- if (std::isspace(*it)) { ++it; continue; }
- auto termend = std::find_if(it, expr.end(), [](auto c) {return !std::isalnum(c) && c != '.'; });
- if (it == termend) ++termend;
- res.push_back({ std::string(it, termend), term_t::oper });
- it = termend;
- }
- for (size_t i = 0; i < res.size(); i++)
- {
- char c = res[i].name[0];
- if (std::isdigit(c)) res[i].type = term_t::constant;
- else if (std::isalpha(c))
- if (i < res.size() - 1 && res[i + 1].name == "(")
- res[i].type = term_t::func;
- else
- res[i].type = term_t::var;
- else if (c == '(') res[i].type = term_t::op_br;
- else if (c == ')') res[i].type = term_t::cl_br;
- }
- return res;
- }
- std::map<string, int> priority{ {"^",100}, {"*",70}, {"/",70}, {"%",70},
- {"+",40}, {"-",40}, {">",20}, {"<",20} };
- vector<term> expression_terms_to_postfix(const vector<term>& terms)
- {
- vector<term> pstfx;
- stack<term> s;
- for (const auto& t : terms)
- switch (t.type)
- {
- case term_t::constant:
- case term_t::var: pstfx.push_back(t); break;
- case term_t::func:
- case term_t::op_br:s.push(t); break;
- case term_t::cl_br:
- while (s.top().type != term_t::op_br)
- {
- pstfx.push_back(s.top());
- s.pop();
- }
- s.pop();
- break;
- case term_t::oper:
- while (s.size() && (s.top().type == term_t::func or
- s.top().type == term_t::oper && priority[s.top().name] >= priority[t.name]))
- {
- pstfx.push_back(s.top());
- s.pop();
- }
- s.push(t);
- }
- while (s.size())
- {
- pstfx.push_back(s.top());
- s.pop();
- }
- return pstfx;
- }
- using operations = std::map<std::string, std::function<double(std::stack<double>&)>>;
- double pop(std::stack<double>& s)
- {
- auto res = s.top();
- s.pop();
- return res;
- }
- operations ops{
- {"+",[](std::stack<double>& s) {return pop(s) + pop(s); }},
- {"-",[](std::stack<double>& s) {return -pop(s) + pop(s); }},
- {"*",[](std::stack<double>& s) {return pop(s) * pop(s); }},
- {"/",[](std::stack<double>& s) {return 1 / pop(s) * pop(s); }},
- {"^",[](std::stack<double>& s) { double p = pop(s); return pow(pop(s),p); }},
- {"exp",[](std::stack<double>& s) {return exp(pop(s)); }},
- {"cos",[](std::stack<double>& s) {return cos(pop(s)); }},
- {">",[](std::stack<double>& s) {return pop(s) < pop(s); }},
- {"<",[](std::stack<double>& s) {return pop(s) > pop(s); }},
- };
- double postfix_calc(const vector<term>& pstfx, operations& ops, map<string, double>& vars)
- {
- stack<double> s;
- for (auto& t : pstfx)
- switch (t.type)
- {
- case term_t::var: s.push(vars[t.name]); break;
- case term_t::constant: s.push(stod(t.name)); break;
- case term_t::func:
- case term_t::oper: s.push(ops[t.name](s)); break;
- }
- return s.top();
- }
- int main()
- {
- std::string expr = "3.15*abc+exp(x^2-cos(x-y-z/x*y))";
- auto terms = parse_string_to_terms(expr);
- auto pstx = expression_terms_to_postfix(terms);
- for (auto t : pstx)
- std::cout << t.name << " " << (int)t.type << std::endl;
- std::map<string, double> vars{ {"abc", 3.0}, {"x", 2.5}, {"y", -1.1}, {"z", 0.1}};
- std::cout << postfix_calc(pstx,ops,vars) << std::endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement