Solved

Stack Based Calculator- Due in 8 hours

Posted on 2007-11-25
33
451 Views
Last Modified: 2013-11-13
Hello Everyone,
I usually don't use sites like this but I really need help with a program I must write using c++. I have tried to write this program but  it is a complete mess so I am not going to bother posting it. Anyway, this is what I must Do :

Design and build a parsing calculator.  Your program must

     accept a string of the form  12 * 3 / (123 + 4) ,
    do the specified calculation,  and
     display the result.  

The program    should continue to ask for input until the user decides to quit.  

In addition,  this program must use a stack to implement the calculation.  You’ll have to

     accept the input as a character string,  
     break it up into its component parts,  and
     convert it to numbers and operators, and
     do the calculation.Notes:
    1.  Instead of the usual precedence, evaluate expressions from left
        to right, but make sure that operations done inside parentheses
        are done first.  For example, the expression  22 *  3 + ( 2 * 3) ,  
        should be evaluated:          22 * 3 +  ( 6)      66 + 6      
 Look up and use the following standard library functions to help with your design:              
  char* strtok(char*, char*)              double atof(char*)

Thanks for your time,
Kumar
0
Comment
Question by:kk_hutton
  • 11
  • 10
  • 8
  • +3
33 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 20348450
Looks like you haven't started to do your homework. If so, would be almost impossible to terminate it in 8 hours, you have to learn lot of concepts. Even worst in these hours.
Could you post some initial code to try to help you?
0
 

Author Comment

by:kk_hutton
ID: 20348463
Here is my code . Its a mess and I think Im better off rewriting it. Everything works except for evaluating parenthesis :



#include <iostream>
#include <stdio.h>

#include <string.h>
#include <stddef.h>
#include <Stdlib.h>

using namespace std;
#define DEAFAULT_SIZE 20
class Stack
{
private:
   int size;
   int top;
   char* values;
public:
   Stack(int size = DEAFAULT_SIZE);
   virtual ~Stack();
   bool isFull();
   bool isEmpty();
   void push(char input);
   char pop();
};
Stack::Stack(int size)
{
   this->size = size;
   values = new char[size];
   top = -1;
}
Stack::~Stack()
{
   delete[] values;
}
bool Stack::isFull()
{
   if(top < size-1)
   {
      return false;
   }
   else
   {
      return true;
   }
}
bool Stack::isEmpty()
{
   if(top == -1)
   {
      return true;
   }
   else
   {
      return false;
   }
}
void Stack::push(char input)
{
   if(!isFull())
   {
      top++;
      values[top] = input;
   }
}
char Stack::pop()
{
   char retVal;
   if(!isEmpty())
   {
      retVal = values[top];
      top--;
   }
   return retVal;
}
class Stackdouble
{
private:
   int size;
   int top;
   double* values;
public:
   Stackdouble(int size = DEAFAULT_SIZE);
   virtual ~Stackdouble();
   bool isFull();
   bool isEmpty();
   void push(double input);
   double pop();
};
Stackdouble::Stackdouble(int size)
{
   this->size = size;
   values = new double[size];
   top = -1;
}
Stackdouble::~Stackdouble()
{
   delete[] values;
}
bool Stackdouble::isFull()
{
   if(top < size-1)
   {
      return false;
   }
   else
   {
      return true;
   }
}
bool Stackdouble::isEmpty()
{
   if(top == -1)
   {
      return true;
   }
   else
   {
      return false;
   }
}
void Stackdouble::push(double input)
{
   if(!isFull())
   {
      top++;
      values[top] = input;
   }
}
double Stackdouble::pop()
{
   double retVal;
   if(!isEmpty())
   {
      retVal = values[top];
      top--;
   }
   return retVal;
}
class Evaluate
{
public:
   Stack operators;
   Stackdouble operands;
   Stack operators2;
   Stackdouble operands2;
   Evaluate();
   double EvaluateEx();
   double EvaluateParenthesis(Stack &one, Stackdouble &two,double &value);
   void getInput();
};
 Evaluate::Evaluate()
{
}

double Evaluate::EvaluateEx()
{
   double value = 0.0;
   double one;
   double two;
      char array[] = "  ( 8 + 0 ) + ( 7 + 0 ) ";
   
   char delims[] = " ";
   char *token = NULL;
   token = strtok( array, delims );
   
   operators.push(*token);
   do
   {
      printf("token: %s\n", token);
       switch(*token)
      {
         case '+':
         this->operators.push(*token);
         continue;
         case '-':
         this->operators.push(*token);
         continue;
         case '*':
         this->operators.push(*token);
         continue;
         case '/':
            this->operators.push(*token);
         continue;
         case ')':
         this->operators.push(*token);
         continue;
         
         case '(':
            //cout << "nigga ";
         this->operators.push(*token);
         continue;
         


         default:
            double convert =  atof(token);

         this->operands.push(convert);
         continue;
      }
   }
   while (token = strtok(NULL, " "));
   do
   {
      char ope;



      one = operands.pop();
      //cout << one << "\n";
      ope = operators.pop();
      //cout << ope << "\n";
      two = operands.pop();
      //cout << two;
      if(ope == ')')
      {
         ope = operators.pop();
         one = operands.pop();
         two = operands.pop();
         if(ope == '+')
         {
         
         value = one + two;
         this->operands.push(value);
         //cout << "\n" << value;
     
         }
      if(ope == '-')
      {
      value = two - one;
      this->operands.push(value);
      cout << "\n \n" << value;
     
      }
      if(ope == '*')
      {
      value = two * one;
      this->operands.push(value);
     
      }
      if(ope == '/')
      {
      value = two / one;
      this->operands.push(value);
      }
         ope = operators.pop();
         if( ope == '(')
            break;
      }

         
         
     
      if(ope == '+')
      {
     
      value = one + two;
      this->operands.push(value);
     // cout << "\n" << value;
      continue;
      }
      if(ope == '-')
      {
      value = two - one;
      this->operands.push(value);
      continue;
      }
      if(ope == '*')
      {
      value = two * one;
      this->operands.push(value);
      continue;
      }
      if(ope == '/')
      {
      value = two / one;
      this->operands.push(value);
      continue;
      }
     
     

     
       
   }

   
   while(!this->operators.isEmpty());
   
     
   return value;
}
     
   
     
     
     
     
 





   


