文章目录

  • 题目描述
  • 思路
    • 使用getline()存储输入的字符串
    • 边读取边压栈
  • 完整代码

题目描述

使用stack处理括号化的表达式。当你看到一个左括号,将其记录下来。当你在一个左括号之后看到一个右括号,从stack中pop对象,直至遇到左括号,将左括号也一起弹出栈。然后将一个值(括号内的运算结果)push到栈中,表示一个括号化的(子)表达式已经处理完毕,被其运算结果所替代。


思路

使用getline()存储输入的字符串

是为了避免cin在提取字符串时遇到空格会终止读取的问题。例如:

// 当输入1 *2时
cin >> s; // s为1
getline(cin, s); // s为1 *2

边读取边压栈

创建两个栈:

  • 一个用来存运算符
  • 一个用来存操作数
    当遇到 “)” 时,弹出运算符栈中的运算符、和对应的操作数栈中的操作数并进行计算直到遇到 “(” ,完成后将这期间的运算结果压入操作数栈。例如:

    处理 “ (,+,) ” 时,将1,2作为操作数从nums栈中弹出,将处理结果3压入nums栈中,当然, “ (,+,) ” 三个运算符全部弹出symbol栈。之后:

    遇到右括号时,将乘号、左括号弹出栈,在这过程中将3、4作为操作数弹出nums栈进行运算,之后,将运算结果压入nums栈。

当处理完全部括号后,将symbol栈中的运算符清空——也就是将对应的运算都进行计算,(在此过程中,减法和除法要注意操作数的先后问题):

当symbol栈中为空时,nums栈中仅有一个元素,也就是最终的计算结果。


完整代码

#include <iostream>
#include <stack>
#include <string>using namespace std;void resolve(stack<double>& s1, stack<char>& s2){while((!s2.empty()) && (s2.top() != '(')){char temp = s2.top();s2.pop();double num1 = s1.top(); //second//cout << "num1: " << num1 << endl;s1.pop();double num2 = s1.top(); //first//cout << "num2: " << num2 << endl;s1.pop();if(temp == '*'){s1.push(num1*num2);//cout << "*" << endl;}if(temp == '/'){s1.push(num2/num1); // 注意操作数的顺序//cout << "/" << endl;}if(temp == '+'){s1.push(num1+num2);//cout << "+" << endl;}if(temp == '-'){ // 注意操作数的顺序s1.push(num2-num1);//cout << "-" << endl;}}if(!s2.empty()){ // 当symbol栈不为空的时候if(s2.top() == '('){ // 遇见左括号也会跳出上述循环    s2.pop();          // 因此无法执行while中的pop}                    // 程序会一直卡在左括号的位置}                      // 所以在这里补上pop避免上述问题}double calculate(string& s) {if(s.empty()){return 0;}stack<double> nums;stack<char> symbol;double num = 0;string temp = ""; // 存储连续数值字符for(size_t i = 0; i < s.size(); i++){if((s[i] >= '0' && s[i] <= '9') || s[i] == '.'){ // 数字temp += s[i]; // 连续数值字符}if(((s[i]<'0'||s[i]>'9')&&s[i]!=' ') || i==s.size()-1){ // 运算符if(!temp.empty()){num = stod(temp); // num存储连续数值字符的终值nums.push(num);}if(s[i] == ')'){resolve(nums, symbol);}else{switch (s[i]) {case '(':case '+':case '-':case '*':case '/':symbol.push(s[i]); // 上述五种运算符直接压栈}}num = 0;temp.clear(); // 清空temp以便存储下一个连续数值字符}}resolve(nums, symbol);return nums.top();
}bool pankong(string& str){ // 判断左右括号是否数量一致int left = 0;int right = 0;for(auto beg = str.begin(); beg != str.end(); beg++){switch (*beg) {case ')': right++; break;case '(': left++; break;}}if(left != right){cout << "左右括号数量不对等" << endl;return false;}else{return true;}
}int main()
{string str; // 表达式double over; // 最终值//cin >> str;getline(cin,str);if(!pankong(str)){ // 判断左右括号数量是否一致return -1;}over = calculate(str);cout << "over: " << over << endl;return 0;
}

