使用C ++中的堆栈评估postfix

时间:2011-04-12 06:43:47

标签: c++ stack evaluation postfix-notation

#include <iostream>
#include <sstream>
#include <stack>
#include <limits>
#include <string>
using namespace std;

int main()
{
    string input;
    cout << "Enter a postfix expression: " << endl;
    getline(cin, input);

    int operand1, operand2, result,number;
    stack<char>operation;

    stringstream temp;

    int i=0;
    while (i < input.length())
    {
        if (isdigit(input[i]))
        {
            operation.push(input[i]);
        }
        else
        {
            operand2 = operation.top();
            temp << operation.top();
            operation.pop();

            operand1 = operation.top();
            temp << operation.top();
            operation.pop();

            switch(operand1,operand2)
            {
                case '+': result=operand1 + operand2;
                break;

                case '-': result=operand1 - operand2;
                break;

                case '*': result=operand1 * operand2;
                break;

                case '/': result=operand1 / operand2;
                break;
            }
            operation.push(result);
        }
        i++;
    }
    cout << "The result is: "<<temp.str()<<endl;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    return 0;
}

我已更改代码并设法获取“pop”值,但操作无效。

3 个答案:

答案 0 :(得分:2)

你可能意味着

switch(input[i])

代替

switch(operation.top())

答案 1 :(得分:1)

更新对代码更改的响应


我可以确认你改变了代码,但不是很好。

  1. 代码主要有它已经存在的所有缺陷,还有一些。
  2. 您现在将操作数组合成字符串流有什么用?
  3. 你现在打开(operand1,operand2)......
    • 两者都未初始化
    • (operand1,operand2)在这个上下文中基本上是(operand2)(sequence operator
    • 您的分支标签是...运营商(+ - / *)
  4. 你现在打印一个最终结果,它是输入中所有数字的串联(如果你到达程序的末尾而没有崩溃)?
  5. 以前错误的事情,应该仍然是固定的

    1. 堆栈计算器的心智模型。
      • 数字(整数)是操作数(因此9,100,39829是有效的操作数)
      • + - / *是operators上的operands 操作的运算符
      • 堆栈操作数堆栈,不是操作员堆栈(不必记住操作符,因为它们会立即被评估)
      • 数字由一行或多行digits(0123456789)组成;因此,您需要阅读多个字符才能在number上推送operand stack
      • operators + - / *取 2 operands,因此对大小<2的堆栈上的任何操作都是错误的(您需要检查该程序或程序)尝试访问不存在或包含垃圾的内存时会崩溃。
    2. 这应该足以让你入门。

      认为的两件事是积极的

      1. 您的程序编译。实际上在那里使用编译器的+1:)
      2. 您将重复的operation.push(result)从交换机中取出,因此不再重复。 +1编码风格......
      3. 我希望你能从中收集代码不是很好(温和地说),我真的认为一些基本的练习是有序的:  1.编写一个简单的for循环,将数字1到10打印到控制台  1.编写一个简单的while循环,打印用户输入的单词  1.使用一个简单的循环来打印1到50之间的所有数字,它们是7的倍数  1.每当用户输入字母a,b,k或z之一时,使用switch语句打印“yes”  2.创建一个简单的循环,只为每个跟在相同字符后面的字符打印输入字符(因此'abccdefgghijkllmabcdd'将成为'cgld')  1.使用相同的循环,但这次打印紧跟在相同单词后面的每个单词(所以“不,不,你不应该弹出,弹出,但推,弹出”变成“没弹出”)

        这应该让你感受到真正的工作方式,没有猜测或“神奇因素”。

        哦,别忘了,我在下面为你实现了整个事情。我不建议你盲目地复制它(这对你的老师来说会很明显:))但如果你想知道,我的意思是上面所有的话,那就是你的意思:)


        1. 您正在推送松散的数字,而不是已解析的数字

        2. 在第31行中,您弹出一个可能为空的堆栈(除非您在编译器上使用调试模式STL标志,否则会导致段错误)

        3. 只是为了好玩:

          #include <iostream>
          #include <stack>
          #include <vector>
          #include <limits>
          #include <string>
          #include <stdexcept>
          #include <iterator>
          #include <fstream>
          
          using namespace std;
          
              template <class T>
                  static void dumpstack(std::stack<T> s/*byval!*/)
              {
                  std::vector<T> vec;
          
                  while (!s.empty())
                  {
                      vec.push_back(s.top());
                      s.pop();
                  }
          
                  std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));
              }
          
              class calc
              {
                  private:
                      std::stack<int> _stack;
                      int _accum;
                      bool _pending;
          
                      void store(/*store accumulator if pending*/)
                      {
                          if (_pending)
                          {
                              _stack.push(_accum);
                              _pending = false;
                              _accum = 0;
                          }
                      }
          
                  public:
                      calc() : _accum(0), _pending(false) 
                      {
                      }
          
                      void handle(char ch)
                      {
                          switch (ch)
                          {
                              case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
                                  _pending = true;
                                  _accum *= 10;
                                  _accum += ch-'0';
                                  break;
                              case '+': case '-': case '/': case '*':
                                  {
                                      store();
                                      if (_stack.size()<2)
                                          throw std::runtime_error("stack underflow");
          
                                      int op2 = _stack.top(); _stack.pop();
                                      int op1 = _stack.top(); _stack.pop();
                                      switch (ch)
                                      {
                                          case '+': _stack.push(op1 + op2); break;
                                          case '-': _stack.push(op1 - op2); break;
                                          case '/': _stack.push(op1 / op2); break;
                                          case '*': _stack.push(op1 * op2); break;
                                      }
          
                                      // feedback to console:
                                      std::cout << std::endl << "(evaluated: " << op1 << " " << ch << " " << op2 << " == " << _stack.top() << ")" << std::endl;
                                      dump();
                                  }
                                  break;
                              default:
                                  store(); // todo: notify of ignored characters in input?
                          }
                      }
          
                      void dump() const
                      {
                          dumpstack(_stack);
                      }
              };
          
              int main() 
              {
                  cout << "Enter postfix expressions: " << endl;
                  calc instance;
          
                  try
                  {
                      while (std::cin.good())
                      {
                          char ch = std::cin.get();
                          instance.handle(ch);
                      }
                      std::cout << "Final result: "; 
                      instance.dump();
          
                      return 0;
                  } catch(const std::exception& e)
                  {
                      std::cerr << "E: " << e.what() << std::endl;
                      return 255;
                  }
          
              }
          

          测试输出:(请注意,您可以在按回车后继续使用剩余的,部分评估的堆栈)

          Enter postfix expressions: 
          1 2 3 +4 * - / 1333 *
          
          (evaluated: 2 + 3 == 5)
          1 5 
          (evaluated: 5 * 4 == 20)
          1 20 
          (evaluated: 1 - 20 == -19)
          -19 E: stack underflow
          

