Thread: Issue with String input on a Postfix Expressions program.

  1. #1
    Registered User
    Join Date
    Sep 2011
    Location
    Hutto, TX
    Posts
    12

    Angry Issue with String input on a Postfix Expressions program.

    Not sure why I can not figure this out. I'm trying to take a string and use it for evaluating a Postfix Expressions. The input should be blank-separated. I can get the program to run just fine without spaces. However, I just can not get it to work with spaces. I have tried both cin.ignore() and getline( cin, postfixExp). Using the cin.ignore() I get an endless loop and when I use getline( cin, postfixExp) it will not allow me to input data. Below is my whole program. The problem I'm in countering is in the driver.cpp.

    Code:
    /*-- LStack.h --------------------------------------------------------------
     
      This header file defines a Stack data type.
      Basic operations:
        constructor:  Constructs an empty stack
        empty:        Checks if a stack is empty
        push:         Modifies a stack by adding a value at the top
        top:          Accesses the top stack value; leaves stack unchanged
        pop:          Modifies stack by removing the value at the top
        display:      Displays all the stack elements
      Note: Execution terminates if memory isn't available for a stack element.
    --------------------------------------------------------------------------*/
    
    #include <iostream>
    using namespace std;
    
    #ifndef LSTACK
    #define LSTACK
    
    typedef int StackElement;
    
    class Stack
    {
     public:
     /***** Function Members *****/
     /***** Constructors *****/
       Stack();
       /*-----------------------------------------------------------------------
        Construct a Stack object.
        Precondition:  None.
        Postcondition: An empty Stack object has been constructed
            (myTop is initialized to a null pointer).
      ------------------------------------------------------------------------*/
    
      Stack(const Stack & original);
      //-- Same documentation as in Figure 7.8
    
     /***** Destructor *****/
      ~Stack(); 
      /*------------------------------------------------------------------------
        Class destructor 
    
        Precondition:  None
        Postcondition: The linked list in the stack has been deallocated.
      ------------------------------------------------------------------------*/
    
     /***** Assignment *****/
      const Stack & operator= (const Stack & rightHandSide);
      /*------------------------------------------------------------------------
        Assignment Operator 
        Precondition:  rightHandSide is the stack to be assigned and is 
            received as a const reference parameter.
        Postcondition: The current stack becomes a copy of rightHandSide
            and a const reference to it is returned.
      ------------------------------------------------------------------------*/
    
      bool empty() const;
      /*------------------------------------------------------------------------
        Check if stack is empty.
        Precondition: None
        Postcondition: Returns true if stack is empty and false otherwise.
       -----------------------------------------------------------------------*/
    
      void push(const StackElement & value);
      /*------------------------------------------------------------------------
        Add a value to a stack.
    
        Precondition:  value is to be added to this stack
        Postcondition: value is added at top of stack provided there is space;
             otherwise, a stack-full message is displayed and execution is
             terminated.
       -----------------------------------------------------------------------*/
    
      void display(ostream & out) const;
      /*------------------------------------------------------------------------
        Display values stored in the stack. 
    
        Precondition:  ostream out is open.
        Postcondition: Stack's contents, from top down, have been output to out.
       -----------------------------------------------------------------------*/
    
      StackElement top() const;
      /*------------------------------------------------------------------------
        Retrieve value at top of stack (if any).
    
        Precondition:  Stack is nonempty
        Postcondition: Value at top of stack is returned, unless the stack is 
            empty; in that case, an error message is displayed and a "garbage
            value" is returned.
       -----------------------------------------------------------------------*/
    
      void pop();
      /*------------------------------------------------------------------------
        Remove value at top of stack (if any).
    
        Precondition:  Stack is nonempty.
        Postcondition: Value at top of stack has been removed, unless the stack
            is empty; in that case, an error message is displayed and
            execution allowed to proceed.
       -----------------------------------------------------------------------*/ 
    
     private:
       /*** Node class ***/
       class Node
       {
        public:
          StackElement data;
          Node * next;
          //--- Node constructor
          Node(StackElement value, Node * link = 0)
          /*-------------------------------------------------------------------
            Precondition:  None.
            Postcondition: A Node has been constructed with value in its data 
                part and its next part set to link (default 0).
           -------------------------------------------------------------------*/
          : data(value), next(link)
          {}
      };
    
      typedef Node * NodePointer;
      
      /***** Data Members *****/
      NodePointer myTop;      // pointer to top of stack
    
    }; // end of class declaration
    
    #endif
    
    
    //--- LStack.cpp -------------------------------------------------
     
    #include <new>
    using namespace std;
    
    #include "LStack.h"
    
    //--- Definition of Stack constructor
    Stack::Stack()
    : myTop(0)
    {}
    
    //--- Definition of Stack copy constructor
    Stack::Stack(const Stack & original)
    {
       myTop = 0;
       if (!original.empty())
       {
          // Copy first node
          myTop = new Stack::Node(original.top());
    
          // Set pointers to run through the stacksŐ linked lists
          Stack::NodePointer lastPtr = myTop,
                             origPtr = original.myTop->next;
    
          while (origPtr != 0)
          {
             lastPtr->next = new Stack::Node(origPtr->data);
             lastPtr = lastPtr->next;
             origPtr = origPtr->next;
          }
       }
    }
    
    //--- Definition of Stack destructor
    Stack::~Stack()
    {     
       // Set pointers to run through the stack
       Stack::NodePointer currPtr = myTop,  // node to be deallocated
                          nextPtr;          // its successor
       while (currPtr != 0)
       {
          nextPtr = currPtr->next;
          delete currPtr;
          currPtr = nextPtr;
       }
    }
    
    //--- Definition of assignment operator
    const Stack & Stack::operator=(const Stack & rightHandSide)
    {
       if (this != &rightHandSide)         // check that not st = st
       {
          this->~Stack();                  // destroy current linked list
          if (rightHandSide.empty())       // empty stack
             myTop = 0;
          else
          {                                // copy rightHandSide's list
             // Copy first node
             myTop = new Stack::Node(rightHandSide.top());
    
             // Set pointers to run through the stacks' linked lists
             Stack::NodePointer lastPtr = myTop,
                                rhsPtr = rightHandSide.myTop->next;
    
             while (rhsPtr != 0)
             {
                lastPtr->next = new Stack::Node(rhsPtr->data);
                lastPtr = lastPtr->next;
                rhsPtr = rhsPtr->next;
             } 
          }
       }
       return *this;
    }
    
    //--- Definition of empty()
    bool Stack::empty() const
    { 
       return (myTop == 0); 
    }
    
    //--- Definition of push()
    void Stack::push(const StackElement & value)
    {
       myTop = new Stack::Node(value, myTop);
    }
    
    //--- Definition of display()
    void Stack::display(ostream & out) const
    {
       Stack::NodePointer ptr;
       for (ptr = myTop; ptr != 0; ptr = ptr->next)
          out << ptr->data << endl;
    }
    
    //--- Definition of top()
    StackElement Stack::top() const
    {
       if (!empty())
          return (myTop->data);
       else
       {
          cerr << "*** Stack is empty "
                  " -- returning garbage ***\n";
          StackElement * temp = new(StackElement);  
          StackElement garbage = *temp;     // "Garbage" value
          delete temp;
          return garbage;
       }
    }
    
    //--- Definition of pop()
    void Stack::pop()
    {
       if (!empty())
       {
          Stack::NodePointer ptr = myTop;
          myTop = myTop->next;
          delete ptr;
       }   
       else
          cerr << "*** Stack is empty -- can't remove a value ***\n";
    }
    
    
    /*----driver.cpp----------------------------------------------------------
                      Driver program to test the Stack class.
      ----------------------------------------------------------------------*/
    
    #include <iostream>
    #include <iomanip>
    #include <string>
    using namespace std;
    	
    #include "LStack.h"
    
    int main()
    {
        Stack s; //Declare a stack of floats
        int i, choice = 1;
        string postfixExp;
        char token;
        float value, value1, value2;
        
    
        while (choice != 0)
        {
            cout << "1. Evaluate a postfix expression" << endl;
            cout << "0. Exit " << endl;
            cout << "Enter the number for the option: ";
    
            cin >> choice;
            switch(choice)
            {
                case 1: cout << "\nEvaluate a postfix expression\n";
                        cout << "Enter postfix expression with tokens separated by blanks: "
                             << endl;
                        cin >> postfixExp;
                        //cin.ignore();
                        //getline( cin, postfixExp); 
                        i = 0;
                        token = postfixExp[i];
                        while((i < postfixExp.size()) && (token != '='))
                        {
                            if(isdigit(token))
                            {
                                value = token - '0';
                                s.push(value);
                            }
                            else
                            {
                                value2 = s.top();
                                s.pop();
                                value1 = s.top();
                                s.pop();
                                switch(token)
                                {
                                    case '+': value = value1 + value2;
                                              break;
                                    case '-': value = value1 - value2;
                                              break;
                                    case '*': value = value1*value2;
                                              break;
                                    case '/': value = value1/value2;
                                              break;
                                }
                                s.push(value);
                            }
                        i++;
                        token = postfixExp[i];
                        }
                        value = s.top();
                        s.pop();
                        cout << "\nThe given postfix expression is " << postfixExp << endl;
                        cout << "\nThe value of the expression is " << value << endl;
                        break;
    
                case 0: cout << "Exiting the program\n";
                        break;
    
               default: cout << "Invalid option\n";
                        break;
            }
         cout << endl;
        }   
       system("pause");
       return 0;
    }
    Last edited by angel48797; 12-03-2011 at 10:13 AM.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Please show a sample of your entries.

    Jim

  3. #3
    Registered User
    Join Date
    Sep 2011
    Location
    Hutto, TX
    Posts
    12
    Quote Originally Posted by jimblumberg View Post
    Please show a sample of your entries.

    Jim
    Just a FYI this is what it should look like:

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: 1

    Evaluate a postfix expression
    Enter postfix expression with tokens separated by blanks:
    2 3 4 + *

    The given postfix expression is 234+*

    The value of the expression is 14

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: 0
    Exiting the program

    Press any key to continue . . .


    ********************
    But what I am getting with no code change is:

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: 1

    Evaluate a postfix expression
    Enter postfix expression with tokens separated by blanks:
    2 3 4 + *

    The given postfix expression is 2

    The value of the expression is 2

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: Invalid option

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: Invalid option

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: Invalid option

    Continues...........until I end the program.


    ********************
    When I add cin.ignore(); I get below as well:


    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: 1

    Evaluate a postfix expression
    Enter postfix expression with tokens separated by blanks:
    2 3 4 + *

    The given postfix expression is 2

    The value of the expression is 2

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: Invalid option

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: Invalid option

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: Invalid option

    Continues...........until I end the program.


    ********************
    When I remove cin >> postfixExp; and cin.ignore(); Then use getline( cin, postfixExp);
    I get this:


    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: 1

    Evaluate a postfix expression
    Enter postfix expression with tokens separated by blanks:
    *** Stack is empty -- returning garbage ***
    *** Stack is empty -- can't remove a value ***

    The given postfix expression is

    The value of the expression is 0

    1. Evaluate a postfix expression
    0. Exit
    Enter the number for the option: 0
    Exiting the program

    Press any key to continue . . .
    Last edited by angel48797; 12-03-2011 at 10:57 AM.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    When you used getline() with the spaces did you take into consideration that token may be a space? If it is a space then you just want to go to the next character and do no other processing.

    I placed the cin.ignore() right after the cin >> choice; and I was able to use getline() to get the entry and by checking for a space the program worked, producing the same answer with or without the spaces.

    Code:
         cin >> choice;
          cin.ignore();
          switch(choice)
          {
             case 1:
                cout << "\nEvaluate a postfix expression\n";
                cout << "Enter postfix expression with tokens separated by blanks: "
                     << endl;
                //cin >> postfixExp;
                //cin.ignore();
                getline( cin, postfixExp);
                i = 0;
                token = postfixExp[i];
                while((i < postfixExp.size()) && (token != '='))
                {
                   if(isspace(token))
                   {
                         // Blank body.
                   }else if(isdigit(token))
    Jim

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Oki.

    cin >> stringVar will stop reading at the first whitespace, so this is a non starter. You do want to use getline(). You have a "cin >> " to get the user choice previously, this'll leave a '\n' hanging around, so you need to cin.ignore() as well. It looks like you've got this far (in your third set of results).

    So hard part is done -- I think this error:

    *** Stack is empty -- returning garbage ***
    *** Stack is empty -- can't remove a value ***
    is simply because your code doesn't expect in input to have spaces. So for "2 3 4 + *", the code reads the digit 2, then next it tries to read the space before the digit 3. The code thinks that things that aren't digits are operators, so runs off trying to get operands from the stack.

    You need to skip whitespace and make sure "token" is set to a meaningful character. It'd probably be a good idea to have some basic error checking, e.g. a default: case in the switch statement.


    Also, your while loop will access 1 past the last element of the string (because it is incremented then used to access the string at the end of the loop). Since the loop then terminates without doing anything, the value isn't ever used, so you might not see a runtime failure. It's not good though -- the access of the ith element should be at the top of the loop.

  6. #6
    Registered User
    Join Date
    Sep 2011
    Location
    Hutto, TX
    Posts
    12
    Thank you soo much.
    I spent 3 hours trying to figure this out. I looked through 3 different C++ books and even tried searching with Google. I came here as a last resort.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ Program to evaluate expressions
    By DMEngOba in forum C++ Programming
    Replies: 5
    Last Post: 05-25-2009, 09:16 PM
  2. evaluate postfix expressions read from infile
    By killmequick in forum C Programming
    Replies: 5
    Last Post: 10-02-2008, 01:19 PM
  3. Stack that evaluates postfix expressions
    By killmequick in forum C Programming
    Replies: 7
    Last Post: 10-01-2008, 06:23 PM
  4. string input issue
    By clearrtc in forum C Programming
    Replies: 9
    Last Post: 08-25-2006, 11:52 AM
  5. postfix expressions
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 12-12-2001, 01:32 PM