博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象程序设计第四次作业(2)
阅读量:5084 次
发布时间:2019-06-13

本文共 6162 字,大约阅读时间需要 20 分钟。

计算四则运算表达式

  • github链接:

0、 运行效果

885954-20160411164225863-1982248431.png

885954-20160411165932332-211360886.png


1、 前期准备

  • 网上各种找资料,各种问同学。其实最重要的还是自己要能理解 (⊙ˍ⊙) 讲真。光是理解别人怎么写我就花了好久的时间 (。_。)

  • 真心要理解透才能做得出来 (⊙ˍ⊙) 网上的方式跟题目要求的都不一样...别人都是转成前缀式或后缀式,把数字和符号存到一起...题目却要求把数字和符号分别存入栈,简直造孽...


2、 问题与解决

  • 先说一句自认为十分重要的话“一口吃不成大胖子”,讲真。刚开始的时候又想弄好对负数的处理又想弄好对优先级的判断,反而哪一件事情都没有做成,还把自己弄的很烦躁。后来就一步一步解决:
    对“-a”和负数处理 -> 无括号运算 -> 有括号运算
  • 一步一步来还有一个好处就是debug的时候,对代码调试的范围就会小很多,debug的效率也会提高。
  • 赤裸裸的血的教训...真的很重要啊...


    <1> 重复利用stringstream对象要记得.clear()

  • 刚开始用的时候没有.clear(),发现怎么算都不对 0 0 回头把存符号和存数字的栈分别输出发现都是同一个符号或数字...翻翻资料发现要.clear()


    <2> 对负号的处理

  • 最开始想的是判断是否- 前面是字符&&后面是数字,如果是的话就把数字取负,-换为+再入栈。
  • 后来发现会有(-(1+3)*2+1)这样的情况,虽然规定一下输入格式,改写成(1-(1+3)*2)就可以没有问题了,但是这样计算器感觉用起来就不是那么方便了。
  • 通过学霸指导,我就把对负号的处理改为在-前面补0。原先有想就在Calculation类里面操作的,但是感觉不好判断-号前面是否是负号..然后我就跑去上次写的scan类里面在字符串存入queue的时候直接补0,感觉这样会比较好操作一点。

    885954-20160411165820457-571779857.png

  • 改完之后的试着输出一下,符合!!


    <3> 计算表达式的值

  • 感觉用栈的话适合用前缀式进行计算比较方便,不过不知道我怎么查的...查到的基本上都是用后缀式进行计算的...等我后缀式理解的七七八八了才发现有前缀式 (⊙ˍ⊙)
  • 然后我应该用了不算后缀式的后缀式吧..
  • 正宗后缀式:885954-20160410234053218-795117959.png

  • 我是再开了两个栈分别用来暂时存储符号和数据,大概想法(类似后缀式计算)如下(=o=)

885954-20160410235000859-150027071.png

  • 其实+ - * /调试好之后,对括号的处理会方便很多,要考虑的情况也不算多,胜利的曙光就在眼前...


    <4> 对栈的调用

  • 其实用法没什么难点,就是一定要注意你在调用.top().pop()的时候stack是否为空!!!!!!!
  • 这点真的相当重要啊!!!无数次挂在这上面...写完一定要认真考虑每一次调用.top().pop()的时候stack是否为空!!!每一次!!!


    <5> 心态

  • 在ddl还没延期之前,其实挺烦躁的...一大堆事情等着去做,眼看着ddl马上就要到了这次作业却还是不怎么会做,代码到处都是bug。
  • 在此要感谢浩晖大神对我的...谆谆教诲?好吧,我不知道用什么词来形容 (゚ー゚)
  • ddl截止的倒数第二天晚上吧,那时候感觉基本思路貌似已经成型了,但具体又不知道怎么下手,超级烦躁。去问浩晖大神也还是不是很懂,然后就负气的说了一句算了不看了也来不及了,之后就滚去睡觉了。第二天早上起来发现皓辉大神发了一大段话,大概意思就是 有没有做出题目本身并不重要,题目太难可以降低难度一步步实施,不要轻易放弃
  • 看完之后就满血复活了hhh 而且说来也奇怪,第二天我就都做出来了 (>▽<)
  • 再一次感谢浩晖大神对我的鼓励!!!


3、 待改进

  • 目前写的代码都是默认输入的表达式完全合法,一旦表达式不合法就会有各种问题了 0 0
  • 还有计算结果的处理。没办法像真正计算器那样限定总数字长度,有几位小数就输出几位小数。只能做到限制小数点后几位,如果小数点后没有小数位或不足限定位数时会补0。看起来总觉得是四舍五入后的结果...