int main()
{
   Evaluate k;
   double r = k.EvaluateEx();
   cout << "\n \n \n" << r;
   
 

}
     
     
     
   
     



0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348481
--> eliminate the paranthesis using stack
12*3/(1+(1+1))
     -> push current expression on stack.
     -> parse for the first paranthesis expression. and push it on stack. at this stage you wud have stack as
12*3/X
then
1+(1+1)
     -> repeat step 2.
Now stack would be as  
12*3/X
then
1+X
then
1+1

   -> repeat stack you until you dont find any expression with paranthesis.

now resolve the stack.

12*3/X
then
1+X
then
1+1

becomes

12*3/X
then
1+X
then
2

which becomes

12*3/X
then
1+2

which becomes

12*3/X
then
3

which becomes

12*3/3

which you can solve. :)


Here i have taken 'X' as a token to identify the place to put the value of the expression of the popped stack expression.


Hope it helps.
0
 

Author Comment

by:kk_hutton
ID: 20348499
Thanks for the help but I get the concept but Im having trouble implementing it into my code. I seem to get zero values whenever I try to evaluate parenthesis.
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348532
>>void Stack::push(char input)
according to the logic i described, you should have passed the whie expression on to the stack.

make it:
void Stack::push(char* input)

-> why are you using class Stackdouble. seems like its of no use.

-> nowhere i cud find the logic of finding the paranthesized expression.
if you find '(' then find CORRESPONDING ')'

you are pushing tokens on to the stack even when its '('. you should have pushed it only when you find CORRESPONDING ')' (not push on stack even if it is ')' but not the corresponding one)

Kumar, please revamp your code fixing above said flaws and revert back. We can discuss further.


Hope it Helps.

regards,
James

0
 

Author Comment

by:kk_hutton
ID: 20348600
but see I have to use the strtok() and atof() methods in order to get credit for this assignment so it seems as if i should split the input into tokens and then add it to the stack. I was wondering if I should use one stack or two stack ?
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348648
atof() -> u can always use it while calculating the popped up stack expression
strtok() -> u can use it as :

case '(' :
            1. set a flag to true;
            2. parse further and record the string in between:
                       if you get the next token as ')', take the string as expression. replace it with 'X' in the pushed up expression and push the string on to the stack.
                       if you get next token as '(' then repeat step 2.
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348653
one stack is okay.
while popping up do a check for paranthesis.
if paranthesis is still their. again repeat the above said 2 steps.
0
 

Author Comment

by:kk_hutton
ID: 20348683
Im still having the same problem. Heres my simplified code :

double Evaluate::EvaluateEx()
{
   double value = 0.0;
 
      char array[] = "   ( 7 + 9 ) + ( 6 + 3 )  ";
   
   char delims[] = " ";
   char *token = NULL;
   token = strtok( array, delims );
   
   stack.push(*token);
   do
   {
      printf("token: %s\n", token);
      this->stack.push(*token);
      continue;
   }
   while (token = strtok(NULL, " "));
   char one,two,three;

   while(!stack.isEmpty())
   {
      one = stack.pop();
      two = stack.pop();
      three = stack.pop();
     
     
      if(two == '+')
      {
         
         value +=  atof(&one) + atof(&three);
            continue;
      }
      if(two == ')')
      {
         if(two == '(')
            break;
         continue;
      }
   }

Sorry If Im hasseling you man but Im really confused
     

   
     
     

     
       
 
   
     
   return value;
}
     
   
     
     
     
     
 



int main()
{
   Evaluate k;
   double r = k.EvaluateEx();
   cout << "\n \n \n" << r;
   
 

}
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348705
>>char one,two,three;
why are you pushing and popping only chars on to the stack. I mean we have to push the expressions on the it. right?

please use char* instead of it. then we will take it forward.

Not a prblem. I am here to help you out. :)
0
 

Author Comment

by:kk_hutton
ID: 20348726
alrite i Have changed everythingto char* pointers but now my program freezes. Please check my code and see what I Did wrong :

#include <iostream>
#include <stdio.h>

#include <string.h>
#include <stddef.h>
#include <Stdlib.h>

using namespace std;
#define DEAFAULT_SIZE 20
class Stack
{
private:
   int size;
   int top;
   char* values;
public:
   Stack(int size = DEAFAULT_SIZE);
   virtual ~Stack();
   bool isFull();
   bool isEmpty();
   void push(char *input);
   char* pop();
};
Stack::Stack(int size)
{
   this->size = size;
   values = new char[size];
   top = -1;
}
Stack::~Stack()
{
   delete[] values;
}
bool Stack::isFull()
{
   if(top < size-1)
   {
      return false;
   }
   else
   {
      return true;
   }
}
bool Stack::isEmpty()
{
   if(top == -1)
   {
      return true;
   }
   else
   {
      return false;
   }
}
void Stack::push(char *input)
{
   if(!isFull())
   {
      top++;
      values[top] = *input;
   }
}
char* Stack::pop()
{
   char *retVal;
   if(!isEmpty())
   {
      *retVal = values[top];
      top--;
   }
   return retVal;
}

class Evaluate
{
public:
   Stack stack;
   
