This is program exercise from The C Programming Language by Kernighan and Ritchie (Chap 5). In this program, when I use '*' as multiplication operator the the pointer **argv points to argv[0] i.e. 1st(Zeroth) argument and reads 1st character 'P' instead of '*'.
Upon execution, with arguments: ./ProgE5-10 +124 -3 * =
it returns incorrect answer instead of -372.
But if replace '*' with 'x' the program works fine. All other operations (viz. +, -, /, =) are also working fine.
Please tell me why * makes argv to point to Program Name.
//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 C+4).
//For multiplication character '*' is not working
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXLINE 1000
#define NUMBER 0
int sign = 1;
char s[MAXLINE];
void calc (int type);
int main(int argc, char *argv[])
{
if (argc < 4)
printf("Usage: ./<programName> op1 op2 operator\n");
else
{
int i, d;
int c;
while (--argc > 0 && (c = **++argv) != '\n')
{
i = 0;
printf("\nargc = %d\tc = %c:%d", argc, c, c);
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '\n')
{
printf("\nNon-Digit: %c : ", c);
if ((c == '+' || c == '-') && isdigit(d = *++(argv[0])))
{
printf("\tSign");
sign = (c == '-') ? -1 : 1;
c = d;
goto DOWN1;
}
else
{
printf("Operator");
printf("\nRead Operator: %c\n", c);
calc(c);
goto DOWN2; //To avoid re-executing calc(Number) which
//is outside any loop in main when operator
//is read and operation is performed.
}
}
DOWN1: while (isdigit(c = *argv[0]))
{
s[i++] = c;
c = *++(argv[0]);
if (**argv == '.')
{
s[i++] = **argv;
while (isdigit(*++(argv[0])))
s[i++] = **argv;
}
s[i] = '\0';
printf("\ns[] = %s", s);
}
calc(NUMBER); //Outside while to get single push of s[]
//after reading the complete number
DOWN2: ;
}
}
return 0;
}
void push (double f);
double pop(void);
void calc (int type)
{
double op2, res;
switch(type)
{
case NUMBER:
push(sign*atof(s));
sign = 1;
break;
case '+':
push(pop() + pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '*':
push(pop() * pop());
break;
case '/':
op2 = pop();
push(pop() / op2);
break;
case '=':
res = pop();
push(res);
printf("\t\t\t||Result = %lg||\n", res);
break;
case '\n':
break;
default:
printf("\nError: Invalid Operator!\n");
break;
}
}
#define STACKSIZE 1000
double val[STACKSIZE];
int sp = 0;
void push(double f)
{
if (sp >= STACKSIZE)
printf("\nError: Stack Overflow!\n");
else
val[sp++] = f, printf("\nNum %lg Pushed to Stack\n", f);
}
double pop(void)
{
if (sp != 0)
{
double ret = val[--sp];
printf("\nNum %lg Popped from the Stack\n", ret);
return ret;
}
else
{
printf("\nError: Stack Empty!\n");
return 0.0;
}
}