面向对象程序设计第四次作业(2)

计算四则运算表达式


0、 运行效果



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,感觉这样会比较好操作一点。

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


<3> 计算表达式的值

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

  • 然后我应该用了不算后缀式的后缀式吧..

  • 正宗后缀式:

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

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


<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
    • 运行效果
    • 不过小数点后面的竟然被四舍五入了...更:coutprintf就可以了 0 0
    • 以下代码已更新

  • Calculation.h

    pragma once

    include

    include

    include

    include

    using namespace std;

    class Calculation
    {

    public:

    //计算表达式的值
    void ToCalculate(queueq);

    private:

    double m_dTemp;
    char m_cTemp;

    //存储数字
    stackfigure;
    stackfigure_temp;

    //存储符号
    stackoperate;
    stackoperate_temp;

    };


  • Calculation.cpp

    include

    include

    include

    include

    include

    include "Calculation.h"

    using namespace std;

    void Calculation::ToCalculate(queueq)
    {
    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_strQue0 < '0' || m_strQue0 > '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、 参考资料

posted @ 2016-04-10 21:54  H_BING  阅读(233)  评论(6)    收藏  举报