1

後置記法方程式を評価する関数を C++ で記述しようとしています。私の一般的な戦略は、文字列をスキャンすることです(適切な形式、たとえば「10 20 + 30 -」)。
インデックス変数 i をインクリメントすることでこれを行っています。インクリメントごとに、その文字が数字か演算子か、またはそのどちらでもないかを確認します。数字の場合は、getNextNum() 関数を使用して後続のすべての数字を取得し、それを float に変換してから、スタックにプッシュします。また、キャプチャした数値の長さだけ i をインクリメントします。文字が演算子の場合、スタックの上位 2 つの要素を取得し、演算を実行してから、結果をスタックにプッシュします。

問題は、while ループが 1 回しか通過しないように見えることです。この関数は、文字列の最初の数値のみを返します。何が問題なのかわかりません。助けていただければ幸いです。while ループに cout ステートメントを挿入しましたが、i は最初の数値の後のインデックスまでインクリメントするだけです。

編集: OK、getNextNum() 関数を追加しました。また、evalPostfix() を strLength の cout で更新し、while ループの各反復後に i も更新しました。指定されたコードを実行すると、次のようになります。

Running…
Please enter an expression in postfix notation: 555 666+
3
555
3
Your expression evaluates to: 555

strLength が本来よりも小さく設定されているようです。これはなぜですか?

#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <stack>
using namespace std;

string getNextNum(string equation, int i);
float evalPostfix(string postfix);
float doOperation(float x, float y, char op);

float doOperation(float x, float y, char op)
{
    switch (op) {
        case '+':
            return x + y;
        case '-':
            return x - y;
        case '*':
            return x * y;
        case '/':
            return x / y;
        default:
            return 0.0;
    }
}


string getNextNum(string equation, int i)
{
    string num = "";
    const string DELIM = "+-*/%^ ";
    while (i<equation.length()) {
        // Iterate through equation until you hit a delimiter.
        if (DELIM.find(equation[i]) != -1) {
            break;
        }
        num += equation[i];
        i++;
    }
    return num;
}

float evalPostfix(string postfix)
{
    const string OPS = "+-*/%^";
    const string NUMS = "0123456789";
    int strLength = postfix.length();
    stack<float> numStack;
    int i = 0;
    cout << strLength << endl;
    while (i<strLength) {
        if (NUMS.find(postfix[i]) != -1) {
            // If a character is a digit, then you should get the 
            // value and push it to the stack (could be multiple characters long).
            string sNextNum = getNextNum(postfix, i);
            float fNextNum = atof(sNextNum.c_str());

            numStack.push(fNextNum);
            cout << sNextNum << endl;
            i += (sNextNum.length() - 1);
            }
        else if (OPS.find(postfix[i] != -1)) {
            // Otherwise, pop the top two elements of the stack, perform the
            // operation, then push the result back to the stack.
            char op = postfix[i];

            float x = numStack.top();
            numStack.pop();

            float y = numStack.top();
            numStack.pop();

            float z = doOperation(x, y, op);
            numStack.push(z);
            }
        i++;
        cout << i << endl;
    };

    // Once the entire string has been scanned through, there should be a float
    // left in the stack, simply return that.
    return numStack.top();
}

int main ()
{
    cout << "Please enter an expression in postfix notation: ";
    string postfix;
    cin >> postfix;

    float eval = evalPostfix(postfix);
    cout << "Your expression evaluates to: " << eval;
    return 0;
}
4

2 に答える 2

1

タイプミスである主要な問題の1つがいくつかあります。これは間違ってい)ます:

