zoukankan      html  css  js  c++  java
  • 第四次作业

    github链接地址

    问题分析

    • 算式计算(注意优先级与负数)
    • 命令行输入输出

    计算

    看了题目本来是一头雾水,后来看了大神推荐的前缀中缀后缀表达式才有了头绪,先转换,后计算。他人思路如下:

    转换思路:将优先级高的运算甩在前面,同级先出现在前面。
    
    具体实现:以后缀表达式为例。
    1.初始化栈1(存储后缀表达式),栈2(运算符的中转站),从左到右扫描算式。
    2.数字直接进1。
    3.运算符进2,但是符号进去之前判断优先级.
    3-1.如果栈里面高或者**相等**就弹出并压入1,继续比较。这样在表达式中优先级高的符号先出现,先运算。同级先出现,先进表达式。
    3-2.如果栈为空,或者栈顶元素优先级或者为“(”,直接进2。
    4.括号进2。
    4-1.“(”直接进2。
    4-2.“)”出现要把它们之间运算符全部弹出并进1,这样括号里面的运算也先进表达式,括号任务完成,可以不要了。
    5.表达式扫描完以后,将2内元素依次弹出并压入1
    
    计算方法:扫描后缀表达式(先进先扫)。
    1.遇见数字进栈。
    2.遇见运算符就把栈前两个元素拉出来运算,结果再进栈。
    最后栈顶元素即为所得算式结果
    
    举个例子 `1+2*(3+4)-5` 。后缀表达式:(栈底到栈顶)`1 2 3 4 + * + 5 - `按照运算规则就是`1+2*(3+4)-5` 
    

    接下来是自己的(对负数处理)

    1.因为Scan得到的是队列,正好从左到右,所以选择转换成后缀
    
    2.选择用队列而不是栈来存储后缀表达式,因为转换的时候只进不出而最后计算需要先进先扫,毫无疑问,队列更合适
    
    3.想了下,出现负数有两种情况。
    3-1.在算式开头,运算时把0压进栈,这样计算-a就相当于0-a。
    3-2.在左括号右边,这样在输入“(”时,加一个判断,如果下一个元素为“-”,就把0压进后缀表达式。
    

    代码

    转换成后缀表达式
      void Calculation::trans(queue<string>*s)
      {
          string c;
    
          while (s->empty() == false)
          {
    
              //读取队列第一个元素
              c = s->front();
    
              //c为运算符时,先判断优先级,低活着平级先将栈顶元素弹出,再与新的栈顶元素比较,直到高于或者栈空或者“(”进入
              if (c == "*" || c == "/")
              {
                  while (sign.empty() == false && (sign.top() == "*" || sign.top() == "/"))
                  {
                      after.push(sign.top());
                      sign.pop();
                  }
                  sign.push(c);
                  s->pop();
              }
    
              if (c == "+" || c == "-")
              {
                  while (sign.empty() == false && (sign.top() == "+" || sign.top() == "-" || sign.top() == "*" || sign.top() == "/"))
                  {
                      after.push(sign.top());
                      sign.pop();
                  }
                  sign.push(c);
                  s->pop();
              }
    
              //为括号时
              if (c == "(")
              {
                  //判断下一个元素是否为“-”是的话说明下个数是负数,后缀表达式压入0
                  sign.push(c);
    
                  s->pop();
                  if (s->front() == "-")
                  {
                      after.push("0");
                  }
    
              }
              //将括号间运算符弹出并压入后缀表达式,括号舍弃
              if (c == ")")
              {
                  while (sign.top() != "(")
                  {
                      after.push(sign.top());
                      sign.pop();
                  }
                  sign.pop();
                  s->pop();
              }
    
              //数字直接进栈
              else if (isdigit(c[0]))
              {
                  after.push(c);
                  s->pop();
              }
    
          }
    
          //运算符全部进后缀表达式
          while (sign.empty() == false)
          {
              after.push(sign.top());
              sign.pop();
          }
    }
    

    计算后缀表达式

      double Calculation::count()
      {
          string c;
          stringstream ss;
    
          num.push(0);//考虑第一个数为负数
          while (after.empty() == false)
          {
              double flag = 0;//存每次栈顶元素与下个元素运算结果
              c = after.front();
    
              //为运算符就把前两个元素弹出来参与运算,并将结果存入栈中
              if (c == "+")
              {
                  double a = num.top();
                  num.pop();
                  double b = num.top();
                  num.pop();
                  flag = b + a;
                  num.push(flag);
              }
    
              if (c == "-")
              {
                  double a = num.top();
                  num.pop();
                  double b = num.top();
                  num.pop();
                  flag = b - a;
                  num.push(flag);
              }
    
              if (c == "*")
              {
                  double a = num.top();
                  num.pop();
                  double b = num.top();
                  num.pop();
                  flag = b*a;
                  num.push(flag);
              }
    
              if (c == "/")
              {
                  double a = num.top();
                  num.pop();
                  double b = num.top();
                  num.pop();
                  flag = b / a;
                  num.push(flag);
              }
    
              //数字直接存入栈中
              else if (isdigit(c[0]))
              {
                  double temp;
                  ss << c;
                  ss >> temp;
                  num.push(temp);
                  ss.clear();
              }
              after.pop();
          }
          //栈顶元素为最终运算结果
          return num.top();
    }
    

    命令行

    怎么说呢,现在还不是太懂,而且它坑了我很久,一开始运行了是这样的

    之后我怎么改代码都没用,后来无意间少写了一句,运行之后还是输出了结果,我就知道不是代码的问题,我就重新建了一个项目,最后成功输出了,截屏如下:

    意外状况

    • 一开始写完代码传参直接归0。。。后来大神自愿接过这个烂摊子,先不传参,把代码理了理,其中左右括号一个中文输入,一个英文输入,这样的错误让我觉得很对不住他。但是运算结果还是有很多不正确,他就告诉我检查时把计算和转换分开检查,然后我就辛劳的开工了
    • 由于看资料时把别人的话看漏了,就是转换成后缀,判断优先级,同级也要弹出。结果还以为别人的错了,自己有劳心劳力的把减法全部变成加上一个负数,除法变成乘上他的倒数,最后还是悻悻的改回来
  • 相关阅读:
    Xcode 增强开发效率的插件
    svn 常用指令
    初识JFinal
    企业竞争案例分析
    可行性研究5
    可行性研究习题4
    可行性研究课后题
    关于阅读软件工程和计算机科学技术区别的文章来谈谈自己看法
    关于中文编程是解决中国程序员效率的秘密武器的问题思考
    Java ForkJoinPool 用法及原理
  • 原文地址:https://www.cnblogs.com/liu424/p/5386768.html
Copyright © 2011-2022 走看看