Cout Not Printing the Return Value from the function

Viewed 85

I am trying the Infix to Prefix conversion and evaluation in C++. Someone here guided me and my converstion was resolved easily. But now I am having problems while evaluating it. The problem is that cout is not printing the return value from my function. Following is my code:

int PrefixEvaluation(string s)
{
    stack<int> st;
    
    for(int i=s.length()-1; i>=0; i--)
    {
        if(s[i] >= '0' && s[i] <= '9')
        {
            st.push(s[i] - '0');
        } // if
        
        else
        {
            int op1 = st.top();
            st.pop();
            
            int op2 = st.top();
            st.pop();
            
            switch (s[i])
            {
                case '+':
                    st.push(op1+op2);
                    break;
                
                case '-':
                    st.push(op1-op2);
                    break;
                    
                case '*':
                    st.push(op1*op2);
                    break;
                
                case '/':
                    st.push(op1/op2);
                    break;
                    
                case '^':
                    st.push(pow(op1,op2));
                    break;
                    
                default:
                    cout<<"Invalid"<<endl;
                    break;

            } // switch
        } // else
    } // for loop

    cout<<st.top()<<endl;

    return st.top();

} // PrefixEvaluation()

int main()
{
    cout<<"Prefix Evaluation: "<<PrefixEvaluation("+*^55/9/9*974")<<endl;
} // main

There is no error displayed. The console simply displays a blank screen. Please help. Thank you.

3 Answers

So as @JaMit already explained above, it was a floating point exception. The problem was that I took variables op1 and op2 in int. Therefore, it was only taking the 0 from the previous value and not the complete number i.e 0.xxx. So, I simply changed their data types from int to double and it worked perfectly. Thank you everyone who tried to help.

The console simply displays a blank screen.

That is a problem. Not so much because your program crashed, but because you do not know where it crashed. The traditional remedy for this is to use a debugger, but in this case diagnostic output could be illuminating. Furthermore, for a project like this (a fairly simple console program), I would recommend having diagnostic output from the start so that you can verify your code as you go along.

What would be good diagnostic output? The core of PrefixEvaluation() is the stack st, so add a diagnostic line before every push and pop. This diagnostic should show the pieces you are working with. For example, when pushing a digit:

std::cerr << "Push " << s[i] << '\n'; // Not converted to int
st.push(s[i] - '0');

(I use std::cerr because it is unbuffered, and because it is possible to separate cout and cerr output by redirecting one of them to a file.) Next example, when pushing an operation:

std::cerr << "Push " << op1 << " + " << op2 << '\n';
st.push(op1+op2);

Do this for all the operations, plus the two pops, and you should see why your program crashed:

Prefix Evaluation: 
Push 4
Push 7
Push 9
Pop  9
Pop  7
Push 9 * 7
Push 9
Pop  9
Pop  63
Push 9 / 63
Push 9
Pop  9
Pop  0
Push 9 / 0

There you go – you hit a division by zero error. (Note: this is a reason to output the pieces without combining them. If the diagnostic was std::cerr << "Push " << op1/op2 << '\n'; then the diagnostic would unhelpfully crash.) To make your program stable (i.e. work even when the input is bad), you should check for zero before dividing. It's up to you to decide what the program should do in this case. Perhaps you simply want to inform the user and exit.

if ( op2 == 0 ) {
    std::cout << "Division by zero!\n";
    std::exit(1);
}
st.push(op1/op2);

Don't forget to remove (or comment out) the diagnostics before declaring the project done.


You could get the same result from a debugger. Let the debugger break execution just as the program crashes, then look at the values of your variables at that point. See that op2 is zero. It works, but if you want to find out why op2 is zero, you often have to do another run, breaking multiple times. In contrast, the diagnostic outputs let you quickly trace the source of the zero to 9/63 with just one run.

The speed of tracing the state of your stack is the reason I find diagnostics helpful in this situation. Each test case can be quickly checked not only for the correct final result, but also for the correct computations along the way. The computations stand out, so if you know which should have been performed, you can scan the output to make sure each is present. This lets you check for many potential bugs with not much effort.

Wow, this is some inconsistency in the STL right there.

std::stack<T,Container>::top

reference top(); const_reference top() const;

Returns reference to the top element in the stack. This is the most recently pushed element. This element will be removed on a call to pop(). Effectively calls c.back().

No mention what happens when the stack is empty, no exception thrown when you try it. It just causes plain undefined behavior (exit 139 for me).

Now why is that relevant? Because what you wrote is a postfix evaluator and you feed it with prefix notation. The first character in the string is '+' so you pop 2 elements from the stack that is empty.

Related