《C++ Primer》练习9.52:使用栈实现四则运算

news2024/11/24 3:47:27

在这里插入图片描述

栈可以用来使用四则运算,是一个稍微有点复杂的题目,去学习了一下用栈实现四则运算的原理,用C++实现了一下。首先要把常见的中缀表达式改成后缀表达式,然后通过后缀表达式计算,具体的原理可以参考这位博主的文章:C语言数据结构篇——用栈实现四则运算,在数和运算符之间都加入了空格来进行分隔,方便后续的提取有效数据处理。

代码还有优化的地方,先记录一下吧:

#include <iostream>
#include <string>
#include <stack>
using namespace std;

int getOperatorPriority(char &a)
{
  int res;
  if (a == '(')
    res = 0;
  else if (a == '+' || a == '-')
    res = 1;
  else if (a == '*' || a == '/')
    res = 2;
  else if (a == ')')
    res = 3;

  return res;
}
bool compareOperatorPriority(char &a, char &b)
{
  int a_res = getOperatorPriority(a);
  int b_res = getOperatorPriority(b);
  return a_res >= b_res;
}

string createBackSeq(string &str)
{
  stack<char> sak;
  string str2;
  int seen = 0;
  int p = 0;
  for (int i = 0; i != str.size(); ++i)
  {
    if (isdigit(str[i]))
    {
      str2.append(str.substr(i, 1));
      if ((i + 1 != str.size() && !isdigit(str[i + 1])) || i == str.size() - 1)
        str2.append(" ");
    }

    else
    {
      if (sak.empty())
      {
        if (str[i] == '(')
          seen += 1;
        sak.push(str[i]);
      }
      else if (str[i] == ')')
      {
        if (seen != 0)
        {
          while (sak.top() != '(')
          {
            str2 += sak.top();
            str2.append(" ");
            sak.pop();
          }
          sak.pop();
          seen--;
        }
        else
          throw std::invalid_argument("No left bracket match!");
      }
      else
      {
        if (compareOperatorPriority(sak.top(), str[i]))
        {
          if (str[i] == '(')
          {
            seen++;
            sak.push(str[i]);
          }

          else
          {
            str2 += sak.top();
            str2.append(" ");
            sak.pop();
            sak.push(str[i]);
          }
        }
        else
        {
          sak.push(str[i]);
        }
      }
    }
  }
  while (!sak.empty())
  {
    if (seen != 0)
      throw invalid_argument("too many left barckets!");
    str2 += sak.top();
    str2.append(" ");
    sak.pop();
  }
  return str2;
}

int calculate(string &str)
{
  size_t pos1 = 0;
  size_t pos2 = 0;
  stack<int> b;
  while (pos2 != string::npos)
  {
    pos1 = str.find_first_not_of(' ', pos1);
    pos2 = str.find_first_of(' ', pos2);

    if (pos2 != string::npos)
    {
      string temp = str.substr(pos1, pos2 - pos1);
      if (temp.find_first_not_of("0123456789") == string::npos)
        b.push(stoi(temp));
      else
      {
        if (b.size() < 2)
          throw std::invalid_argument("too many symbols");
        int right = b.top();
        b.pop();
        int left = b.top();
        b.pop();
        int res;
        if (temp == "+")
          res = left + right;
        else if (temp == "*")
          res = left * right;
        else if (temp == "-")
          res = left - right;
        else if (temp == "/")
        {
          if (right == 0)
            throw std::invalid_argument("Divided by zero.");
          res = left / right;
        }

        b.push(res);
      }
      pos2 += 1;
      pos1 = pos2;
    }
  }
  return b.top();
}

int main()
{
  string str;
  string str2;
  str = "22*(1+2)-(3*4)/(2*1)";
  str2 = createBackSeq(str);
  cout << str2 << endl;
  cout << calculate(str2) << endl;

  str = "1+3*(2++5)";
  str2 = createBackSeq(str);
  cout << str2 << endl;
  cout << calculate(str2) << endl;	

  return 0;
}

