1. 程式人生 > >如何用C語言計算表示式的值,棧的經典應用

如何用C語言計算表示式的值,棧的經典應用

宣告:這個程式可以計算+,-,*,/,負數,小數

負數用括號括起來例如(-1)

負數的計算過程:(-1)  轉變為 (0-1)  哈哈~

 

分成六個點:

1.我的檔案結構

2.順序堆疊的標頭檔案

3.標頭檔案引入與自定義的常量和型別

4.主處理函式

5.測試的主函式

6.測試結果

 

1.我的檔案結構

有兩個檔案        1.expCop.c     裡面的內容是:

標頭檔案與自定義的常量和型別、主處理函式、測試的主函式

                          2.SqeStack.h  裡面的內容是:棧的定義與處理函式

2.順序堆疊的標頭檔案

typedef struct{
    DataType stack[MaxStackSize];
    int top;
}SeqStack;


//棧初始化
void StackInitiate(SeqStack *S){
    S->top = 0;
}
//判斷棧是否為空
int StackNotEmpty(SeqStack S){
    if(S.top==0){
        return 0;
    }
    return 1;
}
//入棧
int StackPush(SeqStack *S,DataType x){
    if(S->top>=MaxStackSize){
        printf("堆疊已滿無法插入!\n");
        return 0;
    }else{
        S->stack[S->top]=x;
        S->top++;
        return 1;
    }
}
//出棧
int StackPop(SeqStack *S,DataType *d){
    if(S->top<=0){
        printf("StackPop堆疊為空!\n");
        return 0;
    }else{
        S->top--;
        *d = S->stack[S->top];
        return 1;
    }
}
//獲取棧頂資料元素
int StackTop(SeqStack S,DataType *d){
    if(S.top<=0){
        printf("StackTop堆疊為空!\n");
        return 0;
    }else{
        *d = S.stack[S.top-1];
        return 1;
    }
}


 3.標頭檔案引入與自定義的常量和型別

typedef char DataType;//定義棧的資料存數的型別
#define MaxStackSize 100//定義棧的大小
#include <stdio.h>//這個不用多說
#include <string.h>//字串處理(自帶)
#include <math.h>//用來處理小數,用到了pow(自帶)
#include "SeqStack.h"//這是順序堆疊的標頭檔案(需要自己建立)

4.主處理函式

