浅谈c--逆波兰表达式中的细节

问题:c语言 #define NUMBER '0' 标识找到一个数  的含义是什么?

这是《THE C PROGRAMMING LANGUAGE》这本书里的逆波兰表达式的原题。

本文将给出 #define NUMBER '0' 标识找到一个数 的详细解释

这里我先贴出源代码

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXOP 100

#define NUMBER '0'


int getop(char []);
void push(double);
double pop(void);

int getch(void);
void ungetch(int);

//atof函数:将字符串s转换成相应的双精度浮点数
int main(){
    int type;
    double op2;
    char s[MAXOP];

    while ((type = getop(s)) != EOF){
        switch (type){
        case NUMBER:                     
            push(atof(s));
            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 '\n':
            printf("\t%.8g\n",pop());
            break;   
        default:
            printf("error:unknown command %s\n",s);
            break;
        }
    }
    return 0;
}

#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 getop(char s[])
{
    int i,c;
    while ((s[0] = c = getch()) ==  ' '|| c == '\t');

    s[1] = '\0';
    if(!isdigit(c) && c !='.')
        return c;
    i = 0;
    if(isdigit(c))
        while (isdigit(s[++i] =c =getch()));

    if(c == '.')
        while (isdigit(s[++i] =c =getch()));

    s[i] = '\0';
    if(c != EOF)
        ungetch(c);
    return NUMBER;

}


#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
    return  (bufp>0) ? buf[--bufp]  : getchar();
}

void ungetch(int c)
{
    if(bufp>=BUFSIZE)
        printf("ungetch:too many characters\n");
    else
        buf[bufp++] = c;
}

 

这个程序是描述逆波兰表达式的,这里我把全部代码贴出来了,其中包含NUMBER的地方有三处,第一个出现是在定义的地方,第二个出现是在switch case结构中,第三个出现是在getop函数的末尾,return一个NUMBER。

 

直接看默认注释“标识找到一个数”,难以理解,本人也是想了好久才有了一点心得。

1.首先我们阅读getop函数,这个函数的作用是获得操作数或者运算符的,遇到运算符,return c,即返回运算符。遇到数字或者带小数点的数字,它返回的是 NUMBER,但变量c里面的值是操作数。

2.然后看第二处代码

while ((type = getop(s)) != EOF){

        switch (type){

        case NUMBER: 

    push(atof(s));

                break;

含义是:getop函数获得的值赋给type,然后根据获得的类型type用switch case结构进行识别进而有后面的进栈和出栈。

getop返回的运算符,case分支有运算符和它对应,getop返回NUMBER,刚好第一个分支NUMBER 和它对应,然后将输入的字符串用atof函数进栈,从而实现了整个输入的操作。

 

注1:由于switch case结构的要求,NUMBER必须是单字符常量表达式,而且type必须是变量。

如果定义个char NUMBER=‘0’显然是变量,所以必须通过宏替换的形式,#define NUMBER '0',将常量变换成变量,且能满足case后面是常量表达式的要求。

 

注2:number这个必须是单字符,无论什么字符都不重要。

若是把#define NUMBER '0'换成#define NUMBER 'a',在代码中还是能正常运行,因为本来就没有影响。

书里写的'标识找到一个数'的真正含义我认为是'定义一个标记符'。

 

上一篇:Android 12(S) 图形显示系统 - SurfaceFlinger的启动和消息队列处理机制(四)


下一篇:P1216 [USACO1.5][IOI1994]数字三角形 Number Triangles(python3实现)