检测后缀表达式的合法性

检测后缀表达式的合法性

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

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

         比如有后缀表达式:

         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;
}

原文地址:https://www.cnblogs.com/unixfy/p/3229063.html