# Thread: need help on Calculator program in C

1. ## need help on Calculator program in C

i need help on how to get the answer of an equation entered by the user. For example:

user enters:
10*2+3/5*912-6/5)= ?

i accepted the equation as string but i dont know how to get the answer, implementing the MDAS rule and all. i already converted the numbers in the string to integer using atoi() but i dont know what's next and what to do with all the operators....

2. The hard part is operator precedence. For that it's much much easier to convert the expression to postfix and then use a stack based evaluation to solve it. Once you have the tokens in postfix form, it's a trivial affair to solve the equation. For example, here's a postfix calculator with a lot of functionality:
Code:
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define UNARY  0  /* Offset into actions for unary words */
#define BINARY 6  /* Offset into actions for binary words */
#define ACLEN  17 /* Total number of actions */
#define UNLEN  6  /* Total number of unary words */
#define BILEN  11 /* Total number of binary words */

static const char *actions[] = {
".", "sqrt", "sq", "not", "abs", "log",
"+", "-",    "*",  "/",   "mod", "pow",
"<", "=",    ">",  "and", "or",
};

static long int stack[1024]; /* 1024 should be MORE than enough */
static int top = 0;

static void eval ( void );
static void gather ( void );
static void process ( const char *action );
static void do_unary ( const char *action );
static void do_binary ( const char *action );
static void die ( const char *msg );

static int is_valid ( const char *action, size_t offset, size_t limit );

int main ( void )
{
while ( 1 )
eval();
}

void eval ( void )
{
gather();
puts ( " ok" );
}

void gather ( void )
{
char buffer[BUFSIZ];
char *action;
char *end;

if ( fgets ( buffer, sizeof buffer, stdin ) == NULL )
die ( "Input error" );

for ( action = strtok ( buffer, " \t\n" );
action != NULL; action = strtok ( NULL, " \t\n" ) )
{
long int number;

/* Process a number or an action */
number = strtol ( action, &end, 0 );
if ( end > action )
stack[top++] = number;
else if ( is_valid ( action, 0, ACLEN ) )
process ( action );
else if ( strcmp ( action, "bye" ) == 0 )
exit ( EXIT_SUCCESS );
else
die ( "Input error" );
}
}

void process ( const char *action )
{
if ( is_valid ( action, UNARY, UNLEN ) )
do_unary ( action );
else if ( is_valid ( action, BINARY, BILEN ) )
do_binary ( action );
}

void do_unary ( const char *action )
{
long int result = 0;
long int a;

if ( top == 0 )
die ( "Stack underflow" );
a = stack[--top];

if ( strcmp ( action, "." ) == 0 ) {
printf ( "%ld ", a );
fflush ( stdout );
return;
}
else if ( strcmp ( action, "not" ) == 0 )
result = !a;
else if ( strcmp ( action, "sqrt" ) == 0 )
result = (long int)sqrt ( a );
else if ( strcmp ( action, "sq" ) == 0 )
result = a * a;
else if ( strcmp ( action, "abs" ) == 0 )
result = abs ( a );
else if ( strcmp ( action, "log" ) == 0 )
result = (long int)log ( a );
else
die ( "Invalid format" );

stack[top++] = result;
}

void do_binary ( const char *action )
{
long int result = 0;
long int a, b;

if ( top < 2 )
die ( "Stack underflow" );
b = stack[--top];
a = stack[--top];

if ( action[0] == '+' )
result = a + b;
else if ( action[0] == '-' )
result = a - b;
else if ( action[0] == '*' )
result = a * b;
else if ( action[0] == '/' ) {
if ( b == 0 )
die ( "Division by zero" );
result = a / b;
}
else if ( strcmp ( action, "mod" ) == 0 ) {
if ( b == 0 )
die ( "Division by zero" );
result = a % b;
}
else if ( strcmp ( action, "pow" ) == 0 )
result = (long int)pow ( a, b );
else if ( action[0] == '<' )
result = a < b;
else if ( action[0] == '=' )
result = a == b;
else if ( action[0] == '>' )
result = a > b;
else if ( strcmp ( action, "and" ) == 0 )
result = a && b;
else if ( strcmp ( action, "or" ) == 0 )
result = a || b;
else
die ( "Invalid format" );

stack[top++] = result;
}

int is_valid ( const char *action, size_t offset, size_t limit )
{
size_t i;

for ( i = offset; i < limit + offset; i++ ) {
if ( strcmp ( action, actions[i] ) == 0 )
return 1;
}

return 0;
}

void die ( const char *msg )
{
fprintf ( stderr, "%s\n", msg );
exit ( EXIT_FAILURE );
}
It's very short, but very powerful. That's because all of the parsing work is done by the stack, not the program logic.

3. Hey Prelude, I have two questions about the code above.
1) Why are the global variables static? Aren't global variables always static?
2) How would you make an answer output? It does the calculations, I just don't know what the result are lol :(

4. Originally Posted by Kleid-0
1) Why are the global variables static? Aren't global variables always static?
Static gives them internal linkage, which will make them available only to functions within that file. So if you have multiple files in the program, only the file in which they are declared static will be able to reference them.

5. >1) Why are the global variables static? Aren't global variables always static?
Global variables and functions are have external linkage by default. Unless you have a need for external linkage, internal is far better. You do that by qualifying a global name as static.

>2) How would you make an answer output?
The period (.) operator will print the current top of the stack.

6. Originally Posted by Prelude
The period (.) operator will print the current top of the stack. :)
I'm trying to read the code correctly, but I'm doing something wrong. I run the program and '.' doesn't like me :(
Code:
kleid@Shiva:~/Programming/Laboratory\$ ./a.out
3*4*5
ok
.
3  ok
.
Stack underflow
:( the answer says 3, but I need 60 :(

7. Code:
3*4*5
ok
.
3  ok
.
Stack underflow
Eew. Remember that this is a postfix calculator, and the binary operators require two numbers to be present on the stack. So your example should be:
Code:
3 4 5 * *
ok
.
60 ok
Of course, you should stop there because now the stack is empty and trying to print the top value will result in an error message. Alternatively, you could do this:
Code:
3 4 * 5 *
ok
.
60 ok
Because the result of the previous operation is left on the top of the stack until an operator removes it. You can even put it all on one line if you want:
Code:
3 4 * 5 * .
60 ok

8. Code:
kleid@Shiva:~/Programming/Laboratory\$ ./a.out
23 45 * 3 .
3  ok
23 45 * 56 * .
57960  ok
23 67 *
ok
.
1541  ok
23 67 / .
0  ok
109 44 + .
153  ok
100 34 * 23 * 2 / .
39100  ok
I gotcha. That's a different way at looking at how a calculator can work, I like it, nice job :)

9. Thanks Prelude for posting that code!

I have been toying around with the idea of writing a RPN calculator program and I am sure I will learn tons just by examining your code.