How can I accept negative values in Postfix and Infix Notation?

十年热恋 提交于 2019-12-07 03:27:25

I don't have a full solution for you, but here are a couple of tips.

  1. I suggest inserting an abstraction layer that reads characters and produces tokens before trying to understand the order of operations. The expression "(42 + 1) - -3" would then become the list { '(', 42, '+', 1, ')', '-', '-', 3 }. A token is often implemented as a class with a type enum (e.g., OPERATOR or NUMBER) and a value (e.g., either a char or a float). (Advanced: You could then convert your tokens into an expression tree, but that might not be necessary here.) This is a little more work, but it makes things much easier to understand than direct string-parsing.

  2. Once you've done that, the key is to determine whether the '-' symbol is intended as infix subtraction or as prefix negation. To do that, look at the previous token (if any). If it's an expression-terminator such as ')' or a number, it's infix subtraction. If there is no such token, or it is some other token, it's prefix negation.

This is what I did:

class expression
{
    //constructors and destructors
public:
    expression();
    ~expression();
    //member properties
private:
    std::string expr;
    std::string postfixExpr;
    //member methods
public:
    // accepts the expression from the user
    void input();
    //prints the accepted expression
    void output();
    //evaluates the accepted expression
    float eval();
    //converts infix expression to postfix
    void convertToPostfix();
    friend bool isOperator(char);
};

inline bool isOperator(char c)
{
    if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#')
        return true;
    return false;
}
void expression::input()
{
    std::cin >> this->expr;
}

float expression::eval()
{
    std::stack<float> s;
    float op1, op2;
    for (int i = 0; i < expr.length(); i++)
    {
        if (expr[i] == '(')
        {
            float sum = 0;
            bool flag = false;
            while (expr[++i] != ')')
            {
                if (expr[i] == '-') {
                    flag = true;
                    i++;
                }
                sum = sum * 10.0 + (float(expr[i]) - float('0'));
            }
            if (flag)
                sum = -sum;
            s.push(sum);
            continue;
        }
        else if (!isOperator(expr[i]))
        {
            s.push(float(expr[i]) - float('0'));
        }
        else
        {
            op2 = s.top();
            s.pop();
            op1 = s.top();
            s.pop();
            switch (expr[i])
            {
            case '+':
                s.push(op1 + op2);
                break;
            case '-':
                s.push(op1 - op2);
                break;
            case'*':
                s.push(op1*op2);
                break;
            case '/':
                s.push(op1 / op2);
                break;

            default:
                std::cerr << "Wrong operator" << std::endl;
                return 0;
            }
        }
    }
    return s.top();
}

In my implementation, the only hitch is to use '(' and ')' as delimiters. Secondly, I also made std::string expr as a property in my expression class. This works fine. But mind well, do input your expression in postfix notation as I still have to include the convertToPostfix function. But I guess, you will figure that out on your own :)

Happy Coding :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!