I have been learning C with [K&R Book 2nd Ed][1]. And well, so far I've gotten to chapter five, and I've been dealing with pointers/command line arguments.

I came up with the following solution for the exercise (Chapter 5, Ex-5.10):

> Exercise 5-10. 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).

I would like to know how to improve it.:

    /*-
     *	Exercise 5-10. 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).
     *
     *	By jr.chavez
     *
     *	NOTE:
     *		To receive the expected output with the following example:
     *			2 3 4 + *
     *		'\' must be used (e.g., 2 3 4 + \* instead of *)
     */
    #include <stdio.h>
    #include <stdlib.h>	/* for atof() */
    #include <string.h>	/* for strlen() */
    #include <ctype.h>	/* for isdigit() */
    
    #define NUMBER	'0'		/* signal that a number was found */
    #define MAXVAL	100		/* next free stack position */
    
    static int sp = 0;		/* next free stack position */
    static double val[MAXVAL];	/* value stack */
    
    void push(double);
    double pop(void);
    
    /* reverse Polish calculator */
    int
    main(int argc, char *argv[])
    {
    	int type, c;
    	double op2;
    	
    	while (--argc > 0) {
    		{
    			char *p = *++argv;
    			type = (!isdigit(c = *p) && strlen(p) == 1) ? c : 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
    				fprintf(stderr, "error: zero divisor\n");
    			break;
    		default:
    			fprintf(stderr, "error: unkown command %s\n", *argv);
    			argc = 1;
    			break;
    		}
    	}
    	printf("\t%.8g\n", pop()); 
    	return 0;
    }
    
    
    /* push: push f onto value stack */
    void
    push(double f)
    {
    	if (sp < MAXVAL)
    		val[sp++] = f;
    	else
    		fprintf(stderr, "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 {
    		fprintf(stderr, "error: empty stack\n");
    		return 0.0;
    	}
    }


input:

    ./bin/main 2 3 4 + \*

output:

    14

Note: I decided not to add options like sin, cos, exp, and pow.

  [1]: https://en.wikipedia.org/wiki/The_C_Programming_Language