//参考文章：https://blog.csdn.net/lei20172017/article/details/116404682

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include<windows.h>
#define MAX_SIZE 1000
/*定义一个运算符栈*/
typedef struct {
    char Operator[MAX_SIZE];
    int top;
} OptorStack;
/*定义一个操作数栈*/
typedef struct {
    double Operand[MAX_SIZE];
    int top;
} OpndStack;
/*初始化运算符栈*/
void InitOptor(OptorStack *S) {
    S->top = -1;
}
/*初始化操作数栈*/
void InitOpnd(OpndStack *S) {
    S->top = -1;
}
/*运算符出栈*/
int PopOptor(OptorStack *S,int *recall,char *errmsg) {
    if(S->top==-1) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    S->top--;
    return 1;
}
/*操作数出栈*/
int PopOpnd(OpndStack *S,int *recall,char *errmsg) {
    if(S->top==-1) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    S->top--;
    return 1;
}

/*运算符入栈*/
int PushOptor(OptorStack *S,char ch,int *recall,char *errmsg) {
    if(S->top==MAX_SIZE-1) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    S->top++;
    S->Operator[S->top]=ch;
    return 1;
}
/*操作数入栈*/
int PushOpnd(OpndStack *S,double ch,int *recall,char *errmsg) {
    if(S->top==MAX_SIZE-1) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    S->top++;
    S->Operand[S->top]=ch;
    return 1;
}
/*取运算符栈栈顶元素*/
char GetOptor(OptorStack *S,int *recall,char *errmsg) {
    if(S->top==-1) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    return S->Operator[S->top];
}
/*取操作数栈栈顶元素*/
double GetOpnd(OpndStack *S,int *recall,char *errmsg) {
    if(S->top==-1) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    return S->Operand[S->top];
}
/*表达式运算函数*/
double Calculate(double a,double b,char op,int *recall,char *errmsg) {
    double result;
    if(op=='+') result=a+b;
    if(op=='-') result=a-b;
    if(op=='*') result=a*b;
    if(op=='/') {   //要防止除数为0
        if(b==0) {
            *recall=-1;
            strcpy(errmsg,"Wrong input.The divisor is not 0");
            return -1;
        }
        result=a/b;
    }
    return result;    //返回结果result
}

int change(char ch) {
    switch(ch) {
        case '+':
            return 0;
        case '-':
            return 1;
        case '*':
            return 2;
        case '/':
            return 3;
        case '(':
            return 4;
        case ')':
            return 5;
        case '#':
            return 6;
    }
}
/*定义一个算符优先关系矩阵*/
char cmp[7][8]= {">><<<>>",">><<<>>",">>>><>>",">>>><>>","<<<<<=?",">>>>?>>","<<<<<?="};
/*算符比较函数，返回优先级:>或<或=*/
int Compare(char ch1,char ch2,int *recall,char *errmsg) {
    if(cmp[change(ch1)][change(ch2)]=='?') {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return -1;
    }
    return cmp[change(ch1)][change(ch2)];
}
/*检查函数,用来检查输入的表达式的操作数和运算符的合法性*/
int Check(char *S,int len) {
    int i;
    for(i=0; i<len; i++) {
        if(S[i]>='0'&&S[i]<='9')continue;
        if(S[i]=='('||S[i]==')'||S[i]=='*'||S[i]=='/'||S[i]=='+'||S[i]=='-'||S[i]=='.')continue;
        return 0;
    }
    return 1;
}

void calculate(char *expre,int *recall,char *errmsg,double *answer) {
    SetConsoleOutputCP(65001);
    char opd[9999];   //opd用来存操作数
    int len;
    OptorStack Optor;
    OpndStack Opnd;
    InitOptor(&Optor);
    InitOpnd(&Opnd);
    PushOptor(&Optor,'#',recall,errmsg);
    len = strlen(expre);
    int kk=0;
    for(int i=0;i<len;i++){
        if(expre[len]>='0'&&expre[len]<='9')continue;
        else kk=1;
    }
    if(kk==0){
        *recall=-1;
        strcpy(errmsg,"you should make sure this is a expression.");
        return;
    }
    if (Check(expre,len) == 0) {
        *recall=-1;
        strcpy(errmsg,"Wrong input.");
        return;
    }
    int i,j=0,k=0;
    double x,y;
    expre[len] = '#';   //在expre数组后加个#结尾标志
    for (i=0; i<=len; i++) {
        if ((expre[i]>='0' && expre[i]<='9') || expre[i] == '.') {
            opd[k++] = expre[i];   //将数字字符存入操作数数组opd中
            j = 1;
            continue;
        }
        if(j) {
            opd[k] = '\0';
            PushOpnd(&Opnd,atof(opd),recall,errmsg);
            j=0;
            k=0;
        }
        switch (Compare(GetOptor(&Optor,recall,errmsg),expre[i],recall,errmsg)) {  //比较运算符栈的栈顶运算符和运算符expre[i]的优先级
            case '<':
                PushOptor(&Optor,expre[i],recall,errmsg);
                break;
            case '=':
                PopOptor(&Optor,recall,errmsg);
                break;
            case '>':
                y = GetOpnd(&Opnd,recall,errmsg),PopOpnd(&Opnd,recall,errmsg);
                x = GetOpnd(&Opnd,recall,errmsg),PopOpnd(&Opnd,recall,errmsg);
                PushOpnd(&Opnd,Calculate(x,y,GetOptor(&Optor,recall,errmsg),recall,errmsg),recall,errmsg);
                PopOptor(&Optor,recall,errmsg);
                i--;
                break;
            default:break;
        }
    }
    if(recall==-1)return;
    *answer = GetOpnd(&Opnd,recall,errmsg);
}
