面白そうだな〜と思っていたので、実装しました。
要するに電卓です。
10+4*(10/2+7)/2+2+(3+(2+2)) ←こういうのを計算してくれます。負数と小数点には対応してません。
楽しかったので自己満足記事です。verifyはしてないので、使用は自己責任でお願いします。
バグがあれば教えてください。
#include <iostream> #include <string> #include <vector> #include <stack> using namespace std; bool isOp(string c){return c == "+" or c == "*" or c == "-" or c == "/" or c == ")" or c == "("; } bool isOp(char c){return c == '+' or c == '*' or c == '-' or c == '/';} bool isNum(char c){return '0' <= c and c <= '9';} bool isNum(string s){return !(isOp(s));} auto parser(string s){ string num = ""; vector<string>token; for(auto c : s){ if(isNum(c)){ num.push_back(c); } else { if(not num.empty()){ token.push_back(num); num.clear(); } token.push_back(string() + c); } } if(not num.empty()) token.push_back(num); return token; } auto OperandPriority(string lower,string higher){ return ((lower == "+" or lower == "-") and (higher == "*" or higher == "/")) ; } auto constructRPN(vector<string>token){ //逆ポーランド記法の文字列配列を生成。 stack<string>st; vector<string> buffer; for(auto str : token){ if(isNum(str)){ buffer.push_back(str); } else { if(str == ")"){ while(st.top() != "("){ buffer.push_back (st.top()); st.pop(); } assert(st.top() == "("); st.pop(); } else if(str == "(" or st.empty()){ st.push(str); } else if(OperandPriority(st.top(),str)){ st.push(str); } else { while(not st.empty() and st.top() != "(" and !OperandPriority(st.top(),str)){ buffer.push_back(st.top()); st.pop(); } st.push(str); } } } while(not st.empty())buffer.push_back(st.top()),st.pop(); return buffer; } int execute(vector<string> l){ stack<int>num; for(auto s: l){ if(isNum(s)){ num.push(stoi(s)); } else { int res = 0; int val1 = num.top();num.pop(); int val2 = num.top();num.pop(); char c = s.front(); switch (c) { case '+': res = val1 + val2; break; case '*': res = val2 * val1; break; case '-': res = val2 - val1; break; default: res = val2 / val1; break; } num.push(res); } } return num.top(); } int main() { string s; cin >> s; auto token = parser(s); auto Literal = constructRPN(token); for(auto s: Literal)cout << s; cout << endl; cout << execute(Literal) << endl; }