C语言实现栈的中缀表达式转化为后缀表达式,并且计算后缀表达式

因为数据结构老师布置了栈的后缀表达式实验,经过思考,有以下反思。

中缀表达式转换为后缀表达式

  1. 关于括号,直接将括号里面的符号加入后缀表达式。
  2. 关于数字,直接推入后缀表达式
  3. 遇到±符号,如果栈为空或者栈顶为“(”,直接将符号推入栈,如果栈不为空,且栈顶不为“(”,则推出栈顶符号。再将±符号推入符号栈。
  4. 如果遇到“/”符号,如果如果栈为空或者栈顶为“(”,直接推入栈,如果栈不为空,且栈顶符号优先级大于或者等于“/”符号,则推出栈顶符号。再将*/符号推入符号栈。
  5. 如果最后符号栈还有符号,直接加入后缀表达式。
    实际上也就是优先级比较的问题。

后缀表达式的计算:
后缀表达式的计算,只需要从左到右,遇到运算符就计算即可,无需考虑优先级的问题
代码块如下

#include
#include
#include
typedef struct node{
	int data;
	struct node *next; 
}node,*link;
typedef struct snode
{
	char c;
	struct snode *next;
}snode,*slink;

void dealExpression();
char opTop(slink &s);
void push(link &s,int x);
void push1(slink &s,char x);
int pop1(slink &s);
int pop(link &s);
void calculate(link &s,slink &s1);
int main(void)
{
	dealExpression();
	
}
void empty(link &s)
{
	s=NULL;
}
void empty1(slink &s)
{
	s=NULL;
}
void push(link &s,int x)
{	node *p=(link )malloc(sizeof(node));
	p->data=x;
	p->next=s;
	s=p;
}
void push1(slink &s,char x)
{	snode *p=(slink )malloc(sizeof(snode));
	p->c=x;
	p->next=s;
	s=p;
}
int pop(link &s)
{
	int x;
	if(s==NULL){
		printf("it is an empty stack");

	}
	else{
		x=s->data;
		s=s->next;
		return x;
	}
}
int pop1(slink &s)
{
	snode *p=s;
	char x;
	if(s==NULL){
		printf("it is an empty stack");
	}
	else{
		x=p->c;
		s=s->next;
		free(p);
		return x;
	}
}	
char opTop(slink &s1){
if(s1==NULL){
	return 0;
}
else{
	return s1->c;
}
}
//计算,将栈中的数值和运算符进行计算 
void calculate(link &s,slink &s1)
{
	int number1,number2;
	char opf;
	number1=pop(s);
	number2=pop(s);
	opf=pop1(s1);
	int tmpResult=0;
	switch(opf){
			case '+':
					tmpResult=number1+number2;
				break;
			case '-':
					tmpResult=number2-number1;

				break;
			case '*':
					tmpResult=number2*number1;
					break;
			case '/':
					tmpResult=number2/number1;
					break;
	}
	push(s,tmpResult);
}

//将中缀表达式转化为后缀,并且存储在数值中 
void dealExpression()
{
	char change[100];
	int i=0;
	char a,b;
	node *s;
	snode *s1;
//定义节点一定要初始化节点,要不然会发生分配内存错误 
	empty(s);
	empty1(s1);
	char currentchar;
	scanf("%c",¤tchar);
//	转换过程 
	while(currentchar!='='){
	switch(currentchar){
		case '+':
		case '-':
			if(opTop(s1)==0){
				push1(s1,currentchar);
			}
			else{
				while(opTop(s1)=='+'||opTop(s1)=='-'||opTop(s1)=='*'||opTop(s1)=='/')
				{
					a=pop1(s1);
					change[i]=a;
					i++;
					printf("%c",a); 
				}
				push1(s1,currentchar);
			}
			scanf("%c",¤tchar);
			break;
		case '*':
		case '/':
			if(opTop(s1)==NULL){
				push1(s1,currentchar);
			}
			else{
				while(opTop(s1)=='*'||opTop(s1)=='/')
				{
					a=pop1(s1);
					change[i]=a;
					i++;
					printf("%c",a);
				}
				push1(s1,currentchar);
			}
			scanf("%c",¤tchar);
			break;
		case '(':
			push1(s1,currentchar);
			scanf("%c",¤tchar);
			break;
		case ')':
			while(opTop(s1)!='('){
				b=pop1(s1);
				change[i]=b;
				i++;
				printf("%c",b);
			}
			pop1(s1);
			scanf("%c",¤tchar);
			break;
		default:
			int opNum=0;
			while(currentchar>='0'¤tchar<='9'){
//				通过递归实现二位到以上的数 
				opNum=opNum*10+currentchar-'0';
				scanf("%c",¤tchar);
			}
 			change[i]=char(opNum);
			i++;
			printf("%d",opNum);
			break;
					}
		}
		while(opTop(s1)!=0)
		{
			a=pop1(s1);
			change[i]=char(a);
			i++;
			printf("%c",a);

		}
//		将转化的后缀表达式进行计算,如果遇到操作符,直接计算就可,无需考虑优先级,只需要考虑到从左至右的顺序 
		int j=0;
		while(j

遇到的问题和反思:
解决了上次中缀表达式中,地址分配错误的问题,因为上次中缀表达式,我没有将栈初始化,所以导致了地址分配错误,所以将栈初始化是很重要的。
然后遇到了case,break的问题,我大意忘记写了break,结果导致了我调试了很久才发现问题:问题是这样的,我输入的 1+2= 结果却是45,在调试中发现“+”的ASCLL码正好是43,而且在最后一次case循环中,不仅是符号栈有输入,数字栈也有输入。才发现是忘记写break,导致最后一次循环:符号栈和数字栈都有输入,符号栈的输入是“+”,数字栈的输入是“43”.所以导致最后结果是45.

你可能感兴趣的:(DAT_THINKING)