答案 2 :(得分:0)

代码有很多问题,从解析输入表达式开始。实际崩溃很可能是因为如果您输入类似"12+"的内容,则会将'1''2'推入堆栈(注意:字符1和2,而不是值1和2 !!!)然后尝试提取两个操作数一个你从未插入堆栈的操作符。

在解析输入时,您正在逐字符地阅读,并且仅使用第一个数字,解析无法处理空格或任何其他分隔符...尝试将问题分解为两个:解析和处理。解析的问题可以通过不使用读取的实际值来解决,而只是打印它们(或以某种形式存储然后打印整个读取表达式),并且可以是第一步。确保解析器能够以健壮的方式处理诸如“1 2 +”,“10 20 +”,“1 2 +”,“1 2 +”(注意空格的不同位置)等常用表达式。并且优雅地解析像“+”,“1 +”,“1 2 ++”这样的表达式...你永远不会相信用户输入,他们会犯错误,不应该让你的程序瘫痪。< / p>

一旦确定能够解析输入,请从实际算法开始。使其对以前无法解决的无效用户输入具有鲁棒性,例如“10 0 /”并进行实际处理。

学习使用调试器,它将帮助您了解事情何时向南发生的原因。调试器只需不到一秒的时间来指出上面代码中的特定问题,它不会告诉你它为什么会死,但它会告诉你它是如何死的以及程序的状态是什么。如果我的预感是正确的,那么它将指向你operation.top()指令作为罪魁祸首,你将能够看到你试图提取比插入更多的元素。逐步执行程序的一部分以了解它实际执行的操作,并且您会注意到当您读取“12+”时,实际上是将两个看似无关的整数存储到堆栈中('1'的ASCII值和'2' ......

相关问题