c++实现中缀表达式 转换为后缀表达式

使用栈来计算后缀表达式的值:

9+(3 - 1)*3+10/2;

后缀表达式:所有的符号都是在运算数字的后面出现: 9 3 1 – 3 * + 10  2 / +

规则:

中缀表达式转后缀表达式:

1.从左到右遍历中缀表达式的每个数字和符号,若是数字就打印同时入栈数字栈snum;

2.若是左括号,则将其压入运算符栈sope中;

3.若是右括号,则将sope栈顶的运算符弹出并打印,直到遇到左括号(左括号也出栈,但不输出打印);

4.若是运算符,若该运算符的优先级大于栈顶运算符的优先级时,则把它压栈;若小于或等于栈顶运算符优先级时,则将栈顶运算符弹出并打印, 同时出栈snum数字按照此运算符运算后结果入栈,再比较新的栈顶运算符,按同样方法处理,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈;

5.若中缀表达式中的各对象处理完毕,则把sope栈中存留的运算符依次弹栈输出打印, 同时取snum中的值按照此运算符运算后的结果入栈,直至sope栈空 。snum栈底元素出栈即为计算结果。

 计算规则:

  • 创建一个双精度数字栈 snum 来存储操作数。Copy
  • 使用 stringstream 将输入字符串 postfix 便于逐个提取 token。
  • 使用 while (ss >> token) 循环来逐个读取 token,直到字符串流结束。每次读取都会跳过空格。
  • 如果 token 的第一个字符是数字(使用 isdigit 函数判断),则将这个 token 转换为 double 类型并推入栈中。
  • 如果 token 不是数字,说明它是一个操作符。
  • 从栈中弹出两个元素(x 和 y),注意:弹出顺序是后进先出(LIFO),所以首先弹出的将是最近进入栈的数字
  • 根据操作符执行相应的数学运算,并将计算结果压入栈中。
  • 针对除法,还需检查除数 y 是否为零,如果是,则抛出异常以避免除以零错误。
  • 最后,函数返回栈顶元素,这个值是后缀表达式的计算结果.

完整代码: 

 

#include <iostream>
#include <string>
#include <exception>
#include <sstream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
bool isvalidexpression(const string & expression)
{
    for (char ch : expression)
    {
        if (!isdigit(ch) && ch != '+' && ch != '-' && ch != '*' && ch != '/' && ch != ' ')
        {
            return false;
        }
    }
    return true;
}

int precedence(char ch)
{
    switch (ch)
    {
    case '+':
    case'-':
        return 1;
    case '*':
    case '/':
        return 2;
    default:
        return 0;

    }
}

string infixtopostfix(const string& expression)
{
    stack<char> sope;//字符栈
    string postfix = "";//后缀表达式
    string numbuff = "";
    for (size_t i = 0; i < expression.length(); i++)
    {
        char ch = expression[i];
        if (isdigit(ch))
        {
            numbuff += ch;
        }
        else
        {
            if (!numbuff.empty())
            {
                postfix += numbuff;
                postfix += ' ';
                numbuff.clear();
            }


            if (ch == '(')
            {
                sope.push(ch);
            }
            else if (ch == ')')
            {
                while (!sope.empty() && sope.top() != '(')
                {
                    postfix += sope.top();
                    postfix += ' ';
                    sope.pop();
                }
                sope.pop();//出栈'('
            }
            else
            {
                while (!sope.empty() && precedence(sope.top()) >= precedence(ch))
                {
                    postfix += sope.top();
                    postfix += ' ';
                    sope.pop();
                }
                sope.push(ch);
            }
        }
    }
    if (!numbuff.empty())
    {
        postfix += numbuff;
        postfix += ' ';
    }
    while (!sope.empty())
    {
        postfix += sope.top();
        postfix += ' ';
        sope.pop();
    }

    if (!postfix.empty() && postfix.back() == ' ')
    {
        postfix.pop_back();
    }
    return postfix;

}

double evaluatepostfix(const string& postfix)
{
    stack<double>snum;//数字栈
    stringstream ss(postfix);
    string token;
    while (ss >> token)
    {
        if (isdigit(token[0]))
        {
     snum.push(stod(token));//stod 是一个函数,用于将字符串转换为 double 类型的浮点数。
        }
        else
        {
            double x = snum.top(); snum.pop();
            double y = snum.top(); snum.pop();
            switch (token[0])
            {
            case '+':snum.push(x + y); break;
            case'-':snum.push(x - y); break;
            case '*':snum.push(x * y); break;
            case '/':if (y != 0)
            {
                snum.push(x / y);
            }
                    else
            {
                throw runtime_error("Error:Division By Zero");
            }
                    break;
                
            }
        }
    }

    return snum.top();


}