   Evaluate();
   double EvaluateEx();
 
};
 Evaluate::Evaluate()
{
}

double Evaluate::EvaluateEx()
{
   double value = 0.0;
 
      char array[] = " ( 6 + 3 ) ";
   
   char delims[] = " ";
   char *token = NULL;
   token = strtok( array, delims );
   
   stack.push(token);
   do
   {
      printf("token: %s\n", token);
      this->stack.push(token);
      continue;
   }
   while (token = strtok(NULL, " "));
   char *one,*two,*three;
//   double value;
   while(!stack.isEmpty())
   {
      one = stack.pop();
      two = stack.pop();
      three = stack.pop();
     
     
      if(*two == '+')
      {
         
         value +=  atof(one) + atof(three);
            continue;
      }
      if(*two == ')')
      {
         cout << "hello";
         two = stack.pop();
         if(*two == '(')
            break;
         if(*two == '+')
         {
            value +=  atof(one) + atof(three);
            break;
         }
         continue;
      }
   }
     

   
     
     

     
       
 
   
     
   return value;
}
     
   
     
     
     
     
 





   


int main()
{
   Evaluate k;
   double r = k.EvaluateEx();
   cout << "\n \n \n" << r;
   
 

}
   
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348865
>>values[top] = *input;
>>*retVal = values[top];

use functions like strcpy.
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348870
>>char* values;
ur stack is able to hold only one expression.
make it an array or a vector.

0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20348875
Kumar, please rectify the code in the lines of above two posts and revert back.
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20348885
you can define a stack template.
You'd better to use 2 stacks, one is used to pocess data, the other is used to process operators.
I will show you a sample below.
#define DEAFAULT_SIZE 20

template <class Type>

class CCStack

{

private:

    Type* base;

    Type* top;

    int size;

public:

    CCStack(int size = DEAFAULT_SIZE);

    ~CCStack();

    bool isFull() const;   //Judge the Stack is full or not.

    bool isEmpty() const;   //Judge the Stack is empty or not.

    bool clearStack();      //(Temporary Scheme) to reset the Stack.

    bool getTop(Type &item) const;  //get the top element

    bool push(const Type &item); //add item to stack

    bool pop(Type &item);        //pop top into item

};
 

template <class Type>

CCStack<Type>::CCStack(int size)

{

    if(!(base=new Type[size*sizeof(Type)]))

    {

        cout << "Error!Failure to apply the memory space." << endl;

        exit(-1);

    }

    top = base;

}
 

template <class Type>

CCStack<Type>::~CCStack()

{

    delete[] base;

    base = NULL;

}
 

template <class Type>

bool CCStack<Type>::push(const Type &item)

{

    if(!isFull())

    {

       *top = item;

       top = top+sizeof(Type);

    }

    return true;

}
 

template <class Type>

bool CCStack<Type>::pop(Type &item)

{

    if(!isEmpty())

    {

       item = *top;

       top = top-sizeof(Type);

    }

    return true;

}
 

template <class Type>

bool CCStack<Type>::isFull()

{

    if(top >= base + size*sizeof(Type))

    {

        return true; 	

    }

    else

    {

        return false;

    }

}
 

template <class Type>

bool CCStack<Type>::isEmpty()

{

    if( top == base )

    {

        return true; 	

    }

    else

    {

        return false;

    }

}

Open in new window

0
 
LVL 4

Accepted Solution

by:
yuy2002 earned 500 total points
ID: 20349320
you have to define the priority of the operators, and u can refer to the code below.


regards,
charles
#include <iostream>

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

using namespace std;

#define DEAFAULT_SIZE 20

template <class Type>

class CCStack

{

private:

    Type* base;

    Type* top;

    int size;

public:

    CCStack(int size = DEAFAULT_SIZE);

    ~CCStack();

    bool isFull() const;   //Judge the Stack is full or not.

    bool isEmpty() const;   //Judge the Stack is empty or not.

    bool getTop(Type &item) const;  //get the top element

    bool push(const Type &item); //add item to stack

    bool pop(Type &item);        //pop top into item

};
 

template <class Type>

CCStack<Type>::CCStack(int size)

{

    if(!(base=new Type[size*sizeof(Type)]))

    {

        cout << "Error!Failure to apply the memory space." << endl;

        exit(-1);

    }

    top = base;

}
 

template <class Type>

CCStack<Type>::~CCStack()

{

    delete[] base;

    base = NULL;

}
 

template <class Type>

bool CCStack<Type>::getTop(Type &item) const

{
 

    if(top > base)

    {

        item = *(top-sizeof(Type));

    }

    else

    {

        return false;

    }

    return true;

}
 

template <class Type>

bool CCStack<Type>::push(const Type &item)

{

    if(!isFull())

    {

       *top = item;

       top = top+sizeof(Type);

    }

    return true;

}
 

template <class Type>

bool CCStack<Type>::pop(Type &item)

{

    if(!isEmpty())

    {

       top = top-sizeof(Type);

	   item = *top;

    }

    return true;

}
 

template <class Type>

bool CCStack<Type>::isFull() const

{

    if(top >= base + size*sizeof(Type))

    {

        return true; 	

    }

    else

    {

        return false;

    }

}
 

template <class Type>

bool CCStack<Type>::isEmpty() const

{

    if( top == base )

    {

        return true; 	

    }

    else

    {

        return false;

    }

}
 

template <class Type>

class CCOperator

{

private:

public:

    CCOperator();

    ~CCOperator();

    char compareOpt(char temp_first,char temp_second);

    Type standardOpt(Type temp_prefix,char temp_opt,Type temp_postfix);

    bool isOpt(char c);

};

template <class Type>

CCOperator<Type>::CCOperator()

{
 

}
 

