Make yourself a stack. Lots of problems get simpler with the right data structure.
Orgainize code however you like, or however your instructor likes is more to the (grade) point, but I like to define subroutines before they are used ("main-at-the-bottom" style) and keep all definitions that go together in the same part of the source file.
/* Value stack implementaiton */
#define VALSTACK_SIZE 100 /* at most 100 operands waiting for postfix operators */
double valstack[VALSTACK_SIZE];
int valstack_index=0;
/* push x onto the stack */
void push_value(double x)
{
assert(valstack_index < VALSTACK_SIZE);
valstack[valstack_index++] = x;
}
/* pop a value from the stack and return it */
double pop_value(void)
{
assert(valstack_index > 0);
return valstack[--valstack_index;
}
/* return true (nonzero) if stack is empty */
int stack_empty()
{ return valstack_index == 0; }
To use the assert macro, you need to #include
. assert() is a good way to insert statements that do nothing if your program is running correctly, but halt with an error if not. If the argument is true, no action is taken, otherwise you get an error message and a halt. I used those to prevent pushing too many values or popping values from an empty stack. A stack removes values in last-in-first-out (LIFO) order.
When your code sees a number, call push_value(x).
When your code sees the / operator:
y = pop_value();
x = pop_value();
assert (y != 0.0); /*TODO: Add a friendly error message here. */
z = x / y;
push_value(z);
printf("%g / %g = %g\n", x, y, z);
Notice the order: y (the second operand) is popped first because it was pushed last. (LIFO)
Also notice how assert can be used. You can halt on an error condition to give basic functionality during testing, but flag the source as a reminder that there's still work to be done. Comments beginning with TODO are easy to search for, and commonly used for that purpose. Some IDEs will automatically list those for you.