!勘误!之前中缀转后缀的一处错误
之前我们在中缀转后缀的处理过程中对于当操作符为”)”的时候,对操作符栈进行弹栈操作,当操作符栈的top()值为”(”,我们将其从操作符栈中进行弹出,但是并没有终止,而是继续弹栈,这是一个严重的错误。比如对于表达式:
4 - ( 3 + 2 ) / ( 3 - 1 )
我们按照之前的做法得到的结果为:
0.5
但是,正确的结果应该为
1.5
具体错误出现在:
我们在当if (op_st.top() == “(”) po_st.pop() 后没有结束while循环,从而导致操作符内所有的操作符都弹栈。
具体的修改方法是在op_st.pop()后面添加一个break;语句。
修改后的程序如下:
// 添加break;语句 #include <iostream> #include <sstream> #include <vector> #include <string> #include <stack> #include <map> 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_infix(vector<string>& inf, const vector<string>& src, const vector<string>& des) { inf.clear(); string line; getline(cin, line); n_replace(line, src, des); istringstream sin(line); string tmp; while (sin >> tmp) { inf.push_back(tmp); } } void show(const vector<string>& hs) { for (vector<string>::size_type i = 0; i != hs.size(); ++i) { cout << hs[i] << ' '; } cout << endl; } 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; } } void in2post(const vector<string>& inf, vector<string>& postf, map<string, int>& ops) { postf.clear(); stack<string> op_st; for (vector<string>::size_type i = 0; i != inf.size(); ++i) { if (!is_operator(inf[i], ops)) { postf.push_back(inf[i]); } else { if (inf[i] == "(") { op_st.push(inf[i]); } else if (inf[i] == ")") { while (!op_st.empty()) { if (op_st.top() == "(") { op_st.pop(); // !勘误! // 如果inf[i] == ")",当遇到"(",将"("弹栈后必须终止弹栈循环。 break; } else { postf.push_back(op_st.top()); op_st.pop(); } } } else // 若为其他运算符 { if (op_st.empty()) // 若为空栈,则直接入栈 { op_st.push(inf[i]); } else { if (ops[inf[i]] > ops[op_st.top()]) { // 如果当前操作符优先级高于站定操作符优先级 // 则直接入栈 op_st.push(inf[i]); } else { // 否则弹出栈中优先级大于等于当前操作符优先级 // 的操作符,并最后将当前操作符压栈 while (!op_st.empty() && ops[op_st.top()] >= ops[inf[i]] && op_st.top() != "(") { /* 等价于 && op_st.top != "(" if (op_st.top() == "(") { // 如果当前栈顶操作符为 "(" // 则终止操作,继续保留 "(" 的栈顶位置 break; } */ postf.push_back(op_st.top()); op_st.pop(); } op_st.push(inf[i]); } } } } } while (!op_st.empty()) { postf.push_back(op_st.top()); op_st.pop(); } } double cal_post(const vector<string>& postf, const map<string, int>& ops) { 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 '+': b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a + b; or_st.push(c); break; case '-': b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a - b; or_st.push(c); break; case '*': b = or_st.top(); or_st.pop(); a = or_st.top(); or_st.pop(); c = a * b; or_st.push(c); break; case '/': 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) { return or_st.top(); } else { 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> inf, postf; vector<string> src, des; init_src_des(src, des); while (1) { get_infix(inf, src, des); // show(inf); in2post(inf, postf, ops); show(postf); double ret = cal_post(postf, ops); cout << ret << endl << endl; } system("PAUSE"); return 0; }