表达式求值和转换

这篇具有很好参考价值的文章主要介绍了表达式求值和转换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#include<iostream>
using namespace std;
#include<string>
#include<cmath>
#include<algorithm>
#include<stack>
#include<unordered_map>

const int maxn = 100020;

stack<double>num;          //数字栈
stack<char>op;          //运算符栈

void eval()                   //用于中缀表达式计算
{
    auto b = num.top();             //考虑运算顺序,先取出来的是第二个运算数
    num.pop();
    auto a = num.top();
    num.pop();

    auto c = op.top();
    op.pop();
    double x = 0;
    if (c == '+')x = a + b;
    else if (c == '-')x = a - b;
    else if (c == '*')x = a * b;
    else x = a / b;
    num.push(x);
}    

bool eval_(char c)                  //用于后缀表达式
{
    auto b = num.top();             //考虑运算顺序,先取出来的是第二个运算数
    num.pop();
    auto a = num.top();
    num.pop();

    int x = 0;
    if (c == '+')x = a + b;
    else if (c == '-')x = a - b;
    else if (c == '*')x = a * b;
    else {
        if (b == 0)
        {
            cout << "Error: " << a << "/0";
            return false;
        }
        x = a / b;

    }
    num.push(x);
    return true;
}

//中缀表达式求值函数

void  evalmerge(string str)
{
    
   
    unordered_map<char, int>pr{ {'+',1},{'-',1},{'*',2},{'/',2} };     //定义一个哈希表,存储优先级

    for (int i = 0; i < str.size(); i++)
    {
        auto c = str[i];
        if (isdigit(c)||c=='-'&&(i==0||str[i-1]=='('))
        {
            int flag = 1, xiaoshuwei = 1;
            double x = c - '0', j = i + 1;
            if (c == '-')
            {
                x = 0;
            }
            while (j < str.size() && (isdigit(str[j])||str[j]=='.'))
            {
                if (str[j] == '.')
                {
                    flag = 0;            //说明是小数了
                    j++;
                    continue;
                }
                if (!flag)                //小数部分
                {
                  
                    x =x+ (1.0*(str[j] - '0'))/pow(10, xiaoshuwei);
                    xiaoshuwei++;
                    j++;
                }
                else
                {
                    x = x * 10 + str[j++] - '0';            //这里的j是要自增的
                }
                
            }
            i = j - 1;                 //别忘记了更新i
            if (c == '-')
            {
                x = -x;
            }
            num.push(x);
        }//取出数字
        else if (c == '+' && (i == 0 || str[i - 1] == '('))
        {
            continue;
        }
        else if (c == '(')  //如果是左括号,入栈即可
        {
            op.push(c);
        }
        else if (c == ')')   //如果是右括号,就意味着我们应该把目前栈里面的运算符都计算完
            //并且我们知道,遇到优先级比当前栈顶优先级低的运算符,我们就会先把栈顶运算符操作完
            //那么,还留在栈里面的操作符都是优先级递增的,所以要从右往左算
        {
            while (op.top() != '(') eval();        //一直计算完整个括号
            op.pop();                         //弹出左括号
        }
        else             //一般情况 
        {
            while (op.size() && pr[op.top()] >= pr[c])//符号栈没空,并且栈顶的运算符优先级大于当前运算符
            {
                eval(); //操作栈顶的运算符
                
               
            }
            op.push(c); //新的运算符压入栈

        }
    }

    while (op.size())   //把最后剩下的运算符操作完
    {
        eval();
    }
    cout << num.top();
}

