中缀表达式的计算主要要转换为后缀表达式。
例如 中缀表达式->(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
#include
#include
#define MAX_STACK_SIZE 100
#define MAX_EXPR_SIZE 100
void 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;
}