程序最美(寻路)

你还在坚持练习你的技术吗?运动员天天训练,音乐家也会演练更难的曲章。你呢?

!勘误!之前中缀转后缀的一处错误

!勘误!之前中缀转后缀的一处错误

         之前我们在中缀转后缀的处理过程中对于当操作符为”)”的时候,对操作符栈进行弹栈操作,当操作符栈的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;
}

posted on 2013-08-01 00:04  unixfy  阅读(268)  评论(0编辑  收藏  举报

导航