Page 118
Write the program expr
, which evaluates a reverse Polish expression from the
command line, where each operator or operand is a separate argument. For example,
expr 2 3 4 + *
evaluates 2 X (3 + 4).
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#define MAX_OP_LEN 16
void push(float val);
float pop(void);
enum op_type { NUMBER, CHARACTER, INVALID };
enum op_type get_op_type(char *buf);
int main(int argc, char *argv[])
{
while (--argc > 0) {
switch (get_op_type(*++argv)) {
case NUMBER:
push(atof(*argv));
break;
case CHARACTER:
switch (**argv) {
case '+':
push(pop() + pop());
break;
case '-':
push(pop() - pop());
break;
case '*':
push(pop() * pop());
break;
case '/':
push(pop() / pop());
break;
}
break;
default:
printf("Invalid argument '%s'", *argv);
break;
}
}
printf("%f\n", pop());
}
enum op_type get_op_type(char *buf)
{
bool is_num =
isdigit(*buf) || (*buf == '-' || *buf == '+' || *buf == '.') &&
isdigit(*(buf + 1));
if (is_num) {
for (; isdigit(*buf); buf++)
;
if (*buf == '\0') {
return NUMBER;
} else {
return INVALID;
}
}
if (*(buf + 1) != '\0') {
return INVALID;
}
return CHARACTER;
}
#define MAX_BUF 16
static float buf[MAX_BUF];
static unsigned idx = 0;
void push(float val)
{
if (idx < MAX_BUF) {
buf[idx++] = val;
} else {
printf("error: buffer full\n");
}
}
float pop(void)
{
if (idx > 0) {
return buf[--idx];
} else {
printf("error: buffer empty\n");
return 0.0;
}
}