测试:

input : 22*(1+2)-(3*4)/(2*1)
output :
22 1 2 + * 3 4 * 2 1 * / -
60

input : 1+3*(2+5)
output :
1 3 2 5 + * +
22

input : 1+3*((2+5)
output : terminate called after throwing an instance of 'std::invalid_argument' what(): too many left barckets!

input : 1+3*(2+5))
output : terminate called after throwing an instance of 'std::invalid_argument' what(): No left bracket match!

input : 1+3*(2+5)/0
output :
1 3 2 5 + * 0 / +
terminate called after throwing an instance of 'std::invalid_argument' what(): Divided by zero.

input : 1+3*(2++5)
output :
1 3 2 + 5 + * +
terminate called after throwing an instance of 'std::invalid_argument' what(): too many symbols.

参考:

  1. 《C++ Primer》

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

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

相关文章

本、硕、博区别真的辣么大吗?

61&#xff1a; 发际线已经说明了一切…… Super Mario&#xff1a; 小学&#xff0c;老师告诉学生&#xff1a;“森林里有只老虎&#xff0c;已经被我关在笼子里&#xff0c;我会带你去那个地方&#xff0c;然后给你一把猎枪&#xff0c;告诉你猎枪怎么用&#xff0c;并开枪…

RFID拓展的相关问答

基于&#xff1a; Research Reading: Smart Parking Applications Using RFID Technology-CSDN博客这篇文章总结了无线射频识别&#xff08;RFID&#xff09;技术在自动化中的应用及其在停车场管理系统中的解决方案。文章提到&#xff0c;RFID技术在自动化中可以降低交易成本&…

4. redis排名系统之C++实战操作对比MySQL

一、MySQL实现方法 假设我们要设计一款排名系统&#xff0c;那必然要涉及到两大类数据&#xff1a;武器数据和非武器的通用数据&#xff0c;它他通常有一个共用的属性&#xff1a;那就是主键唯一的&#xff0c;例如玩家的数字编号&#xff0c;通常在MySQL中是自增的无符号整数…

【牛客面试必刷TOP101】Day9.BM37 二叉搜索树的最近公共祖先和BM42 用两个栈实现队列

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;牛客面试必刷TOP101 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&…

pycharm安装汉化包失败解决方法

在pycharm -setting-plugins-搜索“Chinese”进入此界面&#xff1a; 点击install&#xff0c;在安装时出现&#xff1a;Plugin "Chinese (Simplified) Language Pack / 中文语言包" was not installed: Invalid filename returned by a server 解决方法&#xff1a…

boot分页

List<ElectricDispatchTodoPO> todoList electricDispatchTodoService.queryTodlList(vo, sysStaffVO);// 计算总记录数int total todoList.size();// 如果总记录数大于0PageInfo<ElectricDispatchTodoPO> pageInfo new PageInfo<>();if (total > 0) {…

手把手教你分析IIS日志——IP访问次数,URI访问统计等

配置IIS网站的日志 下载日志分析工具 https://gitee.com/tangdd369098655/open-network-disk 解压打开 选择文件 指定分析规则&#xff08;还可以自己写规则哦~~&#xff09; 运行规则进行分析 今天就写到这里啦~ 小伙伴们&#xff0c;(&#xffe3;ω&#xffe3;(&#x…

Win10 环境下 VS2022 暴力编译PP-OCRv4

1 环境准备 下载PaddleOCR PaddleOCR C 部署代码位于 PaddleOCR\deploy\cpp_infer目录下 复制cpp_infer目录下include和src到项目目录下paddle_inference paddle_inference opencv 这里使用已经安装好的opencv4.5.5下载dirent-master.zip 下载dirent-master.zip, 解压并复制d…

MyLife - Docker安装Consul

