编译原理之逆波兰表达式

逆波兰表达式就是所谓的后缀表达式,运算符号都在运算变量的后面,这样计算机进行计算的时候是非常方便和快捷的。将中缀表达式转换成后缀表达式的算法如下图所示:



根据上图可以直接出来代码,另外转换为后缀表达式之后,对逆波兰表达式的计算就会很方便了,看下图:



需要注意的是,重点不在写程序,重点在于这些个图是怎么出来的,这些也都是前人的总结啊,示例代码如下:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

//栈结构
typedef struct Stack
{
	char *elem;
	int top;
	int size;
}Stack;

//初始化栈
void initStack(Stack *S)
{
	S->elem=(char *)malloc(30*sizeof(char));
	S->top=-1;
	S->size=30;
}

//判断是否栈为空
int isEmpty(Stack *S)
{
	if(S->top==-1)
		return 1;
	else
		return 0;
}

//入栈
void push(Stack *S,char x)
{
	if(S->top==S->size-1)  
	{
		printf("Stack Overflow!\n");
		return;
	}
    S->elem[++S->top]=x;
}  
   
//出栈
char pop(Stack *S)
{  
    char x;
    if(S->top==-1)
	{
		printf("Stack Empty!\n");
		return 0;
	}
    x=S->elem[S->top--];
    return x;
}

//取栈顶元素,但是不删除栈顶元素
char top(Stack *S)
{
    char x;
    if(S->top==-1)
	{
		printf("Stack Empty!\n");
		return 0;
	}
    x=S->elem[S->top];
    return x;
}

//判断当前运算符和栈顶的元素的优先级大小
int isBigger(char cur, char top)
{
	if((cur=='*' || cur=='/') && (top=='+' || top=='-'))
		return 1;
	else if(top=='(')
		return 1;
	else
		return 0;
}

//计算逆波兰表达式的值
void cal(char *buffer)
{
	int stack[30];
	int top=-1;
	unsigned int i=0;
	int j=0;
	int a,b;

	char * temp=(char *)malloc(10*sizeof(char));//存放运算分量的临时数组
	memset(temp,0,10);

	for(i;i='0' && buffer[i]<='9')
			temp[j++]=buffer[i];
		else if(buffer[i]=='&')
		{
			stack[++top]=atoi(temp);
			j=0;
			memset(temp,0,10);
		}
		else if(buffer[i]=='+')
		{
			a=stack[top--];
			b=stack[top--];
			stack[++top]=a+b;
		}
		else if(buffer[i]=='-')
		{
			a=stack[top--];
			b=stack[top--];
			stack[++top]=b-a;
		}
		else if(buffer[i]=='*')
		{
			a=stack[top--];
			b=stack[top--];
			stack[++top]=a*b;
		}
		else if(buffer[i]=='/')
		{
			a=stack[top--];
			b=stack[top--];
			stack[++top]=b/a;
		}
	}

	printf("%d\n",stack[top]);
}

int main()
{
	char ch;
	char buffer[30];
	int t=0;
	int i=0;

	Stack s;
	FILE * fp;

	initStack(&s);

	fp=freopen("in.txt","r",stdin);

	while(scanf("%c",&ch))
	{
		if(ch=='#')//若字符串扫描完毕
		{
			while(!isEmpty(&s) && top(&s)!='(')
				buffer[t++]=pop(&s);
			if(isEmpty(&s))
			{
				buffer[t]='\0';
				printf("%s\n",buffer);
				cal(buffer);
				break;
			}
			else if(top(&s)=='(')
			{
				printf("0 wrong...\n");
				break;
			}
		}

		if(ch=='+' || ch=='-' || ch=='*' || ch=='/')//运算符
		{
			//buffer[t++]='&';
			while( !isEmpty(&s) && !isBigger(ch,top(&s)))//当前运算符比栈顶元素的优先级小,并且栈不为空
			{
				buffer[t++]=pop(&s);
			}
			push(&s,ch);//栈为空,或者是当前运算符比栈顶元素的优先级大,则直接入栈
		}
		else if(ch=='(')//左括号则直接进栈
		{
			push(&s,ch);
		}
		else if(ch==')')//右括号
		{
			while(!isEmpty(&s) && top(&s)!='(')//当栈顶元素不为'(',并且栈不为空,则退栈输出
			{
				buffer[t++]=pop(&s);
			}
			if(top(&s)=='(')//如果栈顶元素为'(',则进栈
				pop(&s);
			else if(isEmpty(&s))//若栈为空,则输入的表达式有错
			{
				printf("1 wrong...\n");
				break;
			}
		}
		else if(ch>='0' && ch<='9')//输入的是运算分量
		{
			while(ch>='0' && ch<='9')
			{
				buffer[t++]=ch;
				ch=fgetc(fp);
			}
			buffer[t++]='&';
			fseek(fp,-1,1);
		}
	}

	return 0;
}




你可能感兴趣的:(算法,编译原理,buffer,fp,struct,算法,c)