template <class Type>

CCOperator<Type>::~CCOperator()

{
 

}

template <class Type>

char CCOperator<Type>::compareOpt(char temp_first,char temp_second)

{

    char pri;

    switch(temp_second)

    {

        case '+':

        case '-':

            if(temp_first=='('||temp_first=='=')

            {

                pri='<';

            }

            else

            {

                pri='>';

            }

            break;

        case '*':

        case '/':

            if(temp_first=='*'||temp_first=='/'||temp_first==')')

            {

                pri='>';

            }  

            else

            {

                pri='<';

            }

            break;

        case '(':

            if(temp_first==')')

            {

                printf("\n\t Expression form error\n");

                exit(-1);

            }

            else

            {

                pri='<';

            }  

            break;

        case ')':

            switch(temp_first)

            {

            case'(':

                pri='=';

                break;

            case'=':

                printf("\n\t Expression form error\n");

                exit(-1);

            default :

                pri='>';

            }

            break;

        case'=':

            switch(temp_first)

            {

            case'=':

                pri='=';

                break;

            case'(' :

                printf("\n\t Expression form error\n");

                exit(-1);

            default :

                pri='>';

            }

            break;

        

        default:

            {

            	printf("\n\t Unknown operator \n");

            	pri = 0;

            }

            break;

     }    

     return pri;

}
 

template <class Type>

Type CCOperator<Type>::standardOpt(Type temp_prefix,char temp_opt,Type temp_postfix)

/* Pre: Already have two Nums and one Opt .

   Post:Return the result of calculate. */

{

    Type temp_result;

    switch(temp_opt)

    {

        case'+':temp_result=temp_prefix+temp_postfix;break;

        case'-':temp_result=temp_prefix-temp_postfix;break;

        case'*':temp_result=temp_prefix*temp_postfix;break;

        case'/':

            if(temp_postfix != 0)

            {

                temp_result=temp_prefix/temp_postfix;

                

            }

            else

            {

                printf("\n\t Calculate error \n");

            }

            break;

        default:

            {

            	printf("\n\t Unsupport operator \n");

            	break;

            }

    }

    return temp_result;

}
 

template <class Type>

bool CCOperator<Type>::isOpt(char c)

{

    switch(c)

    {

        case '+':

        case '-':

        case '*':   

        case '/':

        case '(':

        case ')':

        case '=':

            return true;

        default:

            return false;

     }

}
 

bool doCalculate()

{

    CCStack<double> stackSZ;

    CCStack<char> stackZF;

    CCOperator<double> calculatorOpt;
 

    char temp_opt;                      //Temporary Operation Saver.

    double temp_number;                 //Temporary Number Saver.

    double temp_prefix,temp_postfix;    //Temporary Opt Prefix(Number),Postfix(Number) Saver.

    double temp_final;                  //Temporary Midway Final Saver.

    double final;                       //The Final Calculate Result.

    char temp_c;                        //Temporary Get One Char.

    char convert_str2double[100];       //Use For Convert String To Double.

    int judge=0;                        //The Currently Digit Saver.
 

    stackZF.push('=');

    printf("\nPlease input your expression:");

    temp_c=getchar();  //Get The First Char.

    

    judge++;

    stackZF.getTop(temp_opt);   // Get the Top Element Of the StackZF.

    while(temp_c != '=' || temp_opt != '=')

    {

        if(calculatorOpt.isOpt(temp_c)) // Judge "temp_c" is Opt or not.

        {

            switch(calculatorOpt.compareOpt(temp_opt,temp_c)) // Return The PRI State: ">" , "<" or "=".

            {

            case '<': //Top Element PRI < temp_c.

                stackZF.push(temp_c);

                temp_c=getchar();

                stackZF.getTop(temp_opt);

                break;

            case '='://Shuck Off The "( )" And Calculate "temp_final".

                stackZF.pop(temp_opt);

                stackZF.getTop(temp_opt);

                temp_c=getchar();

                break;

                

            case '>'://Pop From the stackZF And stackSZ and Do Calculate.

                if(temp_opt=='+'||temp_opt=='-'||temp_opt=='*'||temp_opt=='/')

                {

                    stackZF.pop(temp_opt);

                    stackSZ.pop(temp_postfix);

                    stackSZ.pop(temp_prefix);

                    temp_final=calculatorOpt.standardOpt(temp_prefix,temp_opt,temp_postfix); //Calculate Out The temp_final.

                    stackSZ.push(temp_final);

                    stackZF.getTop(temp_opt);

                    break;

                }

                else

                {

                    break;

                }

            }

        }

        else if((temp_c>='0' && temp_c<='9') || temp_c=='.') //Combination The Number(Double)

        {

            int i=0;

            do

            {

                convert_str2double[i]=temp_c;

                i++;

                temp_c=getchar();

            }while((temp_c<='9' && temp_c>='0') || temp_c=='.');

            convert_str2double[i]=0;

            temp_number=atof(convert_str2double); //Use The Function atof() to Convert A String Var To A Double One.

            stackSZ.push(temp_number);

        }

        else

        {

            //ERROR

        }

    }

    stackSZ.getTop(final);

    

    printf("\nResult:%15.15f",final);

    
 

    return 0;

}

int main()

{

    doCalculate();

    return 0;

}

Open in new window

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 7

Expert Comment

by:lucky_james
ID: 20349688
yuy,
       its against the EE ethics to help somebody in his/her assignment with code directly. It would be nice if you give him some comments so that he can rectify and LEARN.

Best Regards,
James
0
 
LVL 7

Expert Comment

by:lucky_james
ID: 20350079
Kumar, as a new comer to this site, hope you wont mind my above comment. But its a sort of rule.....

