0
#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”值,但该操作不起作用。

4

3 回答 3

2

你可能是说

switch(input[i])

反而

switch(operation.top())
于 2011-04-12T06:53:14.690 回答
1

更新对代码更改的响应


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

  1. 该代码大多具有它已经存在的所有缺陷,并且还有一些缺陷。
  2. 您现在将操作数组合成一个字符串流有什么好处?
  3. 您现在打开 (operand1,operand2)...
    • 两者都未初始化
    • (operand1,operand2) 在这种情况下基本上是指 (operand2) (序列运算符)
    • 您的分支标签是 ... 运算符 (+-/*)
  4. 您现在打印一个最终结果,它是输入中所有数字的串联(如果您在没有崩溃的情况下到达程序末尾)?

在以前的错误中,仍应修复

  1. 堆栈计算器的心智模型。
    • 数字(整数)是操作数(所以 9、100、39829 是有效的操作数)
    • +-/* 是运算符(对 进行operators 操作operands
    • 堆栈是操作堆栈,而不是运算符堆栈(不必记住运算符,因为它们会立即计算)
    • digits数字连续由 1 个或多个(0123456789) 组成;所以你需要阅读几个字符才能“推”numberoperand stack
    • operators+-/* 取2 ,因此对 size<2 堆栈的operands任何操作都是错误(您需要检查这一点,否则程序将在尝试访问不存在或包含垃圾的内存时崩溃)。

这应该足以让你开始。

我认为有两件事是积极的:

  1. 你程序编译。+1 为您实际使用那里的编译器:)
  2. 您将重复operation.push(result)从开关中取出,因此不再重复。+1 编码风格...

我希望你能从中看出代码不是很好(说得委婉些),我真的认为一些基本练习是有序的: 1. 编写一个简单的 for 循环,将数字 1 到 10 打印到控制台 1 . 编写一个简单的 while 循环来打印用户输入的单词 1. 使用一个简单的循环来打印 1 到 50 之间的所有数字,这些数字是 7 的倍数 1. 每当用户输入其中一个时,使用 switch 语句打印“yes”字母 a、b、k 或 z 2. 制作一个简单的循环,仅打印相同字符后面的每个字符的输入字符(因此 'abccdefgghijkllmabcdd' 将变为 'cgld') 1. 使用相同的循环,但这次打印每个紧跟在同一个词之后的词(所以“不,不,你不应该弹出,弹出,而是推,弹出”变成“没有流行音乐”)

这应该让您了解事情的真正运作方式,而无需猜测或“神奇因素”。

哦,别忘了,我在下面为你实现了整个过程。我不建议你盲目地复制它(这对你的老师来说是相当明显的:))但是如果你想知道的话,你可以看看,我上面所有的话是什么意思:)


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

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

纯娱乐:

#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
于 2011-04-12T07:20:39.713 回答
0

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

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

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

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

于 2011-04-12T07:47:44.210 回答