为什么字符“ *”在此RPN计算器中执行乘法运算,但是如果我使用符号x表示乘法,则可以正常工作吗?

Cro*_*gle 0 c

这是Kernighan和Ritchie撰写的The C Programming Language的程序练习(第5章)。在此程序中,当我使用“ *”作为乘法运算符时,指针** argv指向argv [0],即1st(Zeroth)参数,并读取第一个字符“ P”而不是“ *”。

执行后,带有参数: ./ProgE5-10 +124 -3 * =

它返回错误的答案,而不是-372。

但是,如果将“ *”替换为“ x”,则程序可以正常运行。所有其他操作(即+,-,/,=)也可以正常工作。

请告诉我为什么*使argv指向程序名称。

//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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Can*_*rop 5

您的外壳程序(例如bash)将*字符视为全局模式,该模式已替换为当前目录中的文件列表。

$ ls
file1
file2
$ echo *
file1 file2
Run Code Online (Sandbox Code Playgroud)

这就是为什么*您的情况下的替换为的原因ProgE5-10,后者是当前目录中的文件。

如果您*在运行程序时以反斜杠转义,或将其用单引号或双引号引起来,则可以解决此问题

$ ./ProgE5-10 +124 -3 \* =
Run Code Online (Sandbox Code Playgroud)