proceeeding with ur posted code:
in ur class STack:
>>   char* values;
try making it a vector of char*. My suggestion is to work with vector of CString.
all you need to do as additional change in class stack is to convert CString to char* and vice versa.

For that:
char* to CString  -> CString(char*) can work.

CString to char* -> use wcstombs_s method.check out :
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=180377&SiteID=1

in ur evaluateEx method:

>>   token = strtok( array, delims );
>>   stack.push(token);
>>   do
>>   {
>>      printf("token: %s\n", token);
>>      this->stack.push(token);
>>      continue;
>>   }

dont use the variable names as 'array', it a keyword in c++.
u r parsing it in tokens.
here only you can do :
1. identify the innermost paranthesis expression. Let term it as EXP. If no expression, then parse the whole string from left to right and calculate the value.
2. push this whole string (i.e. char*) after replacing the EXP with token 'X'
3. pop the stack, evaluate the expression and store the value. again pop the stack, Replace 'X' with the stored value. Then GOTO 1.


So,you need to change your eaveluateEx method code and the funda of stack class (becoz it is storing only chars not the strings and you need a stack of strings).



Let me know where you are stuck now. Hope it helps.

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20350245
Kumar,
 
you opened a new thread in http:Q_22981924.html but the maximum points for one question is 500 points. You should go to http://www.experts-exchange.com/Community_Support/General/ and ask a 0 points question to delete the second thread (as it has two answers only).

Regards, Alex
0
 

Author Comment

by:kk_hutton
ID: 20352133
charles,

If you could explain your code a little more that would be great. I have no exsprience with templates .
0
 

Author Comment

by:kk_hutton
ID: 20352607
I have changed my code to this :

#include <iostream>
#include <stdio.h>
#include <string>

#include <math.h>
#include "stdafx.h"
#include <stdlib.h>

#define DEAFAULT_SIZE 20
//using namespace std;
template <class evaluate>

class CCStack
{
private:
    char* base;
    char* top;
    int size;
public:
    CCStack(int size = DEAFAULT_SIZE);
    ~CCStack();
    bool isFull() const;   //Judge the Stack is full or not.
    bool isEmpty() const;   //Judge the Stack is empty or not.
    bool getTop(char &item) const;  //get the top element
    bool push(const char &item); //add item to stack
    bool pop(char &item);        //pop top into item
};
 
template <class evaluate>
CCStack<evaluate>::CCStack(int size)
{
    if(!(base=new char[size*sizeof(char)]))
    {
        cout << "Error!Failure to apply the memory space." << endl;
        exit(-1);
    }
    top = base;
}
 
template <class evaluate>
CCStack<evaluate>::~CCStack()
{
    delete[] base;
    base = NULL;
}
 
template <class evaluate >
bool CCStack<evaluate>::getTop(char &item) const
{
 
    if(top > base)
    {
        item = *(top-sizeof(char));
    }
    else
    {
        return false;
    }
    return true;
}
 
template <class evaluate>
bool CCStack<evaluate>::push(const char &item)
{
    if(!isFull())
    {
       *top = item;
       top = top+sizeof(item);
    }
    return true;
}
 
template <class evaluate>
bool CCStack<evaluate>::pop(char &item)
{
    if(!isEmpty())
    {
       top = top-sizeof(char);
         item = *top;
    }
    return true;
}
 
template <class evaluate>
bool CCStack<evaluate>::isFull() const
{
    if(top >= base + size*sizeof(char))
    {
        return true;       
    }
    else
    {
        return false;
    }
}
 
template <class evaluate>
bool CCStack<evaluate>::isEmpty() const
{
    if( top == base )
    {
        return true;       
    }
    else
    {
        return false;
    }
}
 
template <class evaluate>
class CCOperator
{
private:
public:
    CCOperator();
    ~CCOperator();
    char compareOpt(char temp_first,char temp_second);
    double standardOpt(double temp_prefix,char temp_opt,double temp_postfix);
    bool isOpt(char c);
};
template <class evaluate>
CCOperator<evaluate>::CCOperator()
{
 
}
 
template <class evaluate>
CCOperator<evaluate>::~CCOperator()
{
 
}
template <class evaluate>
char CCOperator<evaluate>::compareOpt(char temp_first,char temp_second)
{
    char pri;
    switch(temp_second)
    {
        case '+':
        case '-':
            if(temp_first=='('||temp_first=='=')
            {
                pri='<';
            }
            else
            {
                pri='>';
            }
            break;
        case '*':
        case '/':
            if(temp_first=='*'||temp_first=='/'||temp_first==')')
            {
                pri='>';
            }  
            else
            {
                pri='<';
            }
            break;
        case '(':
            if(temp_first==')')
            {
                printf("\n\t Expression form error\n");
                exit(-1);
            }
            else
            {
                pri='<';
            }  
            break;
        case ')':
            switch(temp_first)
            {
            case'(':
                pri='=';
                break;
            case'=':
                printf("\n\t Expression form error\n");
                exit(-1);
            default :
                pri='>';
            }
            break;
        case'=':
            switch(temp_first)
            {
            case'=':
                pri='=';
                break;
            case'(' :
                printf("\n\t Expression form error\n");
                exit(-1);
            default :
                pri='>';
            }
            break;
       
        default:
            {
                  printf("\n\t Unknown operator \n");
                  pri = 0;
            }
            break;
     }    
     return pri;
}
 
