/******************************************************************
 *      Equation parser utility Class V.0.1                       *
 *                                                                *
 *      Author: Iamthwee                                          *
 *                                                                *
 *      Filename: Equation.cpp                                    *
 *                                                                *
 *      Purpose: To provide easy functions for evaluating         *
 *               mathematical expressions with multiple           *
 *               nesting. Permittable operators:                  *
 *               +-/*^()                                          *
 *                                                                *
 *                                                                *
 *      Rights:  The proprietary rights are owned by me           *
 *               alone.                                           *
 *                                                                *
 *               You may not take credit for writing              *
 *               this, sell it, or remove this signature.         *
 *                                                                *
 *      Notes:   Two main methods exist:                          *
 *               -set()                                           *
 *               -rpn()                                           *
 *               -An example is given for clarity.                *  
 *               -Error checks are incomplete                     *
 *                                                                *
 *                                                                *
 ******************************************************************/
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <vector>
#include <cmath>
 
using namespace std;
 
class Equation
{
//define public member functions
public:
        Equation(); //default constructor
        ~Equation();//default destructor
        
        void rpn(); //main method
        void set(string); //main method
        
        
        double Eval(vector <string> & s);
        void Convert(const string & Infix, string & Postfix);
        bool TakesPrecedence(char OperatorA, char OperatorB);
        bool IsOperand(char ch);
        bool IsOperator(char ch);
        bool IsNumber(char ch);
        string ChangeMe(string);
        string InsertSpace(string);
        bool CheckValid(string);
        void Next(string);
        
//define private member functions
private: 
        string Infix;
};

//Polynomial constructor
Equation::Equation() 
{
  Infix = "";  
}

//Polynomial destructor.
Equation::~Equation() 
{
 //do its work
}

//Setter method
void Equation::set(string a)
{
    Infix = a;
}

bool Equation::IsOperand(char ch)
{
   if (
       ((ch >= '0') && (ch <= '9'))||
       (ch == 'v') ||
       (ch == 'y') ||
       (ch == '.') 
       )
      return true;
   else
      return false;
}

bool Equation::IsNumber(char ch)
{
   if (
       ((ch >= '0') && (ch <= '9'))||
       (ch == '.')
       )
       return true;
    else
       return false;
}

bool Equation::IsOperator(char ch)
{
    if ((ch == '+') ||
        (ch == '-') ||
        (ch == '*') ||
        (ch == '/') ||
        (ch == '^'))
        return true;
     else
        return false;
}
        

bool Equation::TakesPrecedence(char OperatorA, char OperatorB)
{
   if (OperatorA == '(')
      return false;
   else if (OperatorB == '(')
      return false;
   else if (OperatorB == ')')
      return true;
   else if ((OperatorA == '^') && (OperatorB == '^'))
      return false;
   else if (OperatorA == '^')
      return true;
   else if (OperatorB == '^')
      return false;
   else if ((OperatorA == '*') || (OperatorA == '/'))
      return true;
   else if ((OperatorB == '*') || (OperatorB == '/'))
      return false;
   else
      return true;   
}

void Equation::Convert(const string & Infix, string & Postfix)
{
   stack <char> OperatorStack;
   char TopSymbol, Symbol;
   int k;

   for (k = 0; k < Infix.size(); k++)
   {
      Symbol = Infix[k];
      if (IsOperand(Symbol))
         Postfix = Postfix + Symbol;
      else
      {
         while ((! OperatorStack.empty()) &&
            (TakesPrecedence(OperatorStack.top(), Symbol)))
            {
            TopSymbol = OperatorStack.top();
            OperatorStack.pop();
            Postfix = Postfix + TopSymbol;
            }
         if ((! OperatorStack.empty()) && (Symbol == ')'))
            OperatorStack.pop();   // discard matching (
         else
            OperatorStack.push(Symbol);
      }
   }

   while (! OperatorStack.empty())
   {
      TopSymbol = OperatorStack.top();
      OperatorStack.pop();
      Postfix = Postfix + TopSymbol;
   }
}

string Equation::ChangeMe(string tmp)
{
    for(int i = 0; i <tmp.length(); i++)
    {
      if(IsNumber(tmp[i])==true)
      {
          if(IsNumber(tmp[i+1])==false)
          {  
              tmp.insert(i+1, "v");
          }    
      }    
    }
    // -ve * -ve case
    for (int i = 0; i < tmp.length(); i++)
    {
        if(tmp[i]=='-')
        {
            if((tmp[i-1]!='v')&&(tmp[i-1]!=')'))
            {
               tmp.replace(i,1,"y"); 
            }
        }
    } 
    return tmp;
}  