int main()
{
    //输入一个表达式
    string expression;
    cout << "请输入一个算数表达式:(例如2*3*(4+5))" << endl;
    getline(cin , expression);

    //检测有效性
    if (!isvalidexpression(expression))
    {
        cout << "表达式不合法" << endl;
    }
    //将中缀表达式转换为后缀表达式
    string postfix = infixtopostfix(expression);
    cout << "后缀表达式是:"<<postfix << endl;

    //计算后缀表达式的值
    
    try
    {
        double result = evaluatepostfix(postfix);
        cout << "后缀表达式的结果为:" << result << endl;
     }
    catch (runtime_error& e)
    {
        cout << e.what() << endl;
    }

    system("pause");
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/16902.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

逆向攻防世界CTF系列33-流浪者

逆向攻防世界CTF系列33-流浪者 shiftf12看到pass&#xff0c;跟进 是个输入的处理&#xff0c;其实很简单&#xff0c;看不懂也没关系&#xff0c;先看看return 这里strcmp成功后return的就是成功 最后要为KanXueCTF2019JustForhappy while ( *(_DWORD *)(a1 4 * v4) < 0x…

算法--解决二叉树遍历问题

第一 实现树的结构 class Node(): # 构造函数&#xff0c;初始化节点对象&#xff0c;包含数据和左右子节点 def __init__(self, dataNone): self.data data # 节点存储的数据 self.left None # 左子节点&#xff0c;默认为None self.rig…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

游戏引擎学习第12天

视频参考:https://www.bilibili.com/video/BV1yom9YnEWY 这节没讲什么东西&#xff0c;主要是改了一下音频的代码 后面有介绍一些alloc 和malloc,VirtualAlloc 的东西 _alloca 函数&#xff08;或 alloca&#xff09;分配的是栈内存&#xff0c;它的特点是&#xff1a; 生命周…

Linux-软件管理-本地仓库和网络资源仓库配置(RHCSA)

该章节的目录如下&#xff1a; 认识rpm包 将设备挂载到/mnt上面 查看光驱上的相关信息 使用rpm包管理软件 仓库的配置(重要) 无相关文件 本地仓库配置&#xff08;书写相关的仓库文件&#xff09; 配置流程 效果测试&#xff08;安装卸载&#xff09; 查看仓库 清理…

【arxiv‘24】Vision-Language Navigation with Continual Learning

论文信息 题目&#xff1a;Vision-Language Navigation with Continual Learning 视觉-语言导航与持续学习 作者&#xff1a;Zhiyuan Li, Yanfeng Lv, Ziqin Tu, Di Shang, Hong Qiao 论文创新点 VLNCL范式&#xff1a;这是一个新颖的框架&#xff0c;它使得智能体能够在适…

数字化建设:指标如何驱动的企业KPI设计?

我们以KPI设定为例&#xff0c;简单说明在一套科学的经营分析体系的加持下&#xff0c;企业的经营KPI应该如何设定&#xff0c;如图所示。 指标驱动的企业KPI设计 每年年初企业做战略规划的同时&#xff0c;会启动年度业务KPI的设定。这个时候经营分析团队会主导整个过程。首先…

初级数据结构——栈题库(c++)

目录 前言1.杭电oj——Bitset2.杭电oj——进制转换[3.力扣——LCR 123. 图书整理 I](https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/description/)[4.力扣——LCR 027. 回文链表](https://leetcode.cn/problems/aMhZSa/)[5.力扣——1614. 括号的最大嵌…

数字化转型企业架构设计手册(交付版),企业数字化转型建设思路、本质、数字化架构、数字化规划蓝图(PPT原件获取)

1、企业架构现状分析 2、企业架构内容框架 3、企业架构设计方法 3.1 、业务架构设计方法 3.2 、数据架构设计方法 3.3 、应用架构设计方法 3.4 、技术架构设计方法 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&…

⾃动化运维利器Ansible-基础

Ansible基础 一、工作原理二、快速入门2.1 测试所有资产的网络连通性2.2 发布文件到被管理节点(资产) 三、资产(被管理节点)3.1 静态资产3.1.1 自定义资产3.1.2 自定义资产的使用3.1.3 资产选择器 四、Ansible Ad-Hoc 命令4.1 模块类型4.1.1 command & shell 模块4.1.2 cop…

鸿蒙NEXT自定义组件:太极Loading

【引言】&#xff08;完整代码在最后面&#xff09; 本文将介绍如何在鸿蒙NEXT中创建一个自定义的“太极Loading”组件&#xff0c;为你的应用增添独特的视觉效果。 【环境准备】 电脑系统&#xff1a;windows 10 开发工具&#xff1a;DevEco Studio NEXT Beta1 Build Vers…

AVL树了解并简单实现

这篇文章默认知道二叉搜索树&#xff0c;如果了解并不多可以先看看二叉搜索树了解和实现-CSDN博客 目录 1.AVL树概念 2.AVL树节点定义 3.AVL树的插入&#xff08;重点&#xff09; 3.1AVL树 3.2AVL树的旋转 3.3AVL树插入代码 4.AVL树的验证 5.AVL树的删除 6.AVL树的性能…

【MySQL】索引原理及操作

目录 索引原理 初识索引 磁盘原理 磁盘与系统之间的关系 MySQL、系统、磁盘之间的关系 理解索引 页目录 页目录设计的数据结构问题 聚簇索引与非聚簇索引 遗留问题 索引操作 创建索引 查询索引 删除索引 其他索引概念与操作 索引原理 索引&#xff08;I…

代码随想录算法训练营第三十一天| 56. 合并区间 、738.单调递增的数字 。c++转java

56. 合并区间 class Solution {public int[][] merge(int[][] intervals) {//对区间按照右边界排序Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));List<int[]> p new LinkedList<>();int l intervals[0][0],r intervals[0][1];for(int i 1;i…

厦大南洋理工最新开源,一种面向户外场景的特征-几何一致性无监督点云配准方法

导读 本文提出了INTEGER&#xff0c;一种面向户外点云数据的无监督配准方法&#xff0c;通过整合高层上下文和低层几何特征信息来生成更可靠的伪标签。该方法基于教师-学生框架&#xff0c;创新性地引入特征-几何一致性挖掘&#xff08;FGCM&#xff09;模块以提高伪标签的准确…

模型运行速度笔记: s/epoch VS s/iter

1 概念介绍 在模型训练中&#xff1a; s/epoch 表示每个epoch所需的秒数&#xff0c;即完成一轮完整数据集训练的时间。s/iter 表示每个iteration&#xff08;迭代&#xff09;所需的秒数&#xff0c;即处理一个batch的时间。 它们的关系是&#xff1a; 2 举例 比如我tra…

k8s 中传递参数给docker容器

文章目录 docker启动时传递参数使用k8s env传递完全覆盖 ENTRYPOINT 和 CMD 在 Kubernetes 中&#xff0c;可以通过多种方式将参数传递给 Dockerfile 或其运行的容器&#xff0c;常见的方式包括使用环境变量、命令行参数、配置文件等。以下是一些常用的方法&#xff1a; docker…

Map Set

在学习TreeMap和TreeSet之前需要先学习有关搜索树的相关知识以及接口Map和Set。 1. 搜索树 1.1 概念 二叉搜索树又称二叉排序树&#xff0c;其特点是&#xff0c;该节点的左边都比其小&#xff0c;右边都比其大&#xff0c;每一棵子树都必须满足这个条件。如下图所示例子。2…

Android OpenGLES2.0开发(八):Camera预览

严以律己&#xff0c;宽以待人 引言 终于到该章节了&#xff0c;还记得Android OpenGLES2.0开发&#xff08;一&#xff09;&#xff1a;艰难的开始章节说的吗&#xff1f;写这个系列的初衷就是因为每次用到GLSurfaceViewCamera预览时&#xff0c;总是CtrlC、CtrlV从来没有研究…

基础 IO

目录 一、基本共识 二、复习C语言中的文件操作 三、与文件操作有关的系统调用接口 1. open 与 close 1.1 umask 2. write 3. read 四、如何理解文件 1. 文件描述符 fd 2. 文件fd分配规则 3. 重定向的引入 4. 重定向的本质 5. dup2 6. 理解 >、>>、…