template <class evaluate>
double CCOperator<evaluate>::standardOpt(double temp_prefix,char temp_opt,double temp_postfix)
/* Pre: Already have two Nums and one Opt .
   Post:Return the result of calculate. */
{
    double temp_result;
    switch(temp_opt)
    {
        case'+':temp_result=temp_prefix+temp_postfix;break;
        case'-':temp_result=temp_prefix-temp_postfix;break;
        case'*':temp_result=temp_prefix*temp_postfix;break;
        case'/':
            if(temp_postfix != 0)
            {
                temp_result=temp_prefix/temp_postfix;
               
            }
            else
            {
                printf("\n\t Calculate error \n");
            }
            break;
        default:
            {
                  printf("\n\t Unsupport operator \n");
                  break;
            }
    }
    return temp_result;
}
 
template <class evaluate>
bool CCOperator<evaluate>::isOpt(char c)
{
    switch(c)
    {
        case '+':
        case '-':
        case '*':  
        case '/':
        case '(':
        case ')':
        case '=':
            return true;
        default:
            return false;
     }
}
 
bool doCalculate()
{
    CCStack<double> stackSZ;
    CCStack<char> stackZF;
    CCOperator<double> calculatorOpt;
 
    char temp_opt;                      //Temporary Operation Saver.
    double temp_number;                 //Temporary Number Saver.
    double temp_prefix,temp_postfix;    //Temporary Opt Prefix(Number),Postfix(Number) Saver.
    double temp_final;                  //Temporary Midway Final Saver.
    double final;                       //The Final Calculate Result.
    char temp_c;                        //Temporary Get One Char.
    char convert_str2double[100];       //Use For Convert String To Double.
    int judge=0;                        //The Currently Digit Saver.
 
    stackZF.push('=');
    printf("\nPlease input your expression:");
    temp_c=getchar();  //Get The First Char.
   
    judge++;
    stackZF.getTop(temp_opt);   // Get the Top Element Of the StackZF.
    while(temp_c != '=' || temp_opt != '=')
    {
        if(calculatorOpt.isOpt(temp_c)) // Judge "temp_c" is Opt or not.
        {
            switch(calculatorOpt.compareOpt(temp_opt,temp_c)) // Return The PRI State: ">" , "<" or "=".
            {
            case '<': //Top Element PRI < temp_c.
                stackZF.push(temp_c);
                temp_c= getchar();
                stackZF.getTop(temp_opt);
                break;
            case '='://Shuck Off The "( )" And Calculate "temp_final".
                stackZF.pop(temp_opt);
                stackZF.getTop(temp_opt);
                temp_c= getchar();
                break;
               
            case '>'://Pop From the stackZF And stackSZ and Do Calculate.
                if(temp_opt=='+'||temp_opt=='-'||temp_opt=='*'||temp_opt=='/')
                {
                    stackZF.pop(temp_opt);
                    stackSZ.pop(temp_postfix);
                    stackSZ.pop(temp_prefix);
                    temp_final=calculatorOpt.standardOpt(temp_prefix,temp_opt,temp_postfix); //Calculate Out The temp_final.
                    stackSZ.push(temp_final);
                    stackZF.getTop(temp_opt);
                    break;
                }
                else
                {
                    break;
                }
            }
        }
        else if((temp_c>='0' && temp_c<='9') || temp_c=='.') //Combination The Number(Double)
        {
            int i=0;
            do
            {
                convert_str2double[i]=temp_c;
                i++;
                temp_c= 'c';
            }while((temp_c<='9' && temp_c>='0') || temp_c=='.');
            convert_str2double[i]=0;
            temp_number=atof(convert_str2double); //Use The Function atof() to Convert A String Var To A Double One.
            stackSZ.push(temp_number);
        }
        else
        {
            //ERROR
        }
    }
    stackSZ.getTop(final);
   
    printf("\nResult:%15.15f",final);
   
 
    return 0;
}
int main()
{
    doCalculate();
    return 0;
}
 



I get the following errors:

Error      5      error C2664: 'CCStack<evaluate>::pop' : cannot convert parameter 1 from 'double' to 'char &'      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      299
Error      6      error C2664: 'CCStack<evaluate>::pop' : cannot convert parameter 1 from 'double' to 'char &'      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      300
Error      9      error C2664: 'CCStack<evaluate>::getTop' : cannot convert parameter 1 from 'double' to 'char &'      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      330
Error      4      error C3861: 'getchar': identifier not found      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      292
Error      3      error C3861: 'getchar': identifier not found      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      286
Error      2      error C3861: 'getchar': identifier not found      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      274
Error      11      error C3861: 'printf': identifier not found      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      332
Error      1      error C3861: 'printf': identifier not found      c:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\test\test\test.cpp      273


Please advise

0
 
LVL 53

Expert Comment

by:Infinity08
ID: 20352710
The errors are pretty self-explanatory :

>> cannot convert parameter 1 from 'double' to 'char &'

It means you're trying to pass a double where a char& is expected.


>> identifier not found

It means that the compiler doesn't know the identifier ... Check whether the identifier is defined (do you have the proper include ?).
0
 

Author Comment

by:kk_hutton
ID: 20353894
alrite i get no compilier errors but when i run it , it does nothing. It asks for a expression to calculate, and nothing happens after that:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define DEAFAULT_SIZE 20
template <class t>
class CCStack
{
private:
    char* base;
    char* top;
    int size;
public:
    CCStack(int size = DEAFAULT_SIZE);
    ~CCStack();
    bool isFull() const;   //Judge the Stack is full or not.
    bool isEmpty() const;   //Judge the Stack is empty or not.
    bool getTop(char &item) const;  //get the top element
    bool push(const char &item); //add item to stack
    bool pop(char &item);        //pop top into item
};
 
template <class t>
CCStack<t>::CCStack(int size)
{
    if(!(base=new char[size*sizeof(char)]))
    {
        cout << "Error!Failure to apply the memory space." << endl;
        exit(-1);
    }
    top = base;
}
 
template <class t>
CCStack<t>::~CCStack()
{
    delete[] base;
    base = NULL;
}
 
