算術表達式求值


  表達式求值是實現程序設計語言的基本問題之一,也是棧的應用的一個典型例子。設計一個程序,演示用算符優先法對算術表達式求值的過程

  (1)從鍵盤輸入任意一個語法正確的(中綴)表達式,顯示並保存該表達式。

  (2)利用棧結構,把上述(中綴)表達式轉換成后綴表達式,並顯示棧的狀態變化過程和所得到的后綴表達式。

  (3)利用棧結構,對上述后綴表達式進行求值,並顯示棧的狀態變化過程和最終結果。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 100
#define M 10
char suffix[N];             //后綴表達式
char ret[2];                //字符串棧進行彈出時的返回值(彈出元素)
char tokens[N][M];          //令牌,將中綴表達式分解后的字符串數組
char ctokens[N][M];         //令牌,將后綴表達式分解后的字符串數組
int count;                  //tokens令牌的個數
int value;                  //表達式的值
int l = 0;                  //ctokens令牌的個數
typedef struct stack1{      //操作符棧
    int  top;
    char elem[N][2];
}stacki;
typedef struct stack2{      //操作數棧
    int top;
    int elem[N];
}stackj;
typedef stacki* STACK;      //指向操作符棧的指針
typedef stackj* DSTACK;     //指向操作數棧的指針

void toSuffix(char *str);                   //將中綴表達式轉化成后綴表達式
int PreParse(char tokens[][M],char *str);   //將中綴表達式分解成令牌返回令牌中字符串個數
int GetProsity(char *ch);                   //獲得操作符的優先級並返回
void push(STACK S,char *opt);               //操作符棧的入棧
char *pop(STACK S);                         //操作符棧的出棧,並返回出棧元素
int IsEmpty(STACK S);                       //判斷操作符棧是否為空
void MakeNull(STACK S);                     //將操作符棧制空
void PrintStack(STACK S);                   //打印操作符棧
void dpush(DSTACK S,int opd);               //操作符數的入棧
void dpop(DSTACK S);                        //操作符數的出棧
void PrintStack1(DSTACK S);                 //打印操作數棧
void MakeNull1(DSTACK S);                   //將操作數棧制空
int Evalute(char ctokens[][M]);             //計算后綴表達式的值並返回

int main()
{
    char str[N];
    printf("Please input a expression:\n");
    gets(str);                              //輸入所求中綴表達式str
    toSuffix(str);                          //將中綴表達式轉化成后綴表達式
    puts(suffix);                           //輸出轉化后的后綴表達式
    value = Evalute(ctokens);               //計算后綴表達式的值
    printf("%d",value);
    return 0;
}

void toSuffix(char *str)
{
    int i;
    stacki stacks;                          //定義一個操作符棧stacks
    STACK optstack = &stacks;               //定義操作符棧指針optstack
    MakeNull(optstack);
    count = PreParse(tokens,str);
    for(i = 0;i < count;i++)
    {
        if(!(strcmp(tokens[i],"+") && strcmp(tokens[i],"-") && strcmp(tokens[i],"*") && strcmp(tokens[i],"/") && strcmp(tokens[i],"(") && strcmp(tokens[i],")")))
        {
            if(IsEmpty(optstack))
            {
                push(optstack,tokens[i]);
                PrintStack(optstack);
            }
            else
            {
                if(!strcmp(tokens[i],"("))
                {
                    push(optstack,tokens[i]);
                    PrintStack(optstack);
                }
                else if(!strcmp(tokens[i],")"))
                {
                    while(strcmp(optstack->elem[optstack->top],"("))        //循環直到遇見左括號
                    {
                        strcpy(ctokens[l],optstack->elem[optstack->top]);
                        l++;
                        strcat(suffix,pop(optstack));
                        PrintStack(optstack);
                    }
                    pop(optstack);                                          //左括號彈出
                    PrintStack(optstack);
                }
                else
                {
                    if(GetProsity(tokens[i]) > GetProsity(optstack->elem[optstack->top]))
                    {
                        push(optstack,tokens[i]);
                        PrintStack(optstack);
                    }
                    else
                    {
                        while(optstack->top < 100)
                        {
                            if(GetProsity(tokens[i]) <= GetProsity(optstack->elem[optstack->top]))
                            {
                                strcpy(ctokens[l],optstack->elem[optstack->top]);
                                l++;
                                strcat(suffix,pop(optstack));
                                PrintStack(optstack);
                            }
                            else
                            {
                                break;
                            }
                        }
                        push(optstack,tokens[i]);
                        PrintStack(optstack);
                    }
                }
            }
        }
        else                            //是數字則直接加到suffix的后面
        {
            strcpy(ctokens[l],tokens[i]);
            l++;
            strcat(suffix,tokens[i]);
        }
    }
    while(optstack->top < 100)          //將剩余元素彈出
    {
        strcpy(ctokens[l],optstack->elem[optstack->top]);
        l++;
        strcat(suffix,pop(optstack));
    }
    PrintStack(optstack);
}