//后缀表达式求值函数,以#结尾,每个字符用空格隔开 负数粘在一起
void evallast(string str)
{


    for (int i = 0; i < str.size() - 1; i++)
    {
        auto c = str[i];

        if (isdigit(c) || (c == '-' && i + 1 < str.size() - 1 && str[i + 1] != ' '))
        {
            int x = c - '0', j = i + 1;
            if (c == '-')
            {
                x = 0;
            }
            while (j < str.size() - 1 && isdigit(str[j]))
            {
                x = x * 10 + str[j++] - '0';            //这里的j是要自增的
            }
            i = j - 1;                 //别忘记了更新i
            if (c == '-')
            {
                x = -x;
            }
            num.push(x);
        }//取出数字
      
        else if (c != ' ')
        {
            if (num.size() < 2)
            {
                cout << "Expression Error: " << num.top();
                return;

            }
            else
            {
                bool flag = eval_(c);
                if (!flag)
                {
                    return;
                }
            }
        }
    }
    if (num.size() == 1)
        cout << num.top();
    else
    {
        if (num.size() > 1)
        {
            cout << "Expression Error: " << num.top();
        }
    }
   


}

//中缀转后缀
string transe(string str)           
{
    string ans;                           //存储结果表达式

    stack<int>shu;
    stack<char>fu;

    unordered_map<char, int>pr{ {'+',1},{'-',1},{'*',2},{'/',2} };     //定义一个哈希表,存储优先级

    for (int i = 0; i < str.size(); i++)
    {
        auto c = str[i];
        if (isdigit(c) || c == '-' && (i == 0 || str[i - 1] == '('))
        {
            string temp;
            temp += c;
            int x = c - '0', j = i + 1;
           
            while (j < str.size() && (isdigit(str[j]) || str[j] == '.'))
            {
                temp += str[j];
                j++;
                
            }
            i = j - 1;                 //别忘记了更新i
            
            ans += temp;                //直接放到结果表达式中
            ans += " ";
        }//取出数字
        else if (c == '+' && (i == 0 || str[i - 1] == '('))
        {
            continue;

        }
        else if (c == '(')  //如果是左括号,入栈即可
        {
            fu.push(c);
        }
        else if (c == ')')   //如果是右括号,就意味着我们应该把目前栈里面的运算符都计算完
            //并且我们知道,遇到优先级比当前栈顶优先级低的运算符,我们就会先把栈顶运算符操作完
            //那么,还留在栈里面的操作符都是优先级递增的,所以要从右往左算
        {
            while (fu.top() != '(')
            {
                auto tempfu = fu.top();
                fu.pop();
                ans += tempfu;
                ans += " ";

            }
            fu.pop();                         //弹出左括号
        }
        else             //一般情况 
        {
            while (fu.size() && pr[fu.top()] >= pr[c])//符号栈没空,并且栈顶的运算符优先级大于当前运算符
            {
                auto temp = fu.top();
                fu.pop();
                ans += temp;
                ans += " ";


            }
            fu.push(c); //新的运算符压入栈

        }
    }
    while (fu.size())   //把最后剩下的运算符操作完
    {
        auto temp = fu.top();
        fu.pop();
        ans += temp;
        ans += " ";
    }
    ans += '#';
    return ans;


}


int main()
{
    string s;
    cin >> s;
    evalmerge(s);
    cout << endl;

    while (!num.empty())
    {
        num.pop();
    }
    while (!op.empty())
    {
        op.pop();
    }

    string ss = transe(s);
    cout << ss << endl;
  
  


    return 0;
}

文章来源地址https://www.toymoban.com/news/detail-737560.html