template <class t>
bool CCStack<t>::getTop(char &item) const
{
 
    if(top > base)
    {
        item = *(top-sizeof(char));
    }
    else
    {
        return false;
    }
    return true;
}
 
template <class t>
bool CCStack<t>::push(const char &item)
{
    if(!isFull())
    {
       *top = item;
       top = top+sizeof(char);
    }
    return true;
}
 
template <class t>
bool CCStack<t>::pop(char &item)
{
    if(!isEmpty())
    {
       top = top-sizeof(char);
         item = *top;
    }
    return true;
}
 
template <class t>
bool CCStack<t>::isFull() const
{
    if(top >= base + size*sizeof(char))
    {
        return true;       
    }
    else
    {
        return false;
    }
}
 
template <class t>
bool CCStack<t>::isEmpty() const
{
    if( top == base )
    {
        return true;       
    }
    else
    {
        return false;
    }
}
 
template <class t>
class CCOperator
{
private:
public:
    CCOperator();
    ~CCOperator();
    char compareOpt(char temp_first,char temp_second);
    double standardOpt(double temp_prefix,char temp_opt,double temp_postfix);
    bool isOpt(char c);
};
template <class t>
CCOperator<t>::CCOperator()
{
 
}
 
template <class t>
CCOperator<t>::~CCOperator()
{
 
}
template <class t>
char CCOperator<t>::compareOpt(char temp_first,char temp_second)
{
    char pri;
    switch(temp_second)
    {
        case '+':
        case '-':
            if(temp_first=='('||temp_first=='=')
            {
                pri='<';
            }
            else
            {
                pri='>';
            }
            break;
        case '*':
        case '/':
            if(temp_first=='*'||temp_first=='/'||temp_first==')')
            {
                pri='>';
            }  
            else
            {
                pri='<';
            }
            break;
        case '(':
            if(temp_first==')')
            {
                printf("\n\t Expression form error\n");
                exit(-1);
            }
            else
            {
                pri='<';
            }  
            break;
        case ')':
            switch(temp_first)
            {
            case'(':
                pri='=';
                break;
            case'=':
                printf("\n\t Expression form error\n");
                exit(-1);
            default :
                pri='>';
            }
            break;
        case'=':
            switch(temp_first)
            {
            case'=':
                pri='=';
                break;
            case'(' :
                printf("\n\t Expression form error\n");
                exit(-1);
            default :
                pri='>';
            }
            break;
       
        default:
            {
                  printf("\n\t Unknown operator \n");
                  pri = 0;
            }
            break;
     }    
     return pri;
}
 
template <class t>
double CCOperator<t>::standardOpt(double temp_prefix,char temp_opt,double temp_postfix)
/* Pre: Already have two Nums and one Opt .
   Post:Return the result of calculate. */
{
    double temp_result;
    switch(temp_opt)
    {
        case'+':temp_result=temp_prefix+temp_postfix;break;
        case'-':temp_result=temp_prefix-temp_postfix;break;
        case'*':temp_result=temp_prefix*temp_postfix;break;
        case'/':
            if(temp_postfix != 0)
            {
                temp_result=temp_prefix/temp_postfix;cout << temp_result;
               
            }
            else
            {
                printf("\n\t Calculate error \n");
            }
            break;
        default:
            {
                  printf("\n\t Unsupport operator \n");
                  break;
            }
    }
    return temp_result;
}
 
template <class t>
bool CCOperator<t>::isOpt(char c)
{
    switch(c)
    {
        case '+':
        case '-':
        case '*':  
        case '/':
        case '(':
        case ')':
        case '=':
            return true;
        default:
            return false;
     }
}
 
bool doCalculate()
{
    CCStack<double> stackSZ;
    CCStack<char> stackZF;
    CCOperator<double> calculatorOpt;
 
    char temp_opt;
    char a1,a2,a3;//Temporary Operation Saver.
    double temp_number;                 //Temporary Number Saver.
    double temp_prefix,temp_postfix;    //Temporary Opt Prefix(Number),Postfix(Number) Saver.
    double temp_final;                  //Temporary Midway Final Saver.
    double final;                       //The Final Calculate Result.
    char temp_c;                        //Temporary Get One Char.
    char convert_str2double[100];       //Use For Convert String To Double.
    int judge=0;                        //The Currently Digit Saver.
 
    stackZF.push('=');
    printf("\nPlease input your expression:");
    temp_c=getchar();  //Get The First Char.
   
    judge++;
    stackZF.getTop(temp_opt);   // Get the Top Element Of the StackZF.
    while(temp_c != '=' || temp_opt != '=')
    {
        if(calculatorOpt.isOpt(temp_c)) // Judge "temp_c" is Opt or not.
        {
            switch(calculatorOpt.compareOpt(temp_opt,temp_c)) // Return The PRI State: ">" , "<" or "=".
            {
            case '<': //Top Element PRI < temp_c.
                stackZF.push(temp_c);
                temp_c=getchar();
                stackZF.getTop(temp_opt);
                break;
            case '='://Shuck Off The "( )" And Calculate "temp_final".
                stackZF.pop(temp_opt);
                stackZF.getTop(temp_opt);
                temp_c=getchar();
                break;
               
            case '>'://Pop From the stackZF And stackSZ and Do Calculate.
                if(temp_opt=='+'||temp_opt=='-'||temp_opt=='*'||temp_opt=='/')
                {
                   char a1,a2,a3;
                    stackZF.pop(a1);
                    stackSZ.pop(a2);
                    stackSZ.pop(a3);
                    temp_opt = a1;
                    temp_postfix = atof(&a2);
                    temp_prefix = atof(&a3);
                    temp_final=calculatorOpt.standardOpt(temp_prefix,temp_opt,temp_postfix); //Calculate Out The temp_final.
                    stackSZ.push(temp_final);
                    stackZF.getTop(temp_opt);
                    break;
                }
                else
                {
                    break;
                }
            }
        }
        else if((temp_c>='0' && temp_c<='9') || temp_c=='.') //Combination The Number(Double)
        {
            int i=0;
            do
            {
                convert_str2double[i]=temp_c;
                i++;
                temp_c=getchar();
            }while((temp_c<='9' && temp_c>='0') || temp_c=='.');
            convert_str2double[i]=0;
            temp_number=atof(convert_str2double); //Use The Function atof() to Convert A String Var To A Double One.
            stackSZ.push(temp_number);
        }
        else
        {
            //ERROR
        }
    }
    char a4;
    stackSZ.getTop(a4);
    final = atof(&a4);
   
   
    printf("\nResult:%15.15f",final);
   
   
 
    return 0;
}
int main()
{
    doCalculate();
    return 0;
}
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20354631
The expression you input should like this ,
3/(1+2)=
you must input equal sign at last
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20354762
you must have some concept about template, look at http://www.iis.sinica.edu.tw/~kathy/vcstl/templates.htm

