检测后缀表达式的合法性
前面我们介绍了《后缀表达式的计算》,具体做法在于设置一个数据结构:操作数栈,基于操作数栈根据操作符进行弹栈、运算、压栈等操作,最终计算而得后缀表达式的结果。
我们默认处理的后缀表达式都是合法的,对于非法的后缀表达式,我们并没有给出适当的处理。这里我们将在后缀表达式的计算过程中,同时检测后缀表达式是否合法,如果合法则计算到底,最终得到后缀表达式的值;如果非法,则返回该后缀表达式为非法。
比如有后缀表达式:
2 + 3 *
该后缀表达式是非法的,因为+操作符只有一个操作数2;
又如:
1 3 5 * + 7 / -
该后缀表达式的/操作符只有一个操作数7,所以也是非法的;
1 3 + 5 7 6 - * 9 /
该后缀表达式中操作数多了一个,导致其非法。
具体的算法逻辑为:
在计算后缀表达式过程中,如果操作数栈中无法提供n个操作数,则操作数太少,导致后缀表达式非法;如果遍历完后缀表达式后,操作数栈中的元素个数大于1个,则说明操作数太多,导致后缀表达式非法。
具体的程序如下:
// 检测后缀表达式的合法性 #include <iostream> #include <sstream> #include <vector> #include <stack> #include <map> #include <string> using namespace std; void get_postfix(vector<string>& postf) { postf.clear(); string line; getline(cin, line); istringstream sin(line); string tmp; while (sin >> tmp) { postf.push_back(tmp); } } void init_op(map<string, int>& ops) { ops.clear(); ops["+"] = 100; ops["-"] = 100; ops["*"] = 200; ops["/"] = 200; ops["("] = 1000; ops[")"] = 0; } bool is_operator(const string& hs, const map<string, int>& ops) { map<string, int>::const_iterator cit = ops.find(hs); if (cit != ops.end()) { return true; } else { return false; } } double cal_post(const vector<string>& postf, const map<string, int>& ops, bool& leg, int& ill_id) { stack<double> or_st; double operand = 0.0, a = 0.0, b = 0.0, c = 0.0; for (vector<string>::size_type i = 0; i != postf.size(); ++i) { if (!is_operator(postf[i], ops)) { operand = static_cast<double>(atof(postf[i].c_str())); or_st.push(operand); } else { switch (postf[i][0]) { case '+': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1001; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a + b; or_st.push(c); break; case '-': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1002; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a - b; or_st.push(c); break; case '*': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1003; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a * b; or_st.push(c); break; case '/': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1004; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a / b; or_st.push(c); break; default: break; } } } if (or_st.size() == 1) { leg = true; return or_st.top(); } else // 检测后缀表达式的合法性:操作数是否有多余 { leg = false; ill_id = 2001; return -10000000000000.0; } } int main() { map<string, int> ops; init_op(ops); vector<string> postf; while (1) { get_postfix(postf); bool leg = true; int ill_id = 0; double ret = cal_post(postf, ops, leg, ill_id); if (leg) { cout << ret << endl << endl; } else { cout << "Illegal: " << ill_id << "!" << endl << endl; } } system("PAUSE"); return 0; }
对操作符的空白符预处理:
// 对后缀表达式操作符的空白符预处理 #include <iostream> #include <sstream> #include <vector> #include <stack> #include <map> #include <string> using namespace std; string& replace_all_distinct(string& str, const string& src, const string& des) { for (string::size_type i = 0; i != string::npos; i += des.size()) { i = str.find(src, i); if (i != string::npos) { str.replace(i, src.size(), des); } else { break; } } return str; } string& n_replace(string& str, const vector<string>& src, const vector<string>& des) { assert(src.size() > 0 && src.size() == des.size()); for (vector<string>::size_type i = 0; i != src.size(); ++i) { replace_all_distinct(str, src[i], des[i]); } return str; } void get_postfix(vector<string>& postf, const vector<string>& src, const vector<string>& des) { postf.clear(); string line; getline(cin, line); n_replace(line, src, des); istringstream sin(line); string tmp; while (sin >> tmp) { postf.push_back(tmp); } } void init_op(map<string, int>& ops) { ops.clear(); ops["+"] = 100; ops["-"] = 100; ops["*"] = 200; ops["/"] = 200; ops["("] = 1000; ops[")"] = 0; } bool is_operator(const string& hs, const map<string, int>& ops) { map<string, int>::const_iterator cit = ops.find(hs); if (cit != ops.end()) { return true; } else { return false; } } double cal_post(const vector<string>& postf, const map<string, int>& ops, bool& leg, int& ill_id) { stack<double> or_st; double operand = 0.0, a = 0.0, b = 0.0, c = 0.0; for (vector<string>::size_type i = 0; i != postf.size(); ++i) { if (!is_operator(postf[i], ops)) { operand = static_cast<double>(atof(postf[i].c_str())); or_st.push(operand); } else { switch (postf[i][0]) { case '+': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1001; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a + b; or_st.push(c); break; case '-': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1002; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a - b; or_st.push(c); break; case '*': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1003; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a * b; or_st.push(c); break; case '/': // 检测后缀表达式的合法性:操作数是否足够 if (or_st.size() < 2) { leg = false; ill_id = 1004; return -10000000000000.0; } b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a / b; or_st.push(c); break; default: break; } } } if (or_st.size() == 1) { leg = true; return or_st.top(); } else // 检测后缀表达式的合法性:操作数是否有多余 { leg = false; ill_id = 2001; return -10000000000000.0; } } void init_src_des(vector<string>& src, vector<string>& des) { src.push_back("+"); src.push_back("-"); src.push_back("*"); src.push_back("/"); src.push_back("("); src.push_back(")"); des.push_back(" + "); des.push_back(" - "); des.push_back(" * "); des.push_back(" / "); des.push_back(" ( "); des.push_back(" ) "); } int main() { map<string, int> ops; init_op(ops); vector<string> postf; vector<string> src, des; init_src_des(src, des); while (1) { get_postfix(postf, src, des); bool leg = true; int ill_id = 0; double ret = cal_post(postf, ops, leg, ill_id); if (leg) { cout << ret << endl << endl; } else { cout << "Illegal: " << ill_id << "!" << endl << endl; } } system("PAUSE"); return 0; }