-3

How can I evaluate an infix string expression which only consists of + and * operators. (No parenthesis).

Example 1:

  • Input: "1+2*3"
  • Output: 7

Example 2:

  • Input: "1+2*3+4"
  • Output: 11

Here is my code I have so far (which is not giving correct result), I wonder if I can do it with one stack (or none)

int evaluateExpression(string s) {
    stack<int> operandStack;
    stack<char> operatorStack;
    string token = "";
    for(char &c : s) {
        if(c == '*' || c == '+') {
            operandStack.push(stoi(token));
            operatorStack.push(c);
            token = "";
        }
        else {
            token += c;
        }
        if(operandStack.size() > 1 
            && operandStack.size() == operatorStack.size() + 1
            && operatorStack.top() == '*') {
                int a = operandStack.top(); operandStack.pop();
                int b = operandStack.top(); operandStack.pop();
                operandStack.push(a * b);
            }
    }
    
    while(operandStack.size() > 1) {
        int a = operandStack.top(); operandStack.pop();
        int b = operandStack.top(); operandStack.pop();
        operandStack.push(a + b);
    }
    
    return operandStack.top();
}

Note: do not want to use any non-standard libraries. Ideally with no use of any library.

A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
  • 2
    Convert it to a postfix expression and evaluate it.:) – Vlad from Moscow Jul 23 '20 at 22:18
  • 3
    What is special here? There are numerous "how to parse math?" questions out there. – Yunnosch Jul 23 '20 at 22:18
  • When scanning the string, don't perform an addition until you find the next `+` operator (as in example 2), or the end of the expression (as in example 1). – user3386109 Jul 23 '20 at 22:46
  • 3
    Possible simple approach: split the string to numbers and operations. Until there is any `*`, take it and the neighboring numbers and replace them with the multiplication result. Once you have only `+`, sum it. The question (requirement for full code writing) is not well suited for SO.. – Jan Stránský Jul 23 '20 at 23:17
  • Added my code snippet – A-Sharabiani Jul 24 '20 at 02:47
  • @Yunnosch here there are not parenthesis, and only + and * operators, to there should be an easier way of evaluating this without extra space maybe (stacks). – A-Sharabiani Jul 24 '20 at 02:50

2 Answers2

4

Yes, you do need only one stack. You can use the standard approach with a shift-reduce parser. In your case, and the simple grammar, this may be already a little bit too much. But I will describe it anyway.

The secret is to use a "parse stack". So only one stack. Not an operator and operand stack. There you will use attributed tokens. A token has a type, like ADD, MULT, NUMBER and, an associated attribute. The attribute is usually a union or a struct. It would be empty for ADD and MULT and would contain a value for NUMBER.

The scanner, which has usually the function getNextToken will produce your tokens. In your case, extremely simple, just those 3 tokens.

Then, in a loop, you will do always the following actions.

  • Always push the fresh token onto the parse stack
  • Try to match the top of the stack with a production of the grammar (and look ahead token)
  • Reduce the stack (Remove matched elements), evaluate the expression, and put the result on the parse stack

So, always: Shift, Match, Reduce

In your case you need for the match function one lookahead symbol, so, the next token. You will find exactly such an example here. There you can find a compiler, with one front end (Scanner, Parser) and 2 different code generators as back end. The code generators are not needed for you task, you can directly evaluate while reducing.

But, for such an easy grammar, you do not need a stack at all. In the book crafting A Compiler with C is a good example. My copy of the book is from 1991, but of course the content is still valid.

They basically write a function for each production/terminal/non-terminal in the grammar and evaluate the tokens and call the functions of other terminals or non-terminals. Interesting approach and not difficult for your use case.

Hope this helps a little . . .

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
A M
  • 14,694
  • 5
  • 19
  • 44
  • 2
    Hi, please put the non-answer parts in a comment. I am not against you venting a little, but a comment on your own post is in my opinion the right place for that. – Yunnosch Jul 24 '20 at 07:22
0
 int evaluateExpression(string s) {
        string token = "";
        char currOperator = '+';
        stack<int> st;
        string temp = s + '.';
        for(const char &c : temp) {
            if(isdigit(c)) {
                token += c;                    
            }
            else if(c != ' ') {
                if(currOperator == '*') {
                    int stackTop = st.top();
                    st.pop();
                    st.push(stackTop * stoi(token));
                }
              
                else if(currOperator == '+') {
                    st.push(stoi(token));
                }
                
                token = "";
                currOperator = c;
            }
        }
        
        int result = 0;
        while(!st.empty()) {
            result += st.top();
            st.pop();            
        }
        return result;
    }
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128