用stack处理中缀表达式【+、-、*、/、()】相关推荐

  1. 九、中缀表达式转为后缀表达式

    使用栈将中缀表达式转为后缀表达式并计算 一.中缀表达式转换为后缀表达式 由于后缀表达式适合计算式进行计算,但是人对于较长的中缀表达式,很难将中缀表达式直接转换为后缀表达式,于是我们使用栈来实现中缀表达 ...

  2. 数据结构 - 栈 (逆波兰计算器)(栈的三种表达式)(前缀、中缀和后缀表达式,后缀也叫逆波兰表达式)(中缀表达式转后缀表达式实现步骤及完整代码)

    栈的三种表达式:前缀.中缀和后缀表达式,后缀也叫逆波兰表达式 前缀(波兰表达式) 中缀(对人来讲很好理解,对于计算机来讲就方便了,一般会把中缀表达式转换成后缀表达式) 后缀(逆波兰表达式) 计算过程 ...

  3. 前缀表达式中缀表达式后缀表达式之间的转换JAVA代码实现

    一.前缀表达式 (1)中缀表达式转前缀表达式 (2)前缀表达式的计算 二.后缀表达式 (1)中缀表达式转后缀表达式 (2)后缀表达式的计算 三.中缀表达式直接计算 四.总结 代码实现的工具类Expre ...

  4. java利用栈求复杂表达式_java中的栈Stack的基本使用和应用(二) ——利用栈计算合法的算术表达,中缀表达式转后缀表达式...

    利用栈Stack计算合法的算术表达式 限定的算术表达式求值问题:包含 "+"."-"."*"."/" .正整数和圆括号的 ...

  5. 利用stack结构,将中缀表达式转换为后缀表达式并求值的算法实现

    #!/usr/bin/env python # -*- coding: utf-8 -*-# learn <<Problem Solving with Algorithms and Dat ...

  6. java中缀表达式转后缀表达式(逆波兰算法)

    四则运算是栈的重要应用之一 中缀表达式转后缀表达式(逆波兰算法)过程 从左到右遍历中缀表达式 数字直接输出为后缀表达式一部分 如果是符号,则判断与栈顶元素的优先级 高于栈顶元素优先级直接入栈 低于或等 ...

  7. java中缀表达式转后缀表达式_数据结构Java实现06----中缀表达式转换为后缀表达式...

    本文主要内容: 表达式的三种形式 中缀表达式与后缀表达式转换算法 一.表达式的三种形式: 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3.我们从小做数学题时,一直使用的就是中缀表达式. 后 ...

  8. 七、使用栈实现综合计算器(中缀表达式)

    使用栈实现综合计算器(中缀表达式) 1.栈的实际需求 请输入一个表达式,计算式:[722-5+1-5+3-3] ,计算出结果 计算机底层是如何运算得到结果的? 注意不是简单的把算式列出运算,因为我们看 ...

  9. 数据结构——栈——中缀表达式和后缀表达式

    什么是中缀表达式,什么是后缀表达式 我们一般看见的多项式计算都是中缀表达式构成的:1+2*3+4/3 类似这种,为什么说是中缀呢?因为它的计算符号都是在两个数中间的. 那么自然而然的明白了后缀表达式是 ...

最新文章

  1. Angular 可观察对象(Observable)
  2. Android下载图片路径问题
  3. c++ opencv 通过网络连接工业相机_OpenCV项目实战之零件缺陷检测(上)
  4. 轻量级高精度人脸检测推荐
  5. qlistwidgetitem itempressed怎么区分左右键_图文介绍:断桥门窗五金配件怎么区分左右定义?...
  6. Android 6.0 动态权限申请
  7. 用户画像是怎么生成出来的?
  8. Linux内核配置系统浅析
  9. spring mvc学习(49):返回json数据
  10. java8四大核心函数式接口(模拟实现,全网最通俗易懂)
  11. Public权限下的列目录
  12. 华为p40为何没有搭载鸿蒙系统?
  13. 陶哲轩实分析 习题 12.5.8 :度量空间中有界闭集不一定是紧集
  14. xp获取计算机管理员权限,xp管理员权限怎么获取?管理员权限不足的解决方法...
  15. Ios 12 linux,iOS12.3~12.4.2支持越狱?包括 A12 设备
  16. 解读随着教育改革的深入steam教育
  17. 商品订单管理系统(参考答案)
  18. android-759b1c是什么,[原创]hooker + jadx 动静结合内存漫游窥视某社交软件视频号功能的数据...
  19. 整理一些简历制作、工作、面试、招聘网站资源分享
  20. 操作系统文件管理实验代码

热门文章

  1. python转r字符_python r不转义变量
  2. logback日志pattern_@Slf4j 实现日志输入到外部文件
  3. .config 和 kconfig以及 makefile的关系
  4. nginx源码学习资源
  5. centos7 安装git_Centos7.4 Yapi 服务搭建
  6. dfa2.java 原理_DFA编程练习2
  7. 【转】Linux下c++调用自己编写的matlab函数:通过mcc动态链接库.so实现
  8. 【转】刨根究底字符编码之一——关键术语解释(上)
  9. applyBinding Observables
  10. 后台接收datetime_input上传date日期时间数据到后台报400怎么办?