CALCULATOR

 

OLD VERSION                                                             NEW VERSION WITH STL

 
//eval.cpp
// this program:
//  - reads lines from standard input, each line represents an
//    infix expression consisting of non-negative real numbers and
//    valid operators;each line sould not contain more than 79 characters
//  - converts an infix expression to a postfix expression
//  - evaluates a postfix expression
//  - for each line of input, prints the original input string
//    and the result of evaluation
//  - if an error detected, prints an error message and takes an
//    appropriate action
// exception handling is used to deal with error conditions

#include <iostream.h> 
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include "stackt.h" 

int isoperator(char);
int precedence (char);
char* in2post(char*, char*);
double evalpostfix(char*);
double apply(char oper, double opnd1, double opnd2);

const int sizein = 80;        //max size of input line(infix //Expression)
const int sizepost = 256;     //max size of postfix expression
main() {
 char in[sizein];
 char post[sizepost];
 double value;
 char ch;

 while (cin.get(in, sizein)) {

  // try block
  try {
   if ((ch = cin.get()) != EOF && ch != '\n')
    throw sizein;           // input line is too long

   in2post(in, post);
   value = evalpostfix(post);
   cout<<in<<" = "<<value<<endl<<endl;
  } // end try block

  // catch block
  catch (char *str) {

   if (strcmp(str, "underflow") == 0) {
    cerr<<in<<endl;
    cerr<<"Invalid expression: possible wrong number of parentheses/"
        <<"too many operators."
        <<"\nExpression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "opndst") == 0) {
    cerr<<in<<endl;
    cerr<<"Invalid expression: too few operators."
        <<"\nExpression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "parentheses") == 0) {
    cerr<<in<<endl;
    cerr<<"Invalid expression: wrong number of parentheses."
        <<"\nExpression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "zero") == 0) {
    cerr<<in<<endl;
    cerr<<"Division by 0 detected. Expression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "overflow") == 0) {
    cerr<<"Stack overflow. Program terminated"<<endl;
    exit (-1);
   }

   else if (strcmp(str, "empty_postfix") == 0)
    ;
  }

  catch (char ch) {
   cerr<<in<<endl;
   cerr<<"Invalid operator: "<<ch<<"\nExpression ignored."<<endl<<endl;
  }

  catch (int size) {
   cin.ignore(100, '\n');
   cerr<<in<<"..."<<endl;
   cerr<<"Input line contains more than "<<(size-1)<<
" characters. "
     <<"Line ignored."<<endl<<endl;
  }

 //control is transferred here after any of the above catch //handlers
 //are executed (except for those that terminate the program)

 }  // end while

 return 0;

// end main
 

// functions to convert and evaluate an expression:

//converts an infix expression into postfix, returns a pointer to
//a postfix expression
char * in2post(char *infix, char *postfix) {

 assert(infix);
 assert(postfix);

 Stack<char> *operst = new Stack<char>;   //Stack of //operators 
 char *p = postfix;
 char curr_oper, old_oper;

 while (*infix) {
  while (isspace(*infix))
   infix++;
  if (!*infix) break;
  if (isdigit(*infix) || *infix == '.') {
   while (isdigit(*infix) || *infix == '.')
    *postfix++ = *infix++;
   *postfix++ = ' ';
  }
  else {
   if (!isoperator(*infix))
    throw *infix;
   curr_oper = *infix;
   infix ++;
   if (curr_oper == '(')
    operst->push(curr_oper);
   else if (curr_oper == ')')
    while ((old_oper = operst->pop()) != '(') {
     *postfix++ = old_oper;
     *postfix++ = ' ';
    }
   else {
    while (!operst->isempty() &&
       precedence(operst->topval()) >= precedence(curr_oper)) {
     old_oper = operst->pop();
     *postfix++ = old_oper;
     *postfix++ = ' ';
    }  //end while
    operst->push(curr_oper);
   }  //end else
  }  //end else
 }  //end while

 while (!operst->isempty()) {
  old_oper = operst->pop(); 
  if (old_oper == '(')
   throw "parentheses";
  *postfix++ = old_oper;
  *postfix++ = ' ';
 }

 *postfix = '\0';
 if (strlen(p) == 0)
  throw "empty_postfix";
 return p;
}

//evaluates a postfix expression and returns the result
double evalpostfix (char *postfix) {

 double opnd1, opnd2, result;
 Stack<double> opndst; 
//Stack of operands

 assert(postfix);
 while (*postfix) {
  while (isspace(*postfix))
   postfix++;
  if (!(*postfix)) break;
  if (isdigit(*postfix)) {
   opnd1 = strtod(postfix, &postfix);
   opndst.push(opnd1);
  }
  else {
   if (!isoperator(*postfix))
    throw *postfix;
   opnd2 = opndst.pop(); 
   opnd1 = opndst.pop(); 
   result = apply(*postfix, opnd1, opnd2);
   opndst.push(result);
   postfix++;
  }
 }

 result = opndst.pop(); 
 if (!opndst.isempty())
  throw "opndst";
 return result;

}

//returns true if oper is a valid operator, otherwise returns false
int isoperator(char oper) {

 return oper == '+' || oper == '-' ||
    oper == '*' || oper == '/' ||
    oper == '(' || oper == ')';
}
 

//returns a number that characterizes precedence of an //operator:
//the bigger the number, the higher precedence
int precedence(char oper) {
 if (oper == '+' || oper == '-')
  return 1;
 else if (oper == '*' || oper =='/')
  return 2;
 else if (oper == '(')
  return 0;
}
 

//returns the result of the operation oper on the opnd1 and //opnd2
double apply(char oper, double opnd1, double opnd2) {

 if (oper == '+')
  return opnd1 + opnd2;
 if (oper == '-')
  return opnd1 - opnd2;
 if (oper == '*')
  return opnd1 * opnd2;
 if (oper == '/') {
  if (opnd2 == 0)
   throw "zero";
  return opnd1/opnd2;
 }
}
 

 

//eval.cpp
// this program:
//  - reads lines from standard input, each line represents an
//    infix expression consisting of non-negative real numbers 
// and  valid operators;each line sould not contain more than //      79 characters
//  - converts an infix expression to a postfix expression
//  - evaluates a postfix expression
//  - for each line of input, prints the original input string
//    and the result of evaluation
//  - if an error detected, prints an error message and takes an
//    appropriate action
// exception handling is used to deal with error conditions

#include <iostream.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <stack> 
using namespace std; 

int isoperator(char);
int precedence (char);
char* in2post(char*, char*);
double evalpostfix(char*);
double apply(char oper, double opnd1, double opnd2);

const int sizein = 80;        //max size of input line (infix //expression)
const int sizepost = 256;     //max size of postfix expression

main() {
 char in[sizein];
 char post[sizepost];
 double value;
 char ch;

 while (cin.get(in, sizein)) {

  // try block
  try {
   if ((ch = cin.get()) != EOF && ch != '\n')
    throw sizein;           // input line is too long

   in2post(in, post);
   value = evalpostfix(post);
   cout<<in<<" = "<<value<<endl<<endl;
  } // end try block

  // catch block
  catch (char *str) {

   if (strcmp(str, "underflow") == 0) {
    cerr<<in<<endl;
    cerr<<"Invalid expression: possible wrong number of parentheses/"
        <<"too many operators."
        <<"\nExpression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "opndst") == 0) {
    cerr<<in<<endl;
    cerr<<"Invalid expression: too few operators."
        <<"\nExpression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "parentheses") == 0) {
    cerr<<in<<endl;
    cerr<<"Invalid expression: wrong number of parentheses."
        <<"\nExpression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "zero") == 0) {
    cerr<<in<<endl;
    cerr<<"Division by 0 detected. Expression ignored."<<endl<<endl;
   }

   else if (strcmp(str, "overflow") == 0) {
    cerr<<"Stack overflow. Program terminated"<<endl;
    exit (-1);
   }

   else if (strcmp(str, "empty_postfix") == 0)
    ;
  }

  catch (char ch) {
   cerr<<in<<endl;
   cerr<<"Invalid operator: "<<ch<<"\nExpression ignored."<<endl<<endl;
  }

  catch (int size) {
   cin.ignore(100, '\n');
   cerr<<in<<"..."<<endl;
   cerr<<"Input line contains more than "<<(size-1)<<
" characters. "
     <<"Line ignored."<<endl<<endl;
  }

 //control is transferred here after any of the above catch //handlers
 //are executed (except for those that terminate the program)

 }  // end while

 return 0;

// end main
 

// functions to convert and evaluate an expression:

//converts an infix expression into postfix, returns a pointer to
//a postfix expression
char * in2post(char *infix, char *postfix) {

 assert(infix);
 assert(postfix);

 stack<char> operst;   //Stack of operators

 char *p = postfix;
 char curr_oper, old_oper;

 while (*infix) {
  while (isspace(*infix))
   infix++;
  if (!*infix) break;
  if (isdigit(*infix) || *infix == '.') {
   while (isdigit(*infix) || *infix == '.')
    *postfix++ = *infix++;
   *postfix++ = ' ';
  }
  else {
   if (!isoperator(*infix))
    throw *infix;
   curr_oper = *infix;
   infix ++;
   if (curr_oper == '(')
    operst.push(curr_oper);
   else if (curr_oper == ')')
    while ((old_oper = operst.top()) != '(') {
     operst.pop();
     *postfix++ = old_oper;
     *postfix++ = ' ';
    }
   else {
    while (!operst.empty() &&
       precedence(operst.top()) >= precedence(curr_oper)) {
     old_oper = operst.top(); 
     operst.pop(); 
     *postfix++ = old_oper;
     *postfix++ = ' ';
    }  //end while
    operst.push(curr_oper);
   }  //end else
  }  //end else
 }  //end while

 while (!operst.empty()) {
  old_oper = operst.top(); 
  if (old_oper == '(')
   throw "parentheses";
  *postfix++ = old_oper;
  *postfix++ = ' ';
 }

 *postfix = '\0';
 if (strlen(p) == 0)
  throw "empty_postfix";
 return p;
}
//evaluates a postfix expression and returns the result
double evalpostfix (char *postfix) {

 double opnd1, opnd2, result;
 stack<double> opndst; 
//Stack of operands

 assert(postfix);
 while (*postfix) {
  while (isspace(*postfix))
   postfix++;
  if (!(*postfix)) break;
  if (isdigit(*postfix)) {
   opnd1 = strtod(postfix, &postfix);
   opndst.push(opnd1);
  }
  else {
   if (!isoperator(*postfix))
    throw *postfix;
   opnd2 = opndst.top(); 
   opndst.pop();
   opnd1 = opndst.top(); 
   opndst.pop(); 
   result = apply(*postfix, opnd1, opnd2);
   opndst.push(result);
   postfix++;
  }
 }

 result = opndst.top(); 
 opndst.pop(); 
 if (!opndst.empty())
  throw "opndst";
 return result;

}
//returns true if oper is a valid operator, otherwise returns false
int isoperator(char oper) {

 return oper == '+' || oper == '-' ||
    oper == '*' || oper == '/' ||
    oper == '(' || oper == ')';
}

//returns a number that characterizes precedence of an //operator:
//the bigger the number, the higher precedence
int precedence(char oper) {
 if (oper == '+' || oper == '-')
  return 1;
 else if (oper == '*' || oper =='/')
  return 2;
 else if (oper == '(')
  return 0;
}
 

//returns the result of the operation oper on the opnd1 and //opnd2
double apply(char oper, double opnd1, double opnd2) {

 if (oper == '+')
  return opnd1 + opnd2;
 if (oper == '-')
  return opnd1 - opnd2;
 if (oper == '*')
  return opnd1 * opnd2;
 if (oper == '/') {
  if (opnd2 == 0)
   throw "zero";
  return opnd1/opnd2;
 }
}

 

TO RUN AN OLD VERSION YOU NEED TO HAVE FOLLOWING FILES IN YOUR DIRECTORY

stack.h     stack.inl

                                                                                   BACK