数据结构实现复杂计算器(自用)

        数据结构用栈实现复杂计算器,当时真的写的我快狗带了,终于在csdn里的小角落的评论里找到大佬的代码,真的肥肠厉害!

        计算器真的好难,需要考虑的东西有很多,多位数字判断该如何办呢,要求实现开方的话,小数要如何处理呢,要实现abs的话,负数也需要考虑。括号带括号的判断该怎么具体实现。以及错误的提示,输入了两个减号该怎么报错,等等等等。在细节各方面非常复杂,让人头疼。

        我发现的大佬的代码不仅考虑了函数,还发现了双目运算符,负数,括号,空格,不止整形还有浮点数,真的令人敬佩。运算符是用了左结合性和右结合性,真的当时都没想到(捂脸),接着是优先级判断,将输入的东西分为三种,数字,函数,运算符。

        最后代码可优化的地方应该就是一些报警,没有直接显示,而是转化了一下,空格就直接无视然后能算出正确的,除0还有开方0,自己加一下就行,这个倒没什么。以及对输入了错误的运算符没有办法,比如9-+8就不行,还是会运算,看看有没有其他大佬能解决。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define ElemItem    Item
#define SUCCEED     1
#define ERROR       0
#define MAXLENGTH   20
struct Item{
    int type;                   //0表示单目运算符,1表示双目运算符,2表示数字
    double num;             //如果是数字就保存在这里
    char oper[MAXLENGTH];   //如果是运算符就保存在这里
}nullItem;
typedef struct SNode{
    ElemItem data;
    SNode *next;
}*Stack;
struct QNode{
    ElemItem data;
    QNode *next;
};
struct Queue{
    QNode *front;
    QNode *rear;
};
void initStack(Stack *s){
    *s = NULL;
}
void push(Stack *s, ElemItem e){
    SNode *p = (SNode*)malloc(sizeof(SNode));
    p->data = e;
    p->next = *s;
    *s = p;
}
int pop(Stack *s, ElemItem *e = NULL){
    if(*s == NULL){
        return ERROR;
    }
    if(e != NULL){
        *e = (*s)->data;
    }
    SNode *p = *s;
    *s = (*s)->next;
    free(p);
    return SUCCEED;
}
ElemItem getSData(Stack s){
    if(s == NULL){
        return nullItem;
    }
    return s->data;
}
void initQueue(Queue *q){
    q->front = NULL;
    q->rear = NULL;
}
void in(Queue *q, ElemItem e){
    QNode* p = (QNode*)malloc(sizeof(QNode));
    p->data = e;
    p->next = NULL;
    if(q->rear != NULL){
        q->rear->next = p;
    }
    q->rear = p;
    if(q->front == NULL){
        q->front = p;
    }
}
int out(Queue *q, ElemItem *e){
    if(q->front == NULL){
        return ERROR;
    }
    *e = q->front->data;
    QNode *p = q->front;
    q->front = q->front->next;
    free(p);
    return SUCCEED;
}
ElemItem getQData(Queue q){
    if(q.front == NULL){
        return nullItem;
    }
    return q.front->data;
}

int getPriority(char *a){				//判断优先级,将它们分为四种情况
    if(strcmp(a, "+") == 0 || strcmp(a, "-") == 0)
        return 1;
    if(strcmp(a, "*") == 0 || strcmp(a, "/") == 0)
        return 2;
    if(strcmp(a, "^") == 0)
        return 3;
    if(strcmp(a, "sqrt") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \
    || strcmp(a, "ln") == 0 || strcmp(a, "abs") == 0 \
    || strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0)
        return 4;													//xiugaileeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
    return -1;
}
int getCombination(char *a){    //1表示左结合,0表示右结合
    if(strcmp(a, "+") == 0 || strcmp(a, "-") == 0 || strcmp(a, "*") == 0 || strcmp(a, "/") == 0 || strcmp(a, "^") == 0)
        return 1;
    if(strcmp(a, "sqrt") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \
    || strcmp(a, "ln") == 0 || strcmp(a, "abs") == 0 \
    || strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0)
        return 0;
    return -1;
}
int getOrder(char *a){          //0表示单目,1表示双目
    if(strcmp(a, "+") == 0 || strcmp(a, "-") == 0 || strcmp(a, "*") == 0 || strcmp(a, "/") == 0 || strcmp(a, "^") == 0)
        return 1;
    if(strcmp(a, "sqrt") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \
    || strcmp(a, "ln") == 0 || strcmp(a, "abs") == 0 \
    || strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0)
        return 0;
    return -1;
}
double getResult0(char *oper, double a1){		//对单个数字的运算
    if(strcmp(oper, "+") == 0)
        return a1;
    if(strcmp(oper, "-") == 0)
        return -a1;
    if(strcmp(oper, "sqrt") == 0)
        return sqrt(a1);
    if(strcmp(oper, "cos") == 0)
        return cos(a1);
    if(strcmp(oper, "tan") == 0)
        return tan(a1);
    if(strcmp(oper, "ln") == 0)
        return log(a1);
    if(strcmp(oper, "abs") == 0)
        return abs(a1);
    if(strcmp(oper, "arcsin") == 0)
        return asin(a1);
    if(strcmp(oper, "arccos") == 0)
        return acos(a1);
    if(strcmp(oper, "arctan") == 0)
        return atan(a1);
    return 0;
}
double getResult1(char *oper, double a1, double a2){		//对多个数字的运算
    if(strcmp(oper, "+") == 0)
        return a1+a2;
    if(strcmp(oper, "-") == 0)
        return a1-a2;
    if(strcmp(oper, "*") == 0)
        return a1*a2;
    if(strcmp(oper, "/") == 0)
        return a1/a2;
    if(strcmp(oper, "^") == 0)
        return pow(a1,a2);
    return 0;
}
double calculate(char *expression){
//对表达式信息初步读取
    int length = strlen(expression);
    Queue firstExp;
    initQueue(&firstExp);
    int flag = -1;										//0表示数字,1表示运算符,2表示函数
    char tmp[MAXLENGTH] = {'\0'};
    for(int i=0; i<length; i++){
        if(expression[i] != ' '){
            if((expression[i] >= '0' && expression[i] <= '9') || expression[i] == '.'){
                if(flag == 1 || flag == 2){						//当读取的内容不属于数字时
                    Item item;
                    item.type = getOrder(tmp);
                    strcpy(item.oper, tmp);
                    in(&firstExp, item);
                    flag = 0;
                    tmp[0] = '\0';
                }
                if(flag == -1){
                    flag = 0;
                }
            }else{
                if(expression[i] >= 'a' && expression[i] <= 'z'){
                    if(flag == 0){							//判断内容属于函数
                        Item item;
                        item.type = 2;
                        item.num = strtod(tmp, NULL);
                        in(&firstExp, item);
                        flag = 2;
                        tmp[0] = '\0';
                    }else if(flag == 1){
                        Item item;
                        item.type = getOrder(tmp);
                        strcpy(item.oper, tmp);
                        in(&firstExp, item);
                        flag = 2;
                        tmp[0] = '\0';
                    }else if(flag == 2 && getOrder(tmp) != -1){
                        Item item;
                        item.type = getOrder(tmp);
                        strcpy(item.oper, tmp);
                        in(&firstExp, item);
                        tmp[0] = '\0';
                    }
                    if(flag == -1){
                        flag = 2;
                    }
                }else{
                    if(flag == 0){			//判断内容属于运算符
                        Item item;
                        item.type = 2;
                        item.num = strtod(tmp, NULL);
                        in(&firstExp, item);
                        flag = 1;
                        tmp[0] = '\0';
                    }else if(flag == 2){
                        Item item;
                        item.type = getOrder(tmp);
                        strcpy(item.oper, tmp);
                        in(&firstExp, item);
                        flag = 1;
                        tmp[0] = '\0';
                    }else if(flag == 1){
                        Item item;
                        item.type = getOrder(tmp);
                        strcpy(item.oper, tmp);
                        in(&firstExp, item);
                        tmp[0] = '\0';
                    }
                    if(flag == -1){
                        flag = 1;
                    }
                }
            }
            int l = strlen(tmp);
            if(l < MAXLENGTH-1){
                tmp[l] = expression[i];
                tmp[l+1] = '\0';
            }
            //printf("first runing\n");
        }
    }
    if(flag == 0){
        Item item;
        item.type = 2;
        item.num = strtod(tmp, NULL);
        in(&firstExp, item);
    }else{
        Item item;
        item.type = 1;
        strcpy(item.oper, tmp);
        in(&firstExp, item);
    }
    tmp[0] = '\0';
 
    //printf("first end\n");
    /*Item i;
    while(out(&firstExp, &i)){
        if(i.type == 2){
            printf("%lf\n", i.num);
        }else{
            printf("%s\n", i.oper);
        }
    }*/

	
	
	//生成后缀表达式
    int frontHasNum = 0;        //最开始有无数字,0表示无数字,1表示有数字,如果最开始无数字,则第一个运算符降为单目运算符
    Stack operStack;
    initStack(&operStack);
    Queue secondExp;
    initQueue(&secondExp);
    Item firstItem;
    while(out(&firstExp, &firstItem)){
        if(firstItem.type == 2){
            frontHasNum = 1;
            in(&secondExp, firstItem);
        }else{
            if(strcmp(firstItem.oper, "(") == 0){
                frontHasNum = 0;
                push(&operStack, firstItem);
            }else if(strcmp(firstItem.oper, ")") == 0){
                frontHasNum = 1;
                Item t;
                while(strcmp(getSData(operStack).oper, "(") != 0){
                    if(!pop(&operStack, &t))
                        break;
                    in(&secondExp, t);
                    //printf("second 1 while\n");
                }
                pop(&operStack);
            }else{
                Item t;
                while((getPriority(firstItem.oper) < getPriority(getSData(operStack).oper)) \
                || (getPriority(firstItem.oper)==getPriority(getSData(operStack).oper) && getCombination(getSData(operStack).oper)==1)){
                    if(!pop(&operStack, &t))
                        break;
                    in(&secondExp, t);
                    //printf("second 2 while\n");
                }
                if(frontHasNum == 0){
                    frontHasNum = 1;
                    firstItem.type = 0;
                }
                push(&operStack, firstItem);
            }
        }
        //printf("second runing\n");
    }
    while(pop(&operStack, &firstItem)){
        in(&secondExp, firstItem);
        //printf("second in runing\n");
    }
 
    //printf("second end\n");
    /*Item i2;
    while(out(&secondExp, &i2)){
        if(i2.type == 2){
            printf("%lf\n", i2.num);
        }else{
            printf("%s\n", i2.oper);
        }
    }*/

//计算
    Stack startCalculate;
    initStack(&startCalculate);
    Item startItem;
    while(out(&secondExp, &startItem)){
        if(startItem.type == 2){
            push(&startCalculate, startItem);
        }else{
            if(startItem.type == 0){
                Item a;
                pop(&startCalculate, &a);
                a.num = getResult0(startItem.oper, a.num);
                push(&startCalculate, a);
            }else if(startItem.type == 1){
                Item a1,a2;
                pop(&startCalculate, &a2);
                pop(&startCalculate, &a1);
                Item a;
                a.type = 2;
                a.num = getResult1(startItem.oper, a1.num, a2.num);
                push(&startCalculate, a);
            }
        }
        //printf("calculating\n");
    }
 
    Item result;
    pop(&startCalculate, &result);
    return result.num;
}
int main(int argc, char *argv[]){
    char exp[200] = {'\0'};
    if(argc != 2){
        printf("输入表达式:\n");
        //scanf("%s", exp);
        gets(exp);
    }else{
        strcpy(exp, argv[1]);
    }
    printf("计算结果为:%lf\n", calculate(exp));
    return 0;
}

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值