Hi, I wrote a program to input an INFIX convert it to POSTFIX and then evaluate it. But the function 'evaluarRPN' used for evaluate POSTFIX some time work and some time not, depend of the input.
For example:
(8*9-8/5+6)*(5-9) = -305, but the program display -308
(8+9) = 17, display 17, here work fine...

Any suggestion? Thanks

#include <iostream>
#include <string>
#include <stack>
#include <cctype>  //alnum
#include <cassert> //assert
using namespace std;
#include <sstream>

string  infixTOposfix(string);
int evaluarRPN(string);

int main ()
{ // main began

string infix,
       posfixWspaces,
       dummy;
int result;
char repeat;

do {
cout << "\nPlease enter the expression in INFIX: ";

getline(cin,infix);
posfixWspaces = infixTOposfix(infix);

cout << "This is the expression in POSTFIX: " << posfixWspaces << endl;

result = evaluarRPN(posfixWspaces);
cout << "The expression after the evaluation: " << result;

cout << "\nDo you want to repeat? Enter 'y' ";
cin >> repeat;
getline(cin,dummy);
} while ( repeat == 'y');

system("PAUSE");
return 0;
} // main end


string infixTOposfix(string exp)
{
/*-------------------------------------------------------------------------
   Function to convert an infix expression exp to postfix.

   Precondition:  None
   Postcondition: Postfix expression corresponding to exp is returned
       or an error message displayed if exp is not well-formed.
-------------------------------------------------------------------------*/

   char token,                   // character in exp
        topToken;                // token on top of opStack
   stack<char> opStack;                // stack of operators
   string postfixExp;            // postfix expression
   const string BLANK = " ";
   for (int i = 0; i < exp.length(); i++)
   {
      token = exp[i];
      switch(token)
      {
         case ' ' : break;       // do nothing -- skip blanks
         case '(' : opStack.push(token);
                    break;
         case ')' : for (;;)
                    {
                       assert (!opStack.empty());
                       topToken = opStack.top();
                       opStack.pop();
                       if (topToken == '(') break;
                       postfixExp.append(BLANK + topToken);
                    }
                    break;
         case '+' : case '-' :
         case '*' : case '/': case'%':
                    for (;;)
                    {
                       if (opStack.empty() ||
                           opStack.top() == '(' ||
                           (token == '*' || token == '/' || token == '%') &&
                           (opStack.top() == '+' || opStack.top() == '-'))
                       {
                          opStack.push(token);
                          break;
                       }
                       else
                       {
                          topToken = opStack.top();
                          opStack.pop();
                          postfixExp.append(BLANK + topToken);
                       }
                    }
                    break;
         default :  // operand
                    postfixExp.append(BLANK + token);
                    for(;;)
                    {
                       if ( !isalnum(exp[i+1]) ) break; // end of identifier
                       i++;
                       token = exp[i];
                       postfixExp.append(1, token);
                    }
      }
   }
   // Pop remaining operators on the stack
   for (;;)
   {
      if (opStack.empty()) break;
      topToken = opStack.top();
      opStack.pop();
      if (topToken != '(')
      {
         postfixExp.append(BLANK + topToken);
      }
      else
      {
         cout << " *** Error in infix expression ***\n";
         break;
      }
   }
   return postfixExp;
}

[B]int evaluarRPN(string posfijo)
{ // evaluarRPN began
stack<int> numStack;

int x, 
    y,
    toInt;
  
string number;

for (int i = 0; i < posfijo.length(); i++)
 { // for began  

  if ( isdigit(posfijo[i]) )
  { // if began
   number = posfijo[i];
   stringstream ss( number );
   ss >> toInt;
   numStack.push( toInt );
  } // if end
  
  else if (posfijo[i] != ' ' )
  { // else began
      y = numStack.top();
      numStack.pop();
      x = numStack.top();
      numStack.pop();
      
     if (posfijo[i] == '+')
        numStack.push( x+y );
        
     else if (posfijo[i] == '-')
        numStack.push( x-y );
        
     else if (posfijo[i] == '*')
        numStack.push( x*y );
             
     else
        numStack.push( x/y );
  } // else end
  
 } // for end
return numStack.top(); 
} // evaluarRPN end[/B]

Dani AI

Generated

The wrong answer (-308) is the classic integer-truncation problem combined with a fragile tokenizer. With integer arithmetic 8/5 == 1, so

89 = 72
72 - 1 + 6 = 77
77
(5-9) = 77 * -4 = -308

With floating-point math 8/5 == 1.6, so 72 - 1.6 + 6 = 76.4 and 76.4 * -4 = -305.6. As noted, switching the value stack and arithmetic to a floating type (double or long double) fixes the truncation. confirmed that change fixed the immediate symptom.

A more robust evaluator also needs proper tokenization (multi-digit numbers, negatives, decimal points) and defensive checks (stack underflow, division by zero). If the postfix string uses spaces between tokens (as the converter does), a simple and reliable approach is to read tokens with istringstream and treat single-character operator tokens specially. Example evaluator sketch:

double evaluateRPN(const std::string &postfix) {
    std::istringstream in(postfix);
    std::string tok;
    std::stack<double> st;
    while (in >> tok) {
        if (tok.size()==1 && (tok=="+"||tok=="-"||tok=="*"||tok=="/"||tok=="%")) {
            if (st.size()<2) throw std::runtime_error("malformed expression");
            double b = st.top(); st.pop();
            double a = st.top(); st.pop();
            if (tok=="+") st.push(a+b);
            else if (tok=="-") st.push(a-b);
            else if (tok=="*") st.push(a*b);
            else if (tok=="/") { if (b==0.0) throw std::runtime_error("division by zero"); st.push(a/b); }
            else st.push(std::fmod(a,b)); // include <cmath>
        } else {
            st.push(std::stod(tok)); // handles multi-digit, negatives, decimals
        }
    }
    if (st.empty()) throw std::runtime_error("empty result");
    return st.top();
}

Additional notes: the infix→postfix stage must either emit negative-number tokens (e.g. -5) or encode unary minus as a separate token; the evaluator above treats -5 as a number. If exact integer modulo is required, handle % with integer operands or document that fmod is used for floating-point. Finally, always validate stack size before popping and handle exceptional cases so malformed input fails cleanly.

Recommended Answers

All 2 Replies

You are doing integer math, change to floating point instead (i.e. from int to double or float).

You are doing integer math, change to floating point instead (i.e. from int to double or float).

You are right. Thanks!!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.