string Equation::InsertSpace(string tmp)
{
    for(int i = 0; i < tmp.length(); i++)
    {
         if (IsOperator(tmp[i])==true)
          {
            tmp.insert(i+1, " ");
            //Insert a space after all
            //found operators
          } 
           else if( tmp[i]=='v' )
           {
              tmp.replace(i,1," ");
              //replace the v with a space
              //for clarity
           }               
    }
    
    for (int i = 0; i < tmp.length(); i++)
    {
        if(tmp[i]=='y')
        {
             tmp.replace(i,1,"-");
        }
     }    
    return tmp; 
}   

bool Equation::CheckValid(string tmp)
{
    //incomplete
    //Changed check that consecutive '+', '-' 
    //signs do not exist
    for (int i = 0; i < tmp.length(); i++)
    {
        if((tmp[i]=='+')||(tmp[i]=='-'))
        {
            if((tmp[i+1]=='+')||(tmp[i+1]=='-'))
            {
                return false;
            }
        }
    }            

    string array = "0123456789+-*/^().";

    int count = 0;
    for (int i = 0; i < tmp.length(); i++)
    {
        for(int j = 0; j < array.length(); j++)
        {
            if(tmp[i]==array[j])
            {
               count++;
            }
        }
    }
    
    if (count == tmp.length())
    {
      return true;   
    }
    else
    {   
      return false;   
    }
            
} 

void Equation::Next(string tmp)
{
  vector <string> array; 
  
  int spaces = 0;
  for ( int a = 0; a < tmp.length(); a++ )
  {
      if(tmp[a]==' ')
      {
          spaces++;
      }
  }        
   string token;
   istringstream iss(tmp);
   while ( getline(iss, token, ' ') )
   {
      array.push_back(token);
   }   
    
  stack <string> my_stack;//initialise stack
  vector <string> temp;
  string ch;
  
  for (int i = 0; i < spaces; i++)
  {
      string s;
      s = array[i]; //make it easier to read
      
      if ((s!="+")&&(s!="*")&&(s!="-")&&(s!="^")&&(s!="/"))
      {
        my_stack.push(s);
        //push numbers onto the stack
      }
         else //i.e if it encounters an operator
         {
               my_stack.push(s);//push operator onto stack
               
               for ( int i = 0; i < 3; i++ )
               {
                 temp.push_back(my_stack.top());
                 my_stack.pop(); //erase from the stack
               }

               double z;
               z = Eval(temp);
               ostringstream outs; 
               outs << z;   // Convert value into a string.
               ch = outs.str(); 

               my_stack.push(ch);
               temp.clear();
          }                
  }
  cout << ch;  
  
} 

double Equation::Eval(vector <string> & temp)
{
    
    string a,b,c;
    a = temp[2]; b = temp[0]; c = temp[1];
    double x,y,z;
    istringstream ins,inse;
    ins.str(a); inse.str(c);
    ins >> x;
    inse >> y;
    
     if (b == "+")
     {
        z = x + y;
        return z;
     } 
     else if (b == "-")
     {
        z = x - y;
        return z;
     } 
     else if (b == "*")
     {
        z = x * y;
        return z;
     }
     else if (b == "/")
     {
        z = x / y;
        return z;
     }
     else if (b == "^")
     {
        z = pow(x,y);
        return z;
     }   
                           
}    

void Equation::rpn()
{
    string Postfix;
    if(CheckValid(Infix)==true)
    {

      string temp;
      temp = ChangeMe(Infix); 
      
      Convert(temp, Postfix);
      
      cout << "****Postfix****\n" << endl
      << InsertSpace(Postfix);

      string hold;
      hold = InsertSpace(Postfix);
         
      cout << "\n\n****Solution****\n\n";
      Next(hold);
      cout << "\n\n";
    }
    else
    {
        cout << "Expression invalid retard!\n";
    }
}      

int main()
{
    //test cases
    Equation a,b,c;
    
    a.set("3-(5-(7+1))^2*(-5)+13");
    a.rpn();
    
    b.set("3.2+(6.34*(1.7))");
    b.rpn();
    
    c.set("3+4*2/(1-5)^2");
    c.rpn();
    
    cin.get();
    return 0;
    
}

Started window cleaning after uni. Got my first ladder, bucket and sponge and since then I haven't looked back.

3
Contributors
2
Replies
20
Views
10 Years
Discussion Span
Last Post by William Hemsworth
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.