Now I talk about the core algorithm.
For an instance ,the expression is "6*(2+5/1)-4*3="

read char                       stack1(double value)                stack2(sign)                description
6                                     6                                                                                    push 6 into stack1
*                                      6                                                *                                 push * into stack2
(                                      6                                                *(                                push ( into stack2
2                                     6,2                                             *(                                push 2 into stack1
+                                     6,2                                            *(+                               push + into stack1
5                                    6,2,5                                         *(+                                push 5 into stack1
/                                     6,2,5                                         *(+/                               push / into stack2
1                                    6,2,5,1                                      *(+/                               push 1 into stack1
)                                     6,2                                           *(+                                do 5/1, stack1&stack2 pop
                                      6,2,5                                        *(+                                 result 5 push into stack1
                                      6                                              *(                                  do 2+5,stack1&stack2 pop
                                      6,7                                           *(                                   result pushed into stack1
                                      6,7                                           *                                    stack2 pop (
-                                                                                                                          do 6*7, stack1&stack2 pop
                                      42                                                                                 result pushed into stack1
                                      42                                            -                                    push - into stack2
4                                    42,4                                         -                                    push 4 into stack1
*                                     42,4                                        -*                                    push * into stack2
3                                    42,4,3                                     -*                                    push 3 into stack1
=                                    42                                           -                                      do 4*3,stack1&stack2 pop
                                      42,12                                      -                                      result pushed into stack1
                                                                                                                            do 42-12,    end
0
 

Author Comment

by:kk_hutton
ID: 20354807
thank you very much. But whenever i enter an expression with = sign , it loops for ever and it doesn't show the answer. Is everything look fine in my code ?
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20356160
>>template <class t>
>>bool CCStack<t>::getTop(char &item) const      // bool CCStack<t>::getTop(t &item) const
>>{
 
>>    if(top > base)
>>    {
>>        item = *(top-sizeof(char));                      // item = *(top-sizeof(t));
>>    }
>>    else
>>    {
>>        return false;
>>    }
>>    return true;
>>}

It's wrong to use char type, look at my sample code.
Template is a more abstract concept than class, if you use char type,
when you declare double stack ,  the top pointer in your stack won't move correctly.
As the double type contains 4 bit,but char type only contains 1 bit.

You can try compiling my sample code and read it in detail.
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20356173
>>As the double type contains 4 bit,but char type only contains 1 bit.
Not bit,but byte.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20356688
>>>>As the double type contains 4 bit,but char type only contains 1 bit.
>>>>Not bit,but byte.

A double has a size of 8 bytes.


>>>> accept the input as a character string

The doCalculate doesn't seem to be well-defined. It is mixing up user input with input parsing. From your requirements you should get the user input as char string. It is not required that you ask for each single char while doing the calculation. I would recommend to move the user input into main and pass the input string to doCalculate.

#include <string>
using namespace std;

int main()
{
    while (true)
    {
        cout << endl << "Please input your expression[Q to quit]: ";
        string input;
        getline(cin, input);
        if (input.find_first_of("Qq") == 0)
             break;
        double d  = doCalculate(input);
        if (d == DBL_MIN)
        {
               cout << "[" << input << "], wrong syntax" << endl << endl;
               continue;
        }
        cout << input " << " = " << d << endl << endl;
    }
    return 0;
}

The doCalulation would have prototype

  double doCalculate(const string& input);

Regards, Alex
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20362587
>>A double has a size of 8 bytes.
yes, you are right.
.
>>The doCalculate doesn't seem to be well-defined. It is mixing up user input with input parsing. From >>your requirements you should get the user input as char string. It is not required that you ask for >>each single char while doing the calculation. I would recommend to move the user input into main and >>pass the input string to doCalculate.
Good suggestion.
0
 

Author Comment

by:kk_hutton
ID: 20392427
would it make sense to change the pop() and and push() methods from char to template t also ?

bool CCStack<t>::push(const char &item)             // use template instead here
{
    if(!isFull())
    {
       *top = item;
       top = top+sizeof(char);                        // change this also from char
    }
    return true;
}
 
template <class t>
bool CCStack<t>::pop(char &item)
{
    if(!isEmpty())
    {
       top = top-sizeof(char);
         item = *top;
    }
    return true;
}
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20393686
>>would it make sense to change the pop() and and push() methods from char to template t also ?
yeah, the code of stack is okay, isn't neccessary to be modified by yourself, just use it.
0
 

Author Closing Comment

by:kk_hutton
ID: 31410931
Thank you very much for helping me
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This is an explanation of a simple data model to help parse a JSON feed
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now