到了这里,关于表达式求值和转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c++表达式求值

    给定一个表达式,其中运算符仅包含 +,-, ,/(加 减 乘 整除),可能包含括号,请你求出表达式的最终值。 注意: 数据保证给定的表达式合法。题目保证符号 - 只作为减号出现,不会作为负号出现,例如,-1+2,(2+2) (-(1+1)+2) 之类表达式均不会出现。题目保表达式中所有数字均

    2024年01月21日
    浏览(36)
  • 栈|逆波兰表达式求值

    逆波兰表达式求值 逆波兰表达式就是后缀表达式,我们平时写的带括号的是中缀表达式。区分中缀表达式和后缀表达式 就是 操作数 和 操作符 的先后关系。 操作符在后 就是后缀表达式 后缀表达式 的用途就是 让计算机直到计算的先后顺序! 比如 我们中缀表达式 a * (b -

    2024年04月11日
    浏览(47)
  • C++ 数据结构 栈 中缀表达式转后缀表达式并求值

    写在前面,这里用的是我自己写的Stack类,并非STL,实现方法为静态数组,但使用过程中的函数方法一样,无伤大雅。(完整code和Stack_static类赋在最后) 1.从左到右遍历 2.数,即参与运算数,直接放进后缀表达式之后 3.左括号 ,直接压入栈(因为括号的优先级最高,无需判断

    2024年02月03日
    浏览(46)
  • 数据结构之表达式求值

     前言 运用堆栈解决表达式的求值,代码思路为: 1.定义两个栈,一个char类型的栈用于存放运算符(ysf)一个int类型的栈用于存放操作数(czs) 如一个表达式3+6*9,将“+”,“*”入ysf栈,将“3”“6”“9”入czs栈 2.运用getchar进行数据的录入,如果接收的是运算符,将其插入到运

    2024年04月29日
    浏览(34)
  • 中缀表达式求值(栈的应用)

    AcWing算法基础课-3302.表达式求值 给定一个表达式,其中运算符仅包含 +,-,*,/ (加 减 乘 整除),可能包含括号,请你求出表达式的最终值。 注意: 数据保证给定的表达式合法。 题目保证符号 - 只作为减号出现,不会作为负号出现,例如, -1+2 , (2+2)*(-(1+1)+2) 之类表达式均不

    2024年02月05日
    浏览(53)
  • 数据结构 实验2——表达式求值

    一、实验名称:表达式求值 二、实验学时: 6 学时 三、实验目的 1.理解栈的结构特点和基本操作特性; 2.掌握利用栈实现表达式求值算法。 四、实验内容 ( 步骤 ) 输入一个算术表达式(以“=”结束),求其值。要求表达式以“=”结束,操作数为多位实数,对错误表达式要进行

    2023年04月08日
    浏览(38)
  • 【数据结构】12 堆栈应用:表达式求值

    有一个常量表达式的中缀表达式为:5 + 6 / 2 - 3 * 4,其后缀形式表示为: 5 6 2 / + 3 4 × -。后缀表达式的特点是运算符位于两个预算数之后。其前缀表达式为: - + 5 / 6 2 × 3 4。 后缀表达式相比于中缀表达式的求值要容易很多。 从左到右扫描该表达式: (1)遇见运算数5 6 2时不

    2024年02月20日
    浏览(53)
  • 数据结构 | 栈的中缀表达式求值

    目录 什么是栈? 栈的基本操作 入栈操作 出栈操作 取栈顶元素 中缀表达式求值 实现思路 具体代码 栈是一种线性数据结构,具有“先进后出”(Last In First Out, LIFO)的特点。它可以看作是一种受限的线性表,只能在表的一端进行插入和删除操作,这一端被称为栈顶,另一端

    2024年02月02日
    浏览(54)
  • LeetCode:150. 逆波兰表达式求值—栈

    🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀 算法专栏: 👉🏻123 题目描述 :给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 来源:力扣(LeetCode) 难度: 简单 提示:

    2023年04月16日
    浏览(55)
  • 『力扣刷题本』:逆波兰表达式求值

    大家好久不昂,最近 1 个多月罗根一直在备考期末,文章发的很少。 现在已经放寒假啦,学习自然也不能拉下,毕竟 4 月份就要去参加蓝桥杯了。 先给自己定个小目标,日更 2 篇! 咳咳,下面马上开始讲题👇 给你一个字符串数组  tokens  ,表示一个根据 逆波兰表示法 表

    2024年01月16日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包