4、 代码

  • 自己试了些小数据暂且没有问题。


    2016/04/13 更新

  • 今天发现了一个八阿哥 (。_。)
  • 测试数据:-10000+20-(-(-20+2)*3-1/(2+6*3)-8)+2
    • 不得不说那些被注释掉的代码挽救了我一命!!没花很久的时间就发现了bug ︿( ̄︶ ̄)︿
    • 每次移动符号和数字的时候都要判断一下符号是否为)之前测的数据都比较巧合 0 0 刚好左括号后面都不是没有括号的计算..好像也不是这么说...原数据如果改成-10000+20-(-(-20+2)*3-1/(2+6*3)-8),在代码没有修改的情况下是可以运行的 0 0
    • 运行效果
      885954-20160413114324738-1670255731.png
    • 不过小数点后面的竟然被四舍五入了...更:coutprintf就可以了 0 0
    • 以下代码已更新

  • Calculation.h

    #pragma once#include 
    #include
    #include
    #include
    using namespace std;class Calculation {public: //计算表达式的值 void ToCalculate(queue
    q);private: double m_dTemp; char m_cTemp; //存储数字 stack
    figure; stack
    figure_temp; //存储符号 stack
    operate; stack
    operate_temp;};

  • Calculation.cpp

    #include 
    #include
    #include
    #include
    #include
    #include "Calculation.h"using namespace std;void Calculation::ToCalculate(queue
    q){ int operate_priority(char c); double calculate(char oper, double front, double behind); double _figure; stringstream stream; string m_strQue; //数字符号分别入stack while (!q.empty()) { m_strQue = q.front(); if (m_strQue[0] < '0' || m_strQue[0] > '9') { stream << m_strQue; stream >> m_cTemp; operate.push(m_cTemp); stream.clear(); } else { stream << m_strQue; stream >> m_dTemp; figure.push(m_dTemp); stream.clear(); } q.pop(); } /* while (!operate.empty()) { cout << operate.top() << endl; operate.pop(); } cout << "**************" << endl; while (!figure.empty()) { cout << figure.top() << endl; figure.pop(); } */ while (!operate.empty()) { //遇到左括号 if (operate.top() == ')') { operate_temp.push(operate.top()); operate.pop(); } else { if (operate_temp.empty()) { operate_temp.push(operate.top()); figure_temp.push(figure.top()); operate.pop(); figure.pop(); //operate可能为空 if (operate.empty()) { break; } } //运算符优先级比较计算 if ((operate_priority(operate.top()) < operate_priority(operate_temp.top())) && (operate_temp.top() != ')')) { //除数为0 if (operate_temp.top() == '/'&&figure_temp.top() == 0) { exit(0); } _figure = calculate(operate_temp.top(), figure.top(), figure_temp.top()); operate_temp.pop(); figure.pop(); figure_temp.pop(); figure.push(_figure); } else { //遇到左括号 if (operate.top() == ')') { operate_temp.push(operate.top()); operate.pop(); } else { operate_temp.push(operate.top()); figure_temp.push(figure.top()); operate.pop(); figure.pop(); } } //括号匹配 if (!operate.empty() && !operate_temp.empty() && (operate.top() == '('&&operate_temp.top() == ')')) { operate.pop(); operate_temp.pop(); } } /* cout << "operate" << endl; if (!operate.empty()) { cout << operate.top() << " "; } cout << endl; cout << "operate_temp" << endl; if (!operate_temp.empty()) { cout << operate_temp.top() << " "; } cout << endl; cout << "figure" << endl; if (!figure.empty()) { cout << figure.top() << " "; } cout << endl; cout << "figure_temp" << endl; if (!figure_temp.empty()) { cout << figure_temp.top() << " "; } cout << endl; cout << "****************************" << endl; */ } /* cout << "operate" << endl; while (!operate.empty()) { cout << operate.top() << " "; operate.pop(); } cout << endl; cout << "operate_temp" << endl; while (!operate_temp.empty()) { cout << operate_temp.top() << " "; operate_temp.pop(); } cout << endl; cout << "figure" << endl; while (!figure.empty()) { cout << figure.top() << " "; figure.pop(); } cout << endl; cout << "figure_temp" << endl; while (!figure_temp.empty()) { cout << figure_temp.top() << " "; figure_temp.pop(); } cout << endl; cout << "--------------------------" << endl; */ while (!operate_temp.empty()) { //除数为0 if (operate_temp.top() == '/'&&figure_temp.top() == 0) { exit(0); } _figure = calculate(operate_temp.top(), figure.top(), figure_temp.top()); operate_temp.pop(); figure.pop(); figure_temp.pop(); figure.push(_figure); } cout << figure.top() << endl;}//判断符号优先级int operate_priority(char c){ int pri; switch (c) { case '+': case '-': pri = 0; break; case '*': case '/': pri = 1; break; case '(': pri = -1; break; case ')': pri = 2; break; } return pri;}//计算double calculate(char oper, double front, double behind) { double result; switch(oper) { case '+': result = front + behind; break; case '-': result = front - behind; break; case '*': result = front * behind; break; case '/': result = front / behind; break; } return result;}
  • 虽然阅读体验可能不太好,但是那些被注释掉的代码都是我流过的血和泪...实在舍不得删除...


5、 参考资料

  • stringstream用法:
  • stack用法:
  • 带括号四则运算:
  • 以上是我找的所有资料中参考度比较高的 0 0

转载于:https://www.cnblogs.com/HBING/p/5375693.html

你可能感兴趣的文章
Android系统--输入系统(十一)Reader线程_简单处理
查看>>
监督学习模型分类 生成模型vs判别模型 概率模型vs非概率模型 参数模型vs非参数模型...
查看>>
Mobiscroll脚本破解,去除Trial和注册时间限制【转】
查看>>
实验五 Java网络编程及安全
查看>>
32位与64位 兼容编程
查看>>
iframe父子页面通信
查看>>
ambari 大数据安装利器
查看>>
java 上传图片压缩图片
查看>>
magento 自定义订单前缀或订单起始编号
查看>>
ACM_拼接数字
查看>>
计算机基础作业1
查看>>
Ubuntu 深度炼丹环境配置
查看>>
C#中集合ArrayList与Hashtable的使用
查看>>
从一个标准 url 里取出文件的扩展名
查看>>
map基本用法
查看>>
poj-1163 动态规划
查看>>
Golang之interface(多态,类型断言)
查看>>
Redis快速入门
查看>>
BootStrap---2.表格和按钮
查看>>
Linear Algebra lecture 2 note
查看>>