• 检测后缀表达式的合法性


    检测后缀表达式的合法性

             前面我们介绍了《后缀表达式的计算》,具体做法在于设置一个数据结构:操作数栈,基于操作数栈根据操作符进行弹栈、运算、压栈等操作,最终计算而得后缀表达式的结果。

             我们默认处理的后缀表达式都是合法的,对于非法的后缀表达式,我们并没有给出适当的处理。这里我们将在后缀表达式的计算过程中,同时检测后缀表达式是否合法,如果合法则计算到底,最终得到后缀表达式的值;如果非法,则返回该后缀表达式为非法。

             比如有后缀表达式:

             2 + 3 *

             该后缀表达式是非法的,因为+操作符只有一个操作数2;

             又如:

           1 3 5 * + 7 / -

             该后缀表达式的/操作符只有一个操作数7,所以也是非法的;

                    1 3 + 5 7 6 - * 9 /

             该后缀表达式中操作数多了一个,导致其非法。

             具体的算法逻辑为:

    Wikipedia

             在计算后缀表达式过程中,如果操作数栈中无法提供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;
    }

  • 相关阅读:
    英语口语——英语连读、发音、英文音标、语调、语气、节奏等等
    高中语法_句法篇——名词性从句、定语从句、状语从句、被动语态、虚拟语气、倒装句
    高中语法_时态篇——笔记 -五大基本句型,十大单词类型、常用时态。
    《数据结构》 第一章 笔记
    《计算机网络》 第三章 数据链路层
    《计算机网络》第二章 物理层笔记
    《计算机网络》谢希仁版--第一章习题
    我个人的c#入门总结【勿入】
    排序算法总结
    C#基础知识点总结
  • 原文地址:https://www.cnblogs.com/unixfy/p/3229063.html
Copyright © 2020-2023  润新知