Language: C++
/* UVa 397 - Equation Elation To build using Visual Studio 2012: cl -EHsc -O2 UVa_397_Equation_Elation.cpp */ #include <iostream> #include <sstream> #include <string> #include <deque> #include <stack> #include <cctype> using namespace std; enum {type_operator, type_operand}; enum {multiply, divide, add, subtract}; struct op { int type_; int value_; op() {} op(int type, int value) : type_(type), value_(value) {} string to_string() const { ostringstream oss; if (type_ == type_operator) { switch (value_) { case multiply: oss << '*'; break; case divide: oss << '/'; break; case add: oss << '+'; break; case subtract: oss << '-'; break; } } else oss << value_; return oss.str(); } #ifdef DEBUG void print() const { if (type_ == type_operator) { switch (value_) { case multiply: cout << '*'; break; case divide: cout << '/'; break; case add: cout << '+'; break; case subtract: cout << '-'; break; } } else cout << value_; } #endif }; int read_integer() { int i = 0; while (true) { char c; cin >> c; if (!isdigit(c)) { cin.unget(); break; } i *= 10; i += c - '0'; } return i; } bool read_equation(deque<op>& infix_ops, string& variable, int& nr_muldiv) { nr_muldiv = 0; char c = 0; while (cin >> c) { if (c == '=') { cin >> variable; return true; } if (c == '+' || c == '-') { if (infix_ops.empty() || infix_ops.back().type_ == type_operator) { // unary operator int sign = (c == '-') ? -1 : 1; infix_ops.push_back(op(type_operand, sign * read_integer())); } else infix_ops.push_back(op(type_operator, ((c == '-') ? subtract : add))); } else if (c == '*') { nr_muldiv++; infix_ops.push_back(op(type_operator, multiply)); } else if (c == '/') { nr_muldiv++; infix_ops.push_back(op(type_operator, divide)); } else { cin.unget(); infix_ops.push_back(op(type_operand, read_integer())); } } return false; } #ifdef DEBUG void print_equation(const deque<op>& infix_ops, const string& variable) { for (deque<op>::const_iterator i = infix_ops.begin(), e = infix_ops.end(); i != e; ++i) { i->print(); cout << ' '; } cout << "= " << variable << endl; } #endif void infix_to_postfix(const deque<op>& infix_ops, deque<op>& postfix_ops) { stack<op> st; for (deque<op>::const_iterator i = infix_ops.begin(), e = infix_ops.end(); i != e; ++i) { if (i->type_ == type_operand) postfix_ops.push_back(*i); else { while (!st.empty()) { if ((st.top().value_ == multiply || st.top().value_ == divide) || (i->value_ == add || i->value_ == subtract)) { // stack top operator has equal or higher precedence postfix_ops.push_back(st.top()); st.pop(); } else break; } st.push(*i); } } while (!st.empty()) { postfix_ops.push_back(st.top()); st.pop(); } } void print_infix_equation(const deque<op>& postfix_ops, const string& variable) { stack<string> st; for (deque<op>::const_iterator i = postfix_ops.begin(), e = postfix_ops.end(); i != e; ++i) { if (i->type_ == type_operand) st.push(i->to_string()); else { string sj = st.top(); st.pop(); string si = st.top(); st.pop(); st.push(si + " " + i->to_string() + " " + sj); } } cout << st.top() << " = " + variable << endl; } void calculate(deque<op>& postfix_ops, int& nr_muldiv) { stack<op> st; while (!postfix_ops.empty()) { op o = postfix_ops.front(); postfix_ops.pop_front(); if (o.type_ == type_operand) st.push(o); else if (nr_muldiv && (o.value_ == add || o.value_ == subtract)) st.push(o); else { op oj = st.top(); st.pop(); op oi = st.top(); st.pop(); int v; switch (o.value_) { case multiply: nr_muldiv--; v = oi.value_ * oj.value_; break; case divide: nr_muldiv--; v = oi.value_ / oj.value_; break; case add: v = oi.value_ + oj.value_; break; case subtract: v = oi.value_ - oj.value_; break; } postfix_ops.push_front(op(type_operand, v)); break; } } while (!st.empty()) { postfix_ops.push_front(st.top()); st.pop(); } } int main() { while (true) { deque<op> infix_ops; string variable; int nr_muldiv; if (!read_equation(infix_ops, variable, nr_muldiv)) break; deque<op> postfix_ops; infix_to_postfix(infix_ops, postfix_ops); print_infix_equation(postfix_ops, variable); do { calculate(postfix_ops, nr_muldiv); #ifdef DEBUG print_equation(postfix_ops, variable); #endif print_infix_equation(postfix_ops, variable); } while (postfix_ops.size() > 1); cout << endl; } return 0; }
No comments:
Post a Comment