中缀表达式计算器

来源:互联网 发布:淘宝直通车推广方案 编辑:程序博客网 时间:2024/06/11 07:18

中缀表达式的计算主要要转换为后缀表达式。

例如       中缀表达式->(1+2)*3-4         转换为后缀表达式   12+3*4-

至于后缀表达式的计算就很容易了     设定一个栈,然后后缀表达式从左到右一次进栈,如果当前的入栈的是数字就将其压入栈中,

如果是运算符,就从栈中弹出两个数字进行相应的运算,然后将运算后的数字压回栈中。当字符串完全处理之后,栈顶就是运算结果

PS:输入的后缀表达式是合法的才行。

那么中缀表达式如何转换为后缀表达式?(ch接受中缀表达式传递过来的字符)

1:ch 是'(' 放入栈;

2: ch 是 ‘)’一次输入栈中的运算符,直到遇到‘(’为止

3:如果ch是其它的合法字符,将ch与当前栈顶比较

    a:ch优先级高于栈顶元素,ch入栈

    b:ch 优先级低于或者等于 栈顶元素,输出栈顶元素,ch入栈

4:如果中缀表达式读取完成,依次输出栈中的元素直到栈空



举个例子:

对于中缀表达式 (A-B)/C+D

1 : '('进栈

2:A->压入输出字符

3:- 入栈

4:B 压入输出字符串

5: ')'一次输出栈里面的字符到输出字符串

6: ‘/’ 入栈

7: C 压入字符串

8: ’+‘    ’/‘出栈 然后’+‘入栈

9: D    压入输出字符串

10: 将栈中剩下的字符串依次输出

#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX_STACK_SIZE 100#define MAX_EXPR_SIZE 100void postfix(char *expr,char *outstr);int eval(char *outstr);typedef enum {lparen,rparen,pluss,minuss,timess,divide,mod,eos,operand} precedence;int stack_int[MAX_STACK_SIZE];precedence stack_prece[MAX_STACK_SIZE];char expr[MAX_EXPR_SIZE];int isp[] = {1,19,12,12,13,13,13,0};int icp[] = {20,19,12,12,13,13,13,0};#define INT_ITEM 1#define PRECE_ITEM 2//入栈void push(int *top,int a,precedence b,int flag){if(*top >= MAX_STACK_SIZE - 1){printf("stack overflow.\n");exit(1);}//不同类型的元素进入不同的栈if(flag==INT_ITEM)stack_int[++*top] = a;else if(flag == PRECE_ITEM)stack_prece[++ *top] = b;}//出栈void pop(int *top,int *a,precedence *b,int flag){if(*top < 0){printf("stack overflow.\n");exit(1);}//函数传进来的 a 和 b 分别接受不同的数值if(flag == INT_ITEM)*a = stack_int [(*top)--];else if(flag == PRECE_ITEM)*b = stack_prece[(*top)--];}//将运算符号转换为特定的符号precedence get_token(char *symbol,int *n,char *expr){*symbol = expr[(*n)++];              // n 表示的是位置switch(*symbol){case '(': return lparen;case ')': return rparen;case '+': return pluss;case '-': return minuss;case '*': return timess;case '/': return divide;case '%': return mod;case '\0': return eos;default: return operand;        //数字即被操作的符号}}//特定的符号转换为运算符号char precedencetochar(precedence token){switch(token){case pluss: return '+';case minuss: return '-';case divide: return '/';case timess: return '*';case mod: return '%';case eos: return '\0';      //结束符号default : return operand;    //数字}}//将中缀表达式转换为后缀表达式void postfix(char *expr,char *outstr){char symbol;precedence token,precevalue;int n=0;int intvalue;int i=0;int top = -1;stack_prece[0] = eos;for(token = get_token(&symbol,&n,expr);token!=eos;token = get_token(&symbol,&n,expr)){//如果取得的栈顶元素是数字存到新的数组中if(token == operand)outstr[i++] = symbol;//如果遇到括号else if(token == rparen){while(stack_prece[top] != lparen){pop(&top,&intvalue,&precevalue,PRECE_ITEM);outstr[i++] = precedencetochar(precevalue);}pop(&top,&intvalue,&precevalue,PRECE_ITEM);}//如果入栈的运算符优先级比当前栈顶的优先级低,弹出当前栈顶else{if(top >=0)while(isp[stack_prece[top]] >= icp[token]){pop(&top,&intvalue,&precevalue,PRECE_ITEM);outstr[i++] = precedencetochar(precevalue);}push(&top,0,token,PRECE_ITEM);}}while(top >= 0){pop(&top,&intvalue,&precevalue,PRECE_ITEM);outstr[i++] = precedencetochar(precevalue);}outstr[i] = '\0';}//计算后缀表达式int eval(char *outstr){precedence token,precevalue;char symbol;int op1,op2,result;int n=0;int top = -1;token = get_token(&symbol,&n,outstr);precevalue = token;while(token != eos){if(token == operand)push(&top,symbol-'0',precevalue,INT_ITEM);else{pop(&top,&op2,&precevalue,INT_ITEM);pop(&top,&op1,&precevalue,INT_ITEM);switch(token){case pluss  : push(&top,op1+op2,precevalue,INT_ITEM);break;case minuss : push(&top,op1-op2,precevalue,INT_ITEM);break;case timess : push(&top,op1*op2,precevalue,INT_ITEM);break;case divide : push(&top,op1/op2,precevalue,INT_ITEM);break;case mod    : push(&top,op1%op2,precevalue,INT_ITEM);break;default : break;}}token = get_token(&symbol,&n,outstr);}pop(&top,&result,&precevalue,INT_ITEM);return result;}int main(){char expr[100],outstr[100];int result;gets(expr);                          //输入的字符串postfix(expr,outstr);result = eval(outstr);printf("the result is %d\n",result);return 0;}