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).
Solution by Lars Wirzenius
Note: Lars uses EXIT_FAILURE on error. As far as I can tell, this is the only thing which makes this a Category 1, rather than Category 0, solution.
/*
* Solution to exercise 5-10 in K&R2:
*
* 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*(3+4).
*
* This is very similar to the program in 4.3 (and should ideally have been
* a modification of that).
*
* Feel free to modify and copy freely.
*
* Lars Wirzenius <liw@iki.fi>
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 1024
double stack[STACK_SIZE];
int stack_height = 0;
void panic(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
void push(double value) {
if (stack_height == STACK_SIZE)
panic("stack is too high!");
stack[stack_height] = value;
++stack_height;
}
double pop(void) {
if (stack_height == 0)
panic("stack is empty!");
return stack[--stack_height];
}
int main(int argc, char **argv) {
int i;
double value;
for (i = 1; i < argc; ++i) {
switch (argv[i][0]) {
case '\0':
panic("empty command line argument");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
push(atof(argv[i]));
break;
case '+':
push(pop() + pop());
break;
case '-':
value = pop();
push(pop() - value);
break;
case '*':
push(pop() * pop());
break;
case '/':
value = pop();
push(pop() / value);
break;
default:
panic("unknown operator");
break;
}
}
printf("%g\n", pop());
return 0;
}
Category 0 Solution by Alex Hoang
/* Allows for leading plus/minus as well as decimal numbers */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define NUMBER 0
void push(double f);
double pop(void);
main(int argc, char *argv[])
{
int type;
int c;
double op1, op2, latest;
while (--argc > 0)
{
*++argv;
if (!isdigit(c = **argv) && strlen(*argv) == 1)
type = c;
else
type = NUMBER;
switch (type)
{
case NUMBER:
push(atof(*argv));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
op2 = pop();
if (op2 != 0.0)
push(fmod(pop(), op2));
else
printf("error: zero divisor\n");
break;
case '^':
op2 = pop();
op1 = pop();
if (op1 == 0.0 && op2 <= 0)
printf("if x = 0.0, y must be greater than 0\n");
else
push(pow(op1, op2));
break;
case 'e':
push(exp(pop()));
break;
case '~':
push(sin(pop()));
break;
default:
printf("error: unknown command: %c\n", type);
break;
}
}
latest = pop();
printf("\t%.8g\n", latest);
return 0;
}
#define MAXVAL 100
int sp = 0;
double val[MAXVAL];
/* maximum depth of val stack */
/* next free stack position */
/* value stack */
/* push: push f onto value stack */
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
menonsahab's
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXVAL 100
int sp = 0;
double val[MAXVAL];
void push(double f)
{
if(sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}
double pop(void)
{
if(sp > 0)
return val[--sp];
else
{
printf("error: stack empty\n");
return 0.0;
}
}
int main(int argc, char *argv[])
{
int i, c, op2;
char *p;
for(i = 1; i < argc; i++)
{
p = argv[i];
printf("argv[%d] = %s\n", i, argv[i]);
while(*p && isdigit(*p))
p++;
printf("*p = %d, %c\n", *p, *p);
switch(*p)
{
case '\0':
push(atoi(argv[i]));
break;
case '+':
push(pop() + pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case 'x':
push(pop() * pop());
break;
case '/':
op2 = pop();
if(op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
}
}
printf("Final result = %lf\n", pop());
return 0;
}
/*
I noticed that the program was giving weird results when I was
using the multiplication symbol '*' as a command line input.
I couldn't figure out why that was happening so now I'm just
using the 'x' symbol to denote multiplication.
I even ran the other two solutions on this page but to no avail.
*/
/*
On running:
expr 2 3 4 + x
the output is:
Final result = 14.000000
*/
'The C Programming Language' 카테고리의 다른 글
Chapter 5 - Pointers and Arrays 12 (0) | 2017.12.22 |
---|---|
Chapter 5 - Pointers and Arrays 11 (0) | 2009.03.27 |
Chapter 5 - Pointers and Arrays 9 (0) | 2009.03.27 |
Chapter 5 - Pointers and Arrays 8 (0) | 2009.03.27 |
Chapter 5 - Pointers and Arrays 7 (0) | 2009.03.27 |