Docker安装Consul 个人觉得像consul之类的基础设施在线上环境直接物理机安装使用可能会好些。但是在开发测试环境用docker容器还是比较方便的。这里学习下docker安装consul使用。 1. Consul 镜像库地址 Consul 镜像库地址&#xff1a;https://hub.docker.com/r/hashicorp/consu…

CleanMyMacX4.12.3最新免费版mac电脑管家

当我们收到一台崭新的mac电脑&#xff0c;第一步肯定是找到一款帮助我们管理电脑运行的“电脑管家”&#xff0c;监控内存运行、智能清理系统垃圾、清理Mac大文件旧文件、消除恶意软件、快速卸载更新软件、隐私保护、监控系统运行状况等。基本在上mac电脑防护一款CleanMyMac就够…

C/C++陷阱——变量名和函数名的冲突问题

C语言/C陷阱——变量名和函数名的冲突问题 先来看这两串代码&#xff1a; 代码一&#xff1a; #include <stdio.h> #include <stdlib.h>int rand 1;int main() {printf("%d\n", rand);return 0; }代码二&#xff1a; #include <stdio.h> #inc…

芯片设计:一颗芯片到底是如何诞生的(上)

目录 芯片设计整体流程 小故事&#xff1a;苹果的芯片设计路 需求分析 架构设计 逻辑设计 前端设计与验证 逻辑综合 DFT&#xff08;可测试性设计&#xff09; 物理实现 小结 芯片设计整体流程 一颗芯片&#xff0c;是如何诞生的呢&#xff1f;其实一颗芯片项目就是…

vue引入jQuery

配置 下载 npm install jquery --save在build的webpack.base.conf中 var webpackrequire("webpack")在module.exports中: plugins: [ //   new webpack.optimize.CommonsChunkPlugin(common.js),new webpack.ProvidePlugin({jQuery: "jquery",$: &quo…

三十五、【进阶】MySQL性能查看

1、基础语法 show global status like Com_______; 2、实际操作 &#xff08;1&#xff09;查看当前数据库sql语句的执行频率 show global status like Com_______; &#xff08;2&#xff09; 执行依次select语句 &#xff08;3&#xff09; 再次查看当前数据库sql语句的执…

GBJ2510-ASEMI电源控制柜专用GBJ2510

编辑&#xff1a;ll GBJ2510-ASEMI电源控制柜专用GBJ2510 型号&#xff1a;GBJ2510 品牌&#xff1a;ASEMI 封装&#xff1a;GBJ-4 恢复时间&#xff1a;&#xff1e;50ns 正向电流&#xff1a;25A 反向耐压&#xff1a;1000V 芯片个数&#xff1a;4 引脚数量&#xf…

python每日一练(7)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

【LeetCode热题100】--739.每日温度

739.每日温度 方法&#xff1a;单调栈 可以维护一个存储下标的单调栈&#xff0c;从栈底到栈顶的下标对应的温度列表中的温度依次递减。如果一个下标在单调栈里&#xff0c;则表示尚未找到下一次温度更高的下标。 正向遍历温度列表。对于温度列表中的每个元素 temperatures[i…

YOLOv5算法改进(11)— 主干网络介绍(MobileNetV3、ShuffleNetV2和GhostNet)

前言:Hello大家好,我是小哥谈。主干网络通常指的是深度学习中的主干模型,通常由多个卷积层和池化层组成,用于提取输入数据的特征。在训练过程中,主干网络的参数会被不断优化以提高模型的准确性。YOLOv5算法中的主干网络可以有多种替换方案,为了后面讲解的方便,本篇文章就…

C结构体内定义结构体,不能直接赋值。

现像&#xff1a; 如下代码&#xff1a; 头文件&#xff1a; typedef struct aBlinkGpioPinOutAbst_{void (*initAsOutput)(void);void (*high)(void);void (*low)(void); }aBlinkGpioPinOutAbst;typedef struct aBlinkGpioAbst_{ #if GPIO_CONFIG_PA0 GPIO_CONFIG_AS_OUTPU…