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
    • スタックオペランドスタックであり、演算子スタックではありません(演算子はすぐに評価されるため、覚えておく必要はありません)
    • 番号は1つ以上digits(0123456789)の行で構成されます。したがって、を「押す」前に、いくつかの文字を読む必要がありますnumberoperand stack
    • operators+-/ *は2を取るので operandsサイズ<2のスタックでの操作はエラーになります(存在しないかゴミを含むメモリにアクセスしようとすると、プログラムがクラッシュすることを確認する必要があります)。

それはあなたが始めるのに十分なはずです。

が思う2つのことはポジティブです:

  1. プログラムをコンパイルします。実際にそこでコンパイラを使用している場合は+1:)
  2. スイッチから繰り返しをoperation.push(result)取り出したので、もう複製されません。コーディングスタイルの+1..。

このことから、コードがあまり良くないことを理解していただければ幸いです(穏やかに言えば)。基本的な演習がいくつか整っていると思います。1。コンソール1に1から10までの数値を出力する単純なforループを作成します。 。ユーザーが入力した単語を出力する単純なwhileループを記述します1.単純なループを使用して7の倍数である1から50までのすべての数値を出力します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 !!!)、2 つのオペランド演算子を抽出しようとすることが原因である可能性が最も高いです。スタックに挿入したことはありません。'1''2'

入力を解析すると、文字ごとに読み取られ、最初の数字のみを使用すると、解析ではスペースやその他の区切り文字を処理できません...問題を解析と処理の2つに分割してみてください。解析の問題は、読み取った実際の値を使用するのではなく、それらを印刷する (または何らかの形式で保存してから、読み取り式全体を印刷する) ことで対処でき、最初のステップになる可能性があります。パーサーが "1 2 +"、"10 20 +"、"1 2+"、" 1 2 + " (スペースの位置が異なることに注意してください) などの一般的な表現を堅牢な方法で処理できることを確認してください。また、" +"、"1 +"、"1 2 ++" などの式を適切に解析することはできません... ユーザー入力を信頼することはできません。ユーザー入力は間違いを犯しますが、それによってプログラムが崩壊することはありません。

入力を解析できることを確認したら、実際のアルゴリズムを開始します。「10 0 /」など、これまで対処できなかった無効なユーザー入力に対して堅牢にして、実際の処理を行います。

デバッガーの使い方を学びましょう。これは、状況が悪化したときに何が原因なのかを理解するのに役立ちます。デバッガーは、上記のコードの特定の問題を指摘するのに 1 秒もかかりません。なぜそれが停止したかはわかりませんが、どのように停止したか、およびプログラムの状態はどのようなものであったかを示します。私の勘が正しければ、operation.top()命令が原因であることがわかり、挿入された要素よりも多くの要素を抽出しようとしていたことがわかります。プログラムの一部を段階的に実行して、実際に何をしているのかを理解してください。「12+」を読むと、実際には一見無関係な 2 つの整数 ('1''2'...の ASCII 値) がスタックに格納されていることに気付くでしょう。

于 2011-04-12T07:47:44.210 に答える