Solved

Somewhat of a Calculator

Posted on 2000-03-06
6
238 Views
Last Modified: 2010-04-02
I need to know how to program and it be like a calculator.  That means if you input 2 * 3 you will get the answer to be 6.

How does this happen and how do you do it.
0
Comment
Question by:SBuntin
  • 4
  • 2
6 Comments
 
LVL 22

Expert Comment

by:nietod
Comment Utility
From http://www.snippets.org

+++Date last modified: 05-Jul-1997

  Basically, EVAL.C converts infix notation to postfix notation. If you're
not familiar with these terms, infix notation is standard human-readable
equations such as you write in a C program. Postfix notation is most familiar
as the "reverse Polish" notation used in Hewlett Packard calculators and in
the Forth language. Internally, all languages work by converting to postfix
evaluation. Only Forth makes it obvious to the programmer.

  EVAL.C performs this conversion by maintaining 2 stacks, an operand stack
and an operator stack. As it scans the input, each time it comes across a
numerical value, it pushes it onto the operand stack. Whenever it comes
across an operator, it pushes it onto the operator stack. Once the input
expression has been scanned, it evaluates it by popping operands off the
operand stack and applying the operators to them.

 For example the simple expression "2+3-7" would push the values 2, 3, and 7
onto the operand stack and the operators "+" and "-" onto the operator stack.
When evaluating the expression, it would first pop 3 and 7 off the operand
stack and then pop the "-" operator off the operator stack and apply it. This
would leave a value of -4 on the stack. Next the value of 2 would be popped
from the operand stack and the remaining operator off of the operator stack.
Applying the "+" operator to the values 2 and -4 would leave the result of
the evaluation, -2, on the stack to be returned.

  The only complication of this in EVAL.C is that instead of raw operators
(which would all have to be 1 character long), I use operator tokens which
allow multicharacter operators and precedence specification. What I push on
the operator stack is still a single character token, but its the operator
token which is defined in the 'verbs' array of valid tokens. Multicharacter
tokens are always assumed to include any leading parentheses. For example, in
the expression "SQRT(37)", the token is "SQRT(".

  Using parentheses forces evaluation to be performed out of the normal
sequence. I use the same sort of mechanism to implement precedence rules.
Unary negation is yet another feature which takes some explicit exception
processing to process. Other than these exceptions, it's pretty
straightforward stuff.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
/* +++Date last modified: 05-Jul-1997 */



/************************************************************************/

/*                                                                      */

/*  EVAL.C - A simple mathematical expression evaluator in C            */

/*                                                                      */

/*  operators supported: Operator               Precedence              */

/*                                                                      */

/*                         (                     Lowest                 */

/*                         )                     Highest                */

/*                         +   (addition)        Low                    */

/*                         -   (subtraction)     Low                    */

/*                         *   (multiplication)  Medium                 */

/*                         /   (division)        Medium                 */

/*                         \   (modulus)         High                   */

/*                         ^   (exponentiation)  High                   */

/*                         sin(                  Lowest                 */

/*                         cos(                  Lowest                 */

/*                         atan(                 Lowest                 */

/*                         abs(                  Lowest                 */

/*                         sqrt(                 Lowest                 */

/*                         ln(                   Lowest                 */

/*                         exp(                  Lowest                 */

/*                                                                      */

/*  constants supported: pi                                             */

/*                                                                      */

/*  Original Copyright 1991-93 by Robert B. Stout as part of            */

/*  the MicroFirm Function Library (MFL)                                */

/*                                                                      */

/*  The user is granted a free limited license to use this source file  */

/*  to create royalty-free programs, subject to the terms of the        */

/*  license restrictions specified in the LICENSE.MFL file.             */

/*                                                                      */

/*  Requires RMALLWS.C, also in SNIPPETS.                               */

/*                                                                      */

/************************************************************************/



#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <math.h>

#include "sniptype.h"

#include "snip_str.h"                     /* For rmallws(), strupr()    */

#include "snipmath.h"

#include "numcnvrt.h"



/*

**  Other SNIPPETS functions

*/



char *rmallws(char *);

char *strupr(char *);





struct operator {

      char        token;

      char       *tag;

      size_t      taglen;

      int         precedence;

};



static struct operator verbs[] = {

      {'+',  "+",       1, 2 },

      {'-',  "-",       1, 3 },

      {'*',  "*",       1, 4 },

      {'/',  "/",       1, 5 },

      {'\\', "\\",      1, 5 },

      {'^',  "^",       1, 6 },

      {'(',  "(",       1, 0 },

      {')',  ")",       1, 99},

      {'S',  "SIN(",    4, 0 },

      {'C',  "COS(",    4, 0 },

      {'A',  "ABS(",    4, 0 },

      {'L',  "LN(",     3, 0 },

