0

この文字列計算機のコードには演算子の優先順位がなく、修正方法がよくわかりません。switch ステートメントと関係があると確信していますが、この文字列計算機を左から右に移動して、減算/加算の前に乗算が発生するかどうかに関係なく計算する必要があります。これまでのコードは次のとおりです。

#include<iostream>
#include<sstream>
#include<string>
#include<cctype>
#include<cmath>
using namespace std;

enum {PLUS='+',MINUS='-',MULT='*'};

int numberValue(string &expr)
{
istringstream is(expr);
int value = 0;
is >> value;
return value;
}

int expressionValue(string &expr)
{
int i = 0;
int p = 0;

if(expr.at(0) == '(' && expr.at(expr.length()-1) == ')')
{
    for(i=0;i<expr.length();i++)
    {
        if(expr.at(i)=='(')
            p++;
        else if(expr.at(i)==')')
            p--;
        if(p==0)
            break;
    }
    if(i==expr.length()-1)
        return expressionValue(expr.substr(1,expr.length()-2));
}

for(i=0;i<expr.length();i++)
{
    if(expr.at(i)=='(')
        p++;
    else if(expr.at(i)==')')
        p--;
    else if(p==0 && ispunct(expr.at(i)))
    {
        switch(expr.at(i))
        {
        case PLUS:
            return expressionValue(expr.substr(0,i)) + 
                expressionValue(expr.substr(i+1,expr.length()-i-    1));
        case MINUS:

            return  expressionValue(expr.substr(0,i)) -
                expressionValue(expr.substr(i+1,expr.length()-i-1));
        case MULT:

            return  expressionValue(expr.substr(0,i)) *
                expressionValue(expr.substr(i+1,expr.length()-i-1));
        }
    }
}


return numberValue(expr);
}

bool Validate(string inputStr)
{
for(int x = 0;x < inputStr.length(); x ++)
{
    if((inputStr[x] == '+') || (inputStr[x] == '-'))
    {
        if((inputStr[x+1] == '+') || (inputStr[x+1] =='-'))
        {
            return false;
        }
    }
}

string arr = "0123456789+-*";
int count = 0;

for(int a = 0; a < inputStr.length(); a++)
{
    for(int b = 0; b < arr.length(); b++)
    {
        if(inputStr[a] == arr[b])
        {
            count++;
        }
    }
}
if(count == inputStr.length())
{
    return true;
}
else
{
    return false;
}
}

int main()
{
string expressionString;
string retry = "y";

cout << "Enter an expression as a string...you can use addition, subtraction \nand     multiplication."<< endl;
cout << "\nKeep in mind that this calculator does not accept decimals and the \nleading operand can not be negative." << endl;
cout << "\nOperands can have no more than 8 digits, each operator has the same \nprecedence, and each operator is left associative." << endl; 
do
{
cout << "\nEnter an expression: ";
cin >> expressionString;

if(Validate(expressionString) == true)
{
    cout << expressionValue(expressionString) << endl;
}
else
{
    cout << "An error has occured in the input" << endl;
}
cout << "Press \"y\" to enter another expression or \"n\" if you want to quit." <<     endl;

cin >> retry;

}while
(retry == "y");
return 0;
}
4

1 に答える 1

2

あなたのコードには 2 つの問題があることがわかりました。

まず、簡単に修正できます。Cin >> string は、最初の空白文字まですべてを取得します。http://www.cplusplus.com/reference/istream/istream/getline/を検討する価値があるかもしれません。これにより、改行文字まですべてが取得されます。これにより、「1 + 1」と入力した場合にプログラムが「1」を返すだけではなくなります。

あなたの2番目の問題、そしてあなたがもっと興味を持っていると私が思う問題は、誤って演算子を右結合にしてしまったという事実です。これは、プログラムの再帰方法の結果です。関数がステートメント 1 + 2 * 3 に対して自分自身を呼び出す方法について考えると、最初の + に遭遇すると、ExpressionValue('1') + ExpressionValue(2 * 3) が呼び出されます。このため、その場合、乗算は加算の前に評価されます。

その問題を解決する最も簡単な方法は、おそらく文字列を逆方向に解析することですが、括弧を処理するコードをかなり変更する必要があると思います。

ちょっと関係ない話で。スタイルの面では、関数の内部をインデントしていないため、一部のコードは読みにくいものでした。

于 2013-04-24T03:15:21.627 に答える