double expressionComputation(char *exp){
    SeqStack myStack;//對操作符進行中綴到字尾
    StackInitiate(&myStack);
    double num[100];//儲存運算元 注:在彈出操作符的以後要立刻取出num最後面兩個數字進行運算後存回num中
    int numSize = 0;
    int i,j;
    int spot = 0;
    char c;
    for(i=0;i<strlen(exp);i++){
        if((exp[i]=='0'||exp[i]=='1'||exp[i]=='2'||exp[i]=='3'||exp[i]=='4'||exp[i]=='5'||exp[i]=='6'||exp[i]=='7'||exp[i]=='8'||exp[i]=='9')&&spot==0){
            j=i+1;
            while(exp[j]=='0'||exp[j]=='1'||exp[j]=='2'||exp[j]=='3'||exp[j]=='4'||exp[j]=='5'||exp[j]=='6'||exp[j]=='7'||exp[j]=='8'||exp[j]=='9'){
                j++;
            }
            num[numSize] = num[numSize] + (exp[i]-'0') * pow(10,j-i-1);
            if(j-i-1==0&&exp[j]!='.'){
                numSize++;
            }
            continue;
        }
        if(exp[i]=='.'||spot==1){
            spot=1;
            if(exp[i]=='.'){
                j=0;
                continue;
            }else{
                j--;
            }
            num[numSize] = num[numSize] + (exp[i]-'0') * pow(10,j);
            if(exp[i+1]!='0'&&exp[i+1]!='1'&&exp[i+1]!='2'&&exp[i+1]!='3'&&exp[i+1]!='4'&&exp[i+1]!='5'&&exp[i+1]!='6'&&exp[i+1]!='7'&&exp[i+1]!='8'&&exp[i+1]!='9'){
                numSize++;
                spot=0;
            }
        }
        if(exp[i]=='+'){
            if(!StackNotEmpty(myStack)){
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='*'||c=='/'||c=='-'||c=='+')){
                while(StackTop(myStack,&c)&&(c=='*'||c=='/'||c=='-'||c=='+')){
                    StackPop(&myStack,&c);
                    switch(c){
                        case '*':num[numSize-2] = num[numSize-2]*num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                        case '/':num[numSize-2] = num[numSize-2]/num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                        case '-':num[numSize-2] = num[numSize-2]-num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                        case '+':num[numSize-2] = num[numSize-2]+num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                    }
                    if(!StackNotEmpty(myStack)){
                        break;
                    }
                }
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&c=='('){
                StackPush(&myStack,exp[i]);
            }
        }
        if(exp[i]=='-'){
            if(exp[i-1]!='0'&&exp[i-1]!='1'&&exp[i-1]!='2'&&exp[i-1]!='3'&&exp[i-1]!='4'&&exp[i-1]!='5'&&exp[i-1]!='6'&&exp[i-1]!='7'&&exp[i-1]!='8'&&exp[i-1]!='9'&&exp[i-1]!='('&&exp[i-1]!=')'){
                printf("輸入格式錯誤!Tip:負數請加括號如(-1)\n");
                break;
            }
            if(!StackNotEmpty(myStack)){
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='*'||c=='/'||c=='+'||c=='-')){
                while(StackTop(myStack,&c)&&(c=='*'||c=='/'||c=='+'||c=='-')){
                    StackPop(&myStack,&c);
                    switch(c){
                        case '*':num[numSize-2] = num[numSize-2]*num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                        case '/':num[numSize-2] = num[numSize-2]/num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                        case '+':num[numSize-2] = num[numSize-2]+num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                        case '-':num[numSize-2] = num[numSize-2]-num[numSize-1];
                                 numSize--;
                                 num[numSize]=0;
                                 break;
                    }
                    if(!StackNotEmpty(myStack)){
                        break;
                    }
                }
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='('||c==')')){
                StackPush(&myStack,exp[i]);
            }
        }
        if(exp[i]=='*'){
            if(!StackNotEmpty(myStack)||(StackTop(myStack,&c)&&(c=='+'||c=='-'))){
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='/')){
                StackPop(&myStack,&c);
                switch(c){
                    case '/':num[numSize-2] = num[numSize-2]/num[numSize-1];
                             numSize--;
                             num[numSize]=0;
                             break;
                }
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='('||c==')')){
                StackPush(&myStack,exp[i]);
            }
        }
        if(exp[i]=='/'){
            if(!StackNotEmpty(myStack)||(StackTop(myStack,&c)&&(c=='+'||c=='-'))){
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='*')){
                StackPop(&myStack,&c);
                switch(c){
                    case '*':num[numSize-2] = num[numSize-2]*num[numSize-1];
                             numSize--;
                             num[numSize]=0;
                             break;
                }
                StackPush(&myStack,exp[i]);
            }else if(StackTop(myStack,&c)&&(c=='('||c==')')){
                StackPush(&myStack,exp[i]);
            }
        }
        if(exp[i]=='('){
            StackPush(&myStack,exp[i]);
            if(exp[i+1]=='-'){
                int k=strlen(exp);
                while(k-1>i){
                    exp[k]=exp[k-1];
                    k--;
                }
                exp[i+1]='0';
            }

        }
        if(exp[i]==')'){
            while(StackTop(myStack,&c)&&c!='('){
                StackPop(&myStack,&c);
                switch(c){
                    case '*':num[numSize-2] = num[numSize-2]*num[numSize-1];
                             numSize--;
                             num[numSize]=0;
                             break;
                    case '/':num[numSize-2] = num[numSize-2]/num[numSize-1];
                             numSize--;
                             num[numSize]=0;
                             break;
                    case '+':num[numSize-2] = num[numSize-2]+num[numSize-1];
                             numSize--;
                             num[numSize]=0;
                             break;
                    case '-':num[numSize-2] = num[numSize-2]-num[numSize-1];
                             numSize--;
                             num[numSize]=0;
                             break;
                }
            }
            StackPop(&myStack,&c);
        }
    }
    while(StackNotEmpty(myStack)){
        StackPop(&myStack,&c);
        switch(c){
            case '*':num[numSize-2] = num[numSize-2]*num[numSize-1];
                     numSize--;
                     num[numSize]=0;
                     break;
            case '/':num[numSize-2] = num[numSize-2]/num[numSize-1];
                     numSize--;
                     num[numSize]=0;
                     break;
            case '+':num[numSize-2] = num[numSize-2]+num[numSize-1];
                     numSize--;
                     num[numSize]=0;
                     break;
            case '-':num[numSize-2] = num[numSize-2]-num[numSize-1];
                     numSize--;
                     num[numSize]=0;
                     break;
        }
    }
    return num[0];//最後的值
}

5.測試的主函式

void main(void){
    char exp[200]="";
    printf("請輸入一個表示式\t形如:2+3+(-5)+1.2\n");
    scanf("%s",exp);
    printf("\n結果為:%lf",expressionComputation(exp));
}

6.測試結果

 

 

可能會存在其他意想不到的錯誤,若測試出現其他錯誤請指正,我會加以修正。