      {'E',  "EXP(",    4, 0 },

      {'t',  "ATAN(",   5, 0 },

      {'s',  "SQRT(",   5, 0 },

      {NUL,  NULL,      0, 0 }

};



static char   op_stack[256];                    /* Operator stack       */

static double arg_stack[256];                   /* Argument stack       */

static char   token[256];                       /* Token buffer         */

static int    op_sptr,                          /* op_stack pointer     */

              arg_sptr,                         /* arg_stack pointer    */

              parens,                           /* Nesting level        */

              state;                            /* 0 = Awaiting expression

                                                   1 = Awaiting operator

                                                */

const double Pi = 3.14159265358979323846;



static int              do_op(void);

static int              do_paren(void);

static void             push_op(char);

static void             push_arg(double);

static int              pop_arg(double *);

static int              pop_op(int *);

static char            *get_exp(char *);

static struct operator *get_op(char *);

static int              getprec(char);

static int              getTOSprec(void);



/************************************************************************/

/*                                                                      */

/*  evaluate()                                                          */

/*                                                                      */

/*  Evaluates an ASCII mathematical expression.                         */

/*                                                                      */

/*  Arguments: 1 - String to evaluate                                   */

/*             2 - Storage to receive double result                     */

/*                                                                      */

/*  Returns: Success_ if successful                                     */

/*           Error_ if syntax error                                     */

/*           R_ERROR if runtime error                                   */

/*                                                                      */

/*  Side effects: Removes all whitespace from the string and converts   */

/*                it to U.C.                                            */

/*                                                                      */

/************************************************************************/



int evaluate(char *line, double *val)

{

      double arg;

      char *ptr = line, *str, *endptr;

      int ercode;

      struct operator *op;



      strupr(line);

      rmallws(line);

      state = op_sptr = arg_sptr = parens = 0;



      while (*ptr)

      {

            switch (state)

            {

            case 0:

                  if (NULL != (str = get_exp(ptr)))

                  {

                        if (NULL != (op = get_op(str)) &&

                              strlen(str) == op->taglen)

                        {

                              push_op(op->token);

                              ptr += op->taglen;

                              break;

                        }



                        if (Success_ == strcmp(str, "-"))

                        {

                              push_op(*str);

                              ++ptr;

                              break;

                        }



                        if (Success_ == strcmp(str, "PI"))

                              push_arg(Pi);



                        else

                        {

                              if (0.0 == (arg = strtod(str, &endptr)) &&

                                    NULL == strchr(str, '0'))

                              {

                                    return Error_;

                              }

                              push_arg(arg);

                        }

                        ptr += strlen(str);

                  }

                  else  return Error_;



                  state = 1;

                  break;



            case 1:

                  if (NULL != (op = get_op(ptr)))

                  {

                        if (')' == *ptr)

                        {

                              if (Success_ > (ercode = do_paren()))

                                    return ercode;

                        }

                        else

                        {

                              while (op_sptr &&

                                    op->precedence <= getTOSprec())

                              {

                                    do_op();

                              }

                              push_op(op->token);

                              state = 0;

                        }



                        ptr += op->taglen;

                  }

                  else  return Error_;



                  break;

            }

      }



      while (1 < arg_sptr)

      {

            if (Success_ > (ercode = do_op()))

                  return ercode;

      }

      if (!op_sptr)

            return pop_arg(val);

      else  return Error_;

}



/*

**  Evaluate stacked arguments and operands

*/



static int do_op(void)

{

      double arg1, arg2;

      int op;



      if (Error_ == pop_op(&op))

            return Error_;



      pop_arg(&arg1);

      pop_arg(&arg2);



      switch (op)

      {

      case '+':

            push_arg(arg2 + arg1);

            break;



      case '-':

            push_arg(arg2 - arg1);

            break;



      case '*':

            push_arg(arg2 * arg1);

            break;



      case '/':

            if (0.0 == arg1)

                  return R_ERROR;

            push_arg(arg2 / arg1);

            break;



      case '\\':

            if (0.0 == arg1)

                  return R_ERROR;

            push_arg(fmod(arg2, arg1));

            break;



      case '^':

            push_arg(pow(arg2, arg1));

            break;



      case 't':

            ++arg_sptr;

            push_arg(atan(arg1));

            break;



      case 'S':

            ++arg_sptr;

            push_arg(sin(arg1));

            break;



      case 's':

            if (0.0 > arg2)

                  return R_ERROR;

            ++arg_sptr;

            push_arg(sqrt(arg1));

            break;



      case 'C':

            ++arg_sptr;

            push_arg(cos(arg1));

            break;



      case 'A':

            ++arg_sptr;

            push_arg(fabs(arg1));

            break;



      case 'L':

            if (0.0 < arg1)

            {

                  ++arg_sptr;

                  push_arg(log(arg1));

                  break;

            }

            else  return R_ERROR;



      case 'E':

            ++arg_sptr;

            push_arg(exp(arg1));

            break;



      case '(':

            arg_sptr += 2;

            break;



      default:

            return Error_;

      }

      if (1 > arg_sptr)

            return Error_;

      else  return op;

}