int PreParse(char tokens[][M],char *str)
{
    char p[N];
    char temp[2];
    int i=0,j = 0,l,k = 0;
    for(i = 0;i < strlen(str);i++)      //刪除表達式中的空格
    {
        if(str[i] == ' ') continue;
        else
        {
            p[j] = str[i];
            j++;
        }
    }
    p[j] = '\0';
    i = 0;
    for(j = 0;j < strlen(p);j++)
    {
        if(p[j] == '+' || p[j] == '-' || p[j] == '*' || p[j] == '/' || p[j] == '(' || p[j] == ')')    //運算符轉化為字符串
        {
            temp[0] = p[j];
            temp[1] = '\0';
            strcpy(tokens[k],temp);
        }
        else
        {
            for(l = 0;isdigit(p[j]);l++)                    //得到多位數字的字符串
            {
                tokens[k][l] = p[j];
                j++;
            }
            tokens[k][l] = '\0';
            j--;
        }
        k++;
    }
    return k ;
}

int GetProsity(char *ch)
{
    int prosity;
    if(!(strcmp(ch,"(")))
    {
        prosity = 0;
    }
    if(!(strcmp(ch,"+") && strcmp(ch,"-")))
    {
        prosity = 1;
    }
    if(!(strcmp(ch,"*") && strcmp(ch,"/")))
    {
        prosity = 2;
    }
    return prosity;
}

void push(STACK S,char *opt)
{
    if(S->top == 0)
    {
        return ;
    }
    S->top--;
    strcpy(S->elem[S->top],opt);
    return ;
}

char *pop(STACK S)
{
        strcpy(ret,S->elem[S->top]);
        S->top++;
        return ret;

}

int IsEmpty(STACK S)
{
    if(S->top > N - 1)
        return 1;
    else
        return 0;
}

void MakeNull(STACK S)
{
    S->top = N ;
}

void MakeNull1(DSTACK S)
{
    S->top = N ;
}
void PrintStack(STACK S)
{
    int i;
    for(i = N-1;i >= S->top;i--)
    {
        printf("%s",S->elem[i]);
    }
    printf("\n");
}

void dpush(DSTACK S,int opd)
{
    if(S->top == 0)
    {
        return ;
    }
    S->top--;
    S->elem[S->top] = opd;
}

void dpop(DSTACK S)
{
    S->top++;
}

void PrintStack1(DSTACK S)
{
    int i;
    for(i = N-1;i >= S->top;i--)
    {
        printf("%d ",S->elem[i]);
    }
    printf("\n");
}
int Evalute(char ctokens[][M])
{
    int i;
    int ropd,lopd;
    int t;
    stackj stack;                   //定義一個操作數棧
    DSTACK opdstack = &stack;       //初始化操作數棧指針
    MakeNull1(opdstack);
    for(i = 0;i < l;i++)
    {
        if(!strcmp(ctokens[i],"+")) //操作符則彈出兩棧內元素進行相應運算
        {
            ropd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            lopd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            t = lopd + ropd;
            dpush(opdstack,t);
            PrintStack1(opdstack);
        }
        else if(!strcmp(ctokens[i],"-"))
        {
            ropd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            lopd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            t = lopd - ropd;
            dpush(opdstack,t);
            PrintStack1(opdstack);
        }
        else if(!strcmp(ctokens[i],"*"))
        {
            ropd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            lopd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            t = lopd * ropd;
            dpush(opdstack,t);
            PrintStack1(opdstack);
        }
        else if(!strcmp(ctokens[i],"/"))
        {
            ropd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            lopd = opdstack->elem[opdstack->top];
            dpop(opdstack);
            t = lopd / ropd;
            dpush(opdstack,t);
            PrintStack1(opdstack);
        }
        else            //操作數入棧
        {
            dpush(opdstack,atoi(ctokens[i]));
            PrintStack1(opdstack);
        }
    }
    value = opdstack->elem[opdstack->top];
    return value;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM