zoukankan      html  css  js  c++  java
  • 面向对象程序设计第四次作业(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 <iostream>
      #include <stack>
      #include <string>
      #include <queue>
      using namespace std;
      
      class Calculation 
      {
      
      public:
      
      	//计算表达式的值
      	void ToCalculate(queue<string>q);
      
      private:
      
      	double m_dTemp;
      	char m_cTemp;
      
      	//存储数字
      	stack<double>figure;
      	stack<double>figure_temp;
      
      	//存储符号
      	stack<char>operate;
      	stack<char>operate_temp;
      
      };
      

    • Calculation.cpp

      #include <iostream>
      #include <queue>
      #include <sstream>
      #include <string>
      #include <stack>
      #include "Calculation.h"
      using namespace std;
      
      void Calculation::ToCalculate(queue<string>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、 参考资料

  • 相关阅读:
    初试PL/SQL并行编程
    SVN 让项目某些文件不受版本控制
    分析php获取客户端ip
    一道月薪3W的java面试题 (小明和小强都是张老师的学生,张老师的生日是某月某日,2人都不知道张老师的生日)
    js遍历对象的属性并且动态添加属性
    CodeForces 150B- Quantity of Strings 推算..
    linux 中多线程使用
    Microsoft Deployment Toolkit 2013 Preview Release Now Available
    谁有SMI-S Provider的一些源码,能参考一下吗
    hdu1395-2^x mod n = 1
  • 原文地址:https://www.cnblogs.com/HBING/p/5375693.html
Copyright © 2011-2022 走看看