中缀表达式计算器

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

例如       中缀表达式->(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 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;
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值