else if (OPS.find( postfix[i] != -1 ) ) {
                 ^                  ^ 

次のようにする必要があります。

else if (OPS.find( postfix[i] ) != std::string::npos) {
                 ^            ^  

charそのため、位置iを比較してから、ブール値の結果-1を実行しています。次に、結果を比較するためfindに使用する必要がありますが、-1findstd::string::npos

ジョナサンが指摘したように:

cin >> postfix ;

最初の黒または改行までのみ読み取ります。を使用getlineすると、その問題が修正されます。

if (getline(cin, postfix))
于 2013-07-07T02:33:50.557 に答える
0

主な問題の 1 つは、入力cin >> postfix;ステートメントが最初の単語しか読み取らないことでした。入力をエコーし​​て、プログラムが見ていると思っているものを見ていることを確認します。

Shafik Yaghmourは別の問題を指摘しています。

学ぶべきポイント:

  1. 入力をエコーし​​て、プログラムが見ていると思うものを見ていることを確認します。
  2. 適切な印刷メッセージでキー変数をトレースします。
  3. post SSCCE ( Short, Self-Contained, Correct Example ) — コンパイル可能なコード;
  4. 入力例とそこから得られる出力を投稿してください。

このコードは入力で機能します555 666+:

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

static float doOperation(float x, float y, char op)
{
    cout << "doOp: x = " << x << ", y = " << y << ", op = " << op << endl;
    if (op == '+')
        x += y;
    return x;
}

string getNextNum(string equation, int i)
{
    string num = "";
    const string DELIM = "+-*/%^ ";
    while (i<equation.length()) {
        // Iterate through equation until you hit a delimiter.
        if (DELIM.find(equation[i]) != -1) {
            break;
        }
        num += equation[i];
        i++;
    }
    return num;
}

float evalPostfix(string postfix)
{
    const string OPS = "+-*/%^";
    const string NUMS = "0123456789";
    int strLength = postfix.length();
    stack<float> numStack;
    int i = 0;
    while (i<strLength) {
        cout << "Top - i: " << i << ", strLength: " << strLength << endl;
        if (NUMS.find(postfix[i]) != -1) {
            // If a character is a digit, then you should get the 
            // value and push it to the stack (could be multiple characters long).
            string sNextNum = getNextNum(postfix, i);
            float fNextNum = atof(sNextNum.c_str());

            numStack.push(fNextNum);
            cout << sNextNum << endl;
            i += (sNextNum.length() - 1);
            }
        else if (OPS.find(postfix[i])!= -1) {
            // Otherwise, pop the top two elements of the stack, perform the
            // operation, then push the result back to the stack.
            char op = postfix[i];

            float x = numStack.top();
            numStack.pop();

            float y = numStack.top();
            numStack.pop();

            float z = doOperation(x, y, op);
            numStack.push(z);
            }
        i++;
        cout << "End - i: " << i << ", strLength: " << strLength << endl;
    }
    cout << "After - i: " << i << ", strLength: " << strLength << endl;

    // Once the entire string has been scanned through, there should be a float
    // left in the stack, simply return that.
    return numStack.top();
}

int main ()
{
    cout << "Please enter an expression in postfix notation: ";
    string postfix;
    //cin >> postfix;
    if (getline(cin, postfix))
    {
        cout << "Evaluating: " << postfix << endl;
        float eval = evalPostfix(postfix);
        cout << "Your expression evaluates to: " << eval << endl;
    }
    return 0;
}

サンプル トレース:

Please enter an expression in postfix notation: 555 666+
Evaluating: 555 666+
Top - i: 0, strLength: 8
555
End - i: 3, strLength: 8
Top - i: 3, strLength: 8
End - i: 4, strLength: 8
Top - i: 4, strLength: 8
666
End - i: 7, strLength: 8
Top - i: 7, strLength: 8
doOp: x = 666, y = 555, op = +
End - i: 8, strLength: 8
After - i: 8, strLength: 8
Your expression evaluates to: 1221

明らかに、解決している特定の問題が解決されると、診断出力の多くが失われる可能性がありますが、示されている線に沿って追加する準備ができていると、解決プロセスが劇的にスピードアップします。

于 2013-07-07T02:36:30.273 に答える