1. ホーム
  2. c++

[解決済み】C++用RPN電卓

2022-02-18 19:12:03

質問

RPN電卓のコードを書こうとしているのですが、複数のオペランドを正しく計算させることに苦労しています" left" と " right" です。

今のところ、私のコードは次のような入力に対して動作しています。 10 15 + = 25

これらの入力を正しく出力させる方法がわからなくて困っています。

入力 100 10 50 25 / * - -2 / = 出力。-40

また、今はスタックサイズを2で割っていますが、これはエラーチェックの一部には有効ですが、上記/下記のような入力ではエラーが表示されます。 100 10 50 25 / * - -2 / = -40

以下の2つの入力に対してエラーチェックを行うようにするにはどうしたらよいでしょうか?

入力 10 20 * / = 出力。 Error: 演算子が多すぎる

    12 20 30 / =                   Error: Too many operand

何かお手伝いいただけると助かります、ありがとうございます

#include <iostream>
#include <stack>
#include <string>
#include <sstream> //make use of a class called istringstream
#include<iomanip>

using namespace std;

//Function prototype for isOperator
bool isOperator(const string& input);

//Function prototype for perforOperation
int performOperation(const string& input, stack<double>& calcStack);

int main()
{

    cout << "RPN Calculator: " << endl;
    cout << "Input\n";

    stack<double> calcStack;
    string input;


        while(input != "0")
        {
            //Terminate program when 0 is entered by user
            while(input != "=")
            {

            // get input
            cin >> input;

            // check for being numeric value
            double num;

                if(istringstream(input) >> num)
                {
                    //use push function
                    calcStack.push(num);
                }

                // check for operator
                else if(isOperator(input))
                {
                    performOperation(input, calcStack);
                }

                // If user enters 0 on a line followed by a new line, the program exits     ????????????
                else if(input == "0\n")
                {
                    return -1;
                }

                // invalid output check
                //else
                //{
                    //cout << "Invalid input" << endl;
                //}
            }
            }
}

    bool isOperator(const string& input)
    {
        string operators[] = {"-", "+", "*", "/"};

        for(int i=0; i<4; i++)
        {
            if(input == operators[i])
            {
                return true;
            }
        }

        return false;
}


int performOperation(const string& input, stack<double>& calcStack)
{
    double firstOperand;
    double secondOperand;
    double result;

    if( calcStack.size() > 2 )                      //Error check gives a false error for last input ???
    {
        cout << "Error: too many operands" << endl;
        return 1;
    }

    //Error chceck for too many operators           ////STILL PRINT OUTPUT???
    if( calcStack.size() < 2 )
        {
            cout << "Error: too many operators" << endl;
            return 1;
        }


    secondOperand = calcStack.top();
    calcStack.pop();


    firstOperand = calcStack.top();
    calcStack.pop();


    if(input == "-")
    {
        result = firstOperand-secondOperand;
    }

    else if (input == "+")
    {
        result = firstOperand + secondOperand;
    }

    else if (input == "*")
    {
        result = firstOperand * secondOperand;
    }

    else if( input == "/")
    {
    result = firstOperand / secondOperand;
    }


    // If user enters 0 on a line followed by a new line, the program exits         ???????????
    else if(input == "0\n")
    {
    return -1;
    }

        //Division by zero error
        if(secondOperand == 0)
            {
                cout << "Error: Division by 0.\n";
                return -1;
            }

    cout << "Output\n";
    cout << result << endl;
    calcStack.push(result);

return 0;

}

解決方法は?

このコードのビットはこちら

if( calcStack.size() > 2 )                      
{
    cout << "Error: too many operands" << endl;
    return 1;
}

メインに移動して若干の変形が必要

else if(isOperator(input))
{
    performOperation(input, calcStack);
}
else if(input == "=")
{
    if (calcStack.size() != 1)
    {
        cout << "Error: too many operands" << endl;
        return 1;
    }
    else
    {
        cout << "Result: " << calcStack.top();
        // now decide whether or not you are preserving the result for
        // the next computation
        calcStack.pop(); // Assuming not keeping result
    }
}

そして、このループを見直す必要があるということです。 while(input != "=")

本当に惜しいことをしましたね。

2つの提案

isOperator関数を最適化することができます。

bool isOperator(const string& input)
{
    static const string operators ="-+*/";
    if (input.length() == 1) // right size to be an operator.
    {
        return operators.find_first_of(input[0]) != string::npos;
        // look in the operator string for the first (and only) character in input
    }
    return false;
}

また、演算子には1文字しかないことが分かっているので、if/else if よりもエレガントなものを使うことができます。

switch (input[0])
{
    case '-':
        result = firstOperand - secondOperand;
        break;
    case '+':
        result = firstOperand + secondOperand;
        break;
    case '*':
        result = firstOperand * secondOperand;
        break;
    case '/':
        if (secondOperand == 0)
        { // moved this test to here because it's the only place it matters.
            cout << "Error: Division by 0.\n";
            return -1;
        }
        result = firstOperand / secondOperand;
        break;
}

コメントへの対処のための追記

この時点であなたのコードはかなり変わっているはずなので、現在のコードで新しい質問を始めたくなるかもしれません。そうでない場合は、これがコメント欄で話していることです。

else if(isOperator(input))
{
    if (performOperation(input, calcStack) != 0)
    {
        // empty out the stack and delete all pending user input.
        calcStack.clear(); 
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
        cout << "Bad input. Try again." << endl;
        break; // exit input loop.
     }
}
else if(input == "=")
{
...