/*

**  Evaluate one level

*/



static int do_paren(void)

{

      int op;



      if (1 > parens--)

            return Error_;

      do

      {

            if (Success_ > (op = do_op()))

                  break;

      } while (getprec((char)op));

      return op;

}



/*

**  Stack operations

*/



static void push_op(char op)

{

      if (!getprec(op))

            ++parens;

      op_stack[op_sptr++] = op;

}



static void push_arg(double arg)

{

      arg_stack[arg_sptr++] = arg;

}



static int pop_arg(double *arg)

{

      *arg = arg_stack[--arg_sptr];

      if (0 > arg_sptr)

            return Error_;

      else  return Success_;

}



static int pop_op(int *op)

{

      if (!op_sptr)

            return Error_;

      *op = op_stack[--op_sptr];

      return Success_;

}



/*

**  Get an expression

*/



static char * get_exp(char *str)

{

      char *ptr = str, *tptr = token;

      struct operator *op;



      if (Success_ == strncmp(str, "PI", 2))

            return strcpy(token, "PI");





      while (*ptr)

      {

            if (NULL != (op = get_op(ptr)))

            {

                  if ('-' == *ptr)

                  {

                        if (str != ptr && 'E' != ptr[-1])

                              break;

                        if (str == ptr && !isdigit(ptr[1]) && '.' != ptr[1])

                        {

                              push_arg(0.0);

                              strcpy(token, op->tag);

                              return token;

                        }

                  }



                  else if (str == ptr)

                  {

                        strcpy(token, op->tag);

                        return token;

                  }



                  else break;

            }



            *tptr++ = *ptr++;

      }

      *tptr = NUL;



      return token;

}



/*

**  Get an operator

*/



static struct operator * get_op(char *str)

{

      struct operator *op;



      for (op = verbs; op->token; ++op)

      {

            if (Success_ == strncmp(str, op->tag, op->taglen))

                  return op;

      }

      return NULL;

}



/*

**  Get precedence of a token

*/



static int getprec(char token)

{

      struct operator *op;



      for (op = verbs; op->token; ++op)

      {

            if (token == op->token)

                  break;

      }

      if (op->token)

            return op->precedence;

      else  return 0;

}



/*

**  Get precedence of TOS token

*/



static int getTOSprec(void)

{

      if (!op_sptr)

            return 0;

      return getprec(op_stack[op_sptr - 1]);

}



#ifdef TEST



#include <stdio.h>



#ifdef __WATCOMC__

 #pragma off (unreferenced);

#endif

#ifdef __TURBOC__

 #pragma argsused

#endif



main(int argc, char *argv[])

{

      int retval;

      double val;



      printf("evaluate(%s) ", argv[1]);

      printf("returned %d\n", retval = evaluate(argv[1], &val));

      if (0 == retval)

            printf("val = %f\n", val);

      return 0;

}



#endif /* TEST */

0
 

Author Comment

by:SBuntin
Comment Utility
Not exactly what I was looking for.  Something less complex would work.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 22

Expert Comment

by:nietod
Comment Utility
How is it not what you are looking for?  

Something less complex probalby won't work.  If it could be written as a single statement, no one would boither to write it as 100.
0
 

Author Comment

by:SBuntin
Comment Utility
I Have this:

#include <iostream.h>

main()
{
      int left, right, answer;
      char operation;

      // Input
      cout << "Please input an equation (e.g. 4 * 5): ";
      cin >> left >> operation >> right;

      //Setting up Case and Calculating
      switch (operation)
      {
            case '+': answer = left + right; break;
            case '-': answer = left - right; break;
            case '*': answer = left * right; break;
            case '/': answer = left / right; break;
            default : cout << "Not Recognized.";
      }

      //Output
      cout << left << " " << operation << " " << right << " equals " << answer;


      return 0;
}

The only problem I have now is that when it catches the case default it will still print the output
0
 
LVL 22

Accepted Solution

by:
nietod earned 30 total points
Comment Utility
It might have been good to show the example first and describe the exact problem....


How about

bool Error = false;

//Setting up Case and Calculating
switch (operation)
{
   case '+': answer = left + right; break;
   case '-': answer = left - right; break;
   case '*': answer = left * right; break;
   case '/': answer = left / right; break;
   default : cout << "Not Recognized.";
       Error = true;
}

//Output
if (!Error)
   cout << left << " " << operation << " " << right << " equals " << answer;
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

772 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

17 Experts available now in Live!

Get 1:1 Help Now