2条回答 默认 最新
- Eyre Turing 2020-02-24 13:44关注
表达式计算建议看一下《数据结构》,先转换为逆波兰表达式,然后再计算。
当然用字符串匹配也是可以的,但是这样复杂度会比较高,
匹配最里面的括号有一个方法就是寻找第一个右括号,和这个右括号对应的左括号合起来就是最里面的括号。
当然我给你一个逆波兰表达式的代码吧,可以解决你的问题,有点长,300多行:#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, "sin") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \ || strcmp(a, "ln") == 0 || strcmp(a, "exp") == 0 \ || strcmp(a, "arcsin") == 0 || strcmp(a, "arccos") == 0 || strcmp(a, "arctan") == 0) return 4; 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, "sin") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \ || strcmp(a, "ln") == 0 || strcmp(a, "exp") == 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, "sin") == 0 || strcmp(a, "cos") == 0 || strcmp(a, "tan") == 0 \ || strcmp(a, "ln") == 0 || strcmp(a, "exp") == 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, "sin") == 0) return sin(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, "exp") == 0) return exp(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; }
运行后直接输入算式就可以了。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 3无用