逻辑运算&&、!、||、>、>=、<、<=、==、(、)中缀表达式转后缀表达式(逆波兰表达式子)

这是一个C++实现的中缀逻辑运算表达式转后缀表达式并进行计算的程序。代码包括了从字符串中获取数字、布尔值和运算符的函数,以及中缀转后缀和后缀计算的算法。程序能够处理包括等于、不等于、小于、大于、小于等于、大于等于、与、或等逻辑运算符。
摘要由CSDN通过智能技术生成

背景

网上找了一圈没有现成的逻辑运算的中缀表达式转后缀表达式,全是四则运算的,自己写一下。

代码


#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<sstream>
#include <iostream>
using namespace std;


enum NodeType
{

    TypeDIGIT,//数字
    TypeBOOLEN,//bool
    TypeOP//运算符
};
struct Node{
    std::string content;//
    NodeType type;
};

typedef struct Node node;

class Parser
{
private:

    //设置优先级(注意默认操作数的优先级最高,即其不需要进栈,进栈的都是运算符)
    map<std::string, int> p;

    //获得从 str 的index位置获得 bool 字符串
    bool getBool(const std::string& str,int index,std::string&bl)
    {
        bl.clear();
        if(index+4>str.length())
        {
            return  false;
        }
        bl=str.substr(index,4);
        if(bl=="true")
        {
            return true;
        }

        if(index+5>str.length())
        {
            return  false;
        }
        bl=str.substr(index,5);
        if(bl=="false")
        {
            return true;
        }
        return false;


    }
    //获得从 str 的index位置获得 数字 字符串
    bool getDigit(const std::string& str,int index,std::string&digit)
    {
        digit.clear();
        while(index<str.size()&&isDigit(str[index]))
        {
            digit+=str[index];
            index++;
        }
        if(digit.empty())
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    //获得从 str 的index位置获得 操作符 字符串
    bool getOp(const std::string& str,int index,std::string&op)
    {
        char current_char=str[index];

        if (current_char == '=') {

            char next_char=str.size()>(index+1)?str[index+1]:0;
            if(next_char == '=')
            {
                op="==";
            }else
            {
                return false;
            }

        }
        if (current_char == '!') {

            char next_char=str.size()>(index+1)?str[index+1]:0;
            if(next_char == '=')
            {
                op="!=";
            }

            else
            {
                op="!";
            }
        }
        if (current_char == '<') {
            char next_char=str.size()>(index+1)?str[index+1]:0;
            if(next_char == '=')
            {
                op="<=";
            }

            else
            {
                op="<";
            }
        }
        if (current_char == '>') {
            char next_char=str.size()>(index+1)?str[index+1]:0;
            if(next_char == '=')
            {
                op="<=";
            }

            else
            {
                op=">";
            }

        }
        if (current_char == '&') {
            char next_char=str.size()>(index+1)?str[index+1]:0;
            if(next_char == '&')
            {
                op="&&";
            }

            else
            {
                return false;
            }
        }
        if (current_char == '|') {
            char next_char=str.size()>(index+1)?str[index+1]:0;
            if(next_char == '|')
            {
                op="||";
            }

            else
            {
                return false;
            }
        }
        return  true;

    }

    bool calcEQ(const std::string &a,const  std::string & b)
    {
        return std::stoi(a)==std::stoi(b);
    }
    bool calcNE(const std::string &a,const  std::string & b)
    {
        return std::stoi(a)!=std::stoi(b);
    }

    bool calcLT(const std::string &a,const  std::string & b)
    {
        return std::stoi(a)<std::stoi(b);
    }
    bool calcGT(const std::string &a,const  std::string & b)
    {
        return std::stoi(a)>std::stoi(b);
    }
    bool calcLE(const std::string &a,const  std::string & b)
    {
        return std::stoi(a)<=std::stoi(b);
    }
    bool calcGE(const std::string &a,const  std::string & b)
    {
        return std::stoi(a)>=std::stoi(b);
    }
    bool toBool(const  std::string & b)
    {
        bool v;
        std::istringstream(b) >> std::boolalpha >> v;
        return v;
    }
    bool calcNOT(const  std::string & b)
    {
        return !toBool(b);
    }
    std::string toString(bool b)
    {
        if(b)
        {
            return "true";
        }else
        {
            return "false";
        }

    }
    bool isDigit(char c) {

        if (c >= '0' && c <= '9')
            return true;
        return false;
    }
public:
    Parser()
    {
        p["&&"] = p["||"] = 1;//通过hashmap赋值
        p[">"] = p[">="]=p["<"] = p["<="]=p["=="] = p["!="] = 2;//通过hashmap赋值
        p["!"] = 3;//通过hashmap赋值
    }

    /*
    中缀转后缀C++代码实现(比较方便)
    1.遇到操作数:添加到后缀表达式中或直接输出
    2.栈空时:遇到运算符,直接入栈
    3.遇到左括号:将其入栈
    4.遇到右括号:执行出栈操作,输出到后缀表达式,直到弹出的是左括号
    注意:左括号不输出到后缀表达式
    5.遇到其他运算符:弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;栈顶左括号,将该运算符入栈
    6.将栈中剩余内容依次弹出后缀表达式
    */
    queue<node> change(const std::string& str){
        stack<node> s;//操作符栈
        queue<node> q;//后缀表达式队列
        string var;
        for (int i = 0; i < str.length();){
            if (str[i] == '('){//3.遇到左括号:将其入栈
                node temp;
                temp.type = TypeOP;
                temp.content = str[i];
                s.push(temp);
                i++;
            }
            else if (str[i] == ')'){//4.遇到右括号:执行出栈操作,输出到后缀表达式,直到弹出的是左括号
                while (!s.empty() && s.top().content != "("){
                    q.push(s.top());
                    s.pop();
                }
                s.pop();//弹出左括号
                i++;
            }
            else if (getDigit(str,i,var)){
                //如果是数字
                node temp;
                temp.type = TypeDIGIT;
                temp.content = var ;

                i+=var.length();
                q.push(temp);//操作数进入后缀表达式
            }
            else if (getBool(str,i,var)){
                //如果是
                node temp;
                temp.type = TypeBOOLEN;
                temp.content = var ;

                i+=var.length();
                q.push(temp);//操作数进入后缀表达式
            }
            else if(getOp(str,i,var)){
                //如果是操作符
                //5.遇到其他运算符:弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;栈顶左括号,将该运算符入栈
                node temp;
                temp.type = TypeOP;

                if(s.size()==0||s.top().content=="(")
                {

                }
                else{

                    while (!s.empty() && p[s.top().content] >= p[var]){
                        q.push(s.top());
                        s.pop();
                    }
                }

                temp.content = var;
                s.push(temp);
                i+=var.length();
            }else
            {
                return q;
            }
        }
        //6.将栈中剩余内容依次弹出后缀表达式
        while (!s.empty()){
            q.push(s.top());
            s.pop();
        }
        return  q;
    }


    //*************************************************************
    //后缀表达式的计算
    /*
    从左到右扫描后缀表达式
    1)若是操作数,就压栈,
    2)若是操作符,就连续弹出两个操组数
    3)栈顶的值即为所需结果
    注:先弹出的是第一操作数,后弹出的是第二操作数
    */
    bool  calculate( queue<node>& q ){
        stack<node> s1;//存放操作数的,为了计算后缀表达式的值
        node cur, temp;
        while (!q.empty()){//后缀队列非空
            cur = q.front();//记录队首元素
            q.pop();
            if (cur.type == TypeBOOLEN||cur.type ==TypeDIGIT){//是操作数进入栈
                s1.push(cur);
            }
            else{//是操作符就运算
                std::string var_a,var_b;
                if(cur.content == "!")
                {
                    var_b =s1.top().content;

                    s1.pop();//弹出第二操作数
                    temp.type = TypeBOOLEN;

                    temp.content=toString(!toBool(var_b));

                }else
                {
                    var_b =s1.top().content;
                    s1.pop();//弹出第二操作数
                    var_a = s1.top().content;
                    s1.pop();//弹出第一操作数
                    temp.type = TypeBOOLEN;
                    if (cur.content == "=="){
                        temp.content = toString(calcEQ(var_a , var_b));
                    }
                    else if (cur.content == "!="){
                        temp.content = toString(calcNE(var_a , var_b));
                    }
                    else if (cur.content == "<="){
                        temp.content = toString(calcLE(var_a , var_b));
                    }
                    else if (cur.content == "<"){
                        temp.content = toString(calcLT(var_a , var_b));
                    }else if (cur.content == ">="){
                        temp.content = toString(calcGE(var_a , var_b));
                    }
                    else if (cur.content == ">"){
                        temp.content = toString(calcGT(var_a , var_b));
                    }
                    else if (cur.content == "&&"){
                        temp.content = toString(toBool( var_a) && toBool(var_b));
                    }
                    else if (cur.content == "||"){
                        temp.content = toString(toBool(var_a) || toBool(var_b));
                    }

                }
                s1.push(temp);//把计算后的结果再次压栈
            }

        }

        return toBool(s1.top().content);

    }
    //*************************************************************
};

int main()
{
    Parser p;
    //queue<Node> q=p.change("!false");
    queue<Node> q=p.change("12<23&&!(11>22||13<12)");
    bool answer=p.calculate(q);
    cout << answer<<endl;
    return 0;
}

参考

https://blog.csdn.net/qq_36144258/article/details/95075064
https://blog.csdn.net/Coder_Dacyuan/article/details/79941743

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值