コード変更への応答を更新する
コードを変更したことは確認できますが、良い方法ではありません。
- コードには、ほとんどの場合、すでに持っていたすべての欠陥と、さらにいくつかの欠陥があります。
- オペランドを文字列ストリームに結合することは、どのような利点がありますか?
- ここで(operand1、operand2)をオンにします...
- 両方とも初期化されていません
- (operand1、operand2)は、このコンテキストでは基本的に(operand2)を意味します(シーケンス演算子)
- ブランチラベルは...演算子(+-/ *)
- これで、入力のすべての数字を連結した最終結果が出力されます(クラッシュせずにプログラムの最後に到達した場合)。
以前は間違っていたものの中で、まだ修正する必要があります
- スタック計算機のメンタルモデル。
- 数値(整数)はオペランドです(したがって、9、100、39829は有効なオペランドです)
- +-/ *は演算子です(
operators
を操作しますoperands
)
- スタックはオペランドスタックであり、演算子スタックではありません(演算子はすぐに評価されるため、覚えておく必要はありません)
- 番号は1つ以上
digits
(0123456789)の行で構成されます。したがって、を「押す」前に、いくつかの文字を読む必要がありますnumber
。operand stack
operators
+-/ *は2を取るので、 operands
サイズ<2のスタックでの操作はエラーになります(存在しないかゴミを含むメモリにアクセスしようとすると、プログラムがクラッシュすることを確認する必要があります)。
それはあなたが始めるのに十分なはずです。
私が思う2つのことはポジティブです:
- プログラムをコンパイルします。実際にそこでコンパイラを使用している場合は+1:)
- スイッチから繰り返しを
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。同じループを使用しますが、今回は同じ単語の直後に続く単語(つまり、「いいえ、いいえ、ポップ、ポップではなく、プッシュ、ポップ」は「ポップなし」)
これにより、当て推量や「魔法の要素」がなくても、物事が実際にどのように機能するかを感じることができます。
ああ、そして忘れないでください、私はあなたのためにすべてを以下に実装しました。私はあなたがそれを盲目的にコピーすることを提案しません(それはあなたの先生にはかなり明白です:))しかしあなたが知りたいのならあなたが覗き見するためにそこにあります、私が上記のすべての言葉で何を意味するか:)
解析された数値ではなく、緩い数字をプッシュしています
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