Go Premium for a chance to win a PS4. Enter to Win

x
Solved

# Somewhat of a Calculator

Posted on 2000-03-06
Medium Priority
246 Views
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
Question by:SBuntin
• 4
• 2

LVL 22

Expert Comment

ID: 2589136
From http://www.snippets.org

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

ID: 2589142

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

/*                                                                      */

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

/*                                                                      */

/*  operators supported: Operator               Precedence              */

/*                                                                      */

/*                         (                     Lowest                 */

/*                         )                     Highest                */

/*                         -   (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        */

/*                                                                      */

/*  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);

}

}

else if (str == ptr)

{

strcpy(token, op->tag);

}

else break;

}

*tptr++ = *ptr++;

}

*tptr = NUL;

}

/*

**  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

ID: 2592914
Not exactly what I was looking for.  Something less complex would work.
0

LVL 22

Expert Comment

ID: 2592959
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

ID: 2593184
I Have this:

#include <iostream.h>

main()
{
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

nietod earned 120 total points
ID: 2593213
It might have been good to show the example first and describe the exact problem....

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

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [sâ€¦
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a â€¦
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relatâ€¦
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
###### Suggested Courses
Course of the Month8 days, 10 hours left to enroll