设计一个程序,演示用运算符优先法对算术表达式求值的过程。
算法:
①表达式过程包含了操作数、运算符和表达式结束符"#",给每种运算符赋予一个优先数,然后设立两个栈:一个运算符栈(OPTR),一个操作数栈(OPND),分别存放运算符和操作数
②对表达式从左往右进行扫描,遇到操作数进OPND栈。遇到运算符,则比较它与OPTR栈的栈顶元素的优先数,若它的优先数更大,则将它压入栈中;否则弹出栈顶的运算符a,并从OPND栈连续弹出两个栈顶元素y和x,进行运算xay,并将结果压入OPND栈。
③在表达式左边也虚设一个"#",使得其在OPTR栈底,一旦左边的"#"与右边的"#"相遇,则表示表达式求值的结束。
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define maxsize 10
typedef struct
{
char elem[maxsize];
int top; //top表示栈顶元素的下一个空位置
}sqstacktp;
void InitStack(sqstacktp *s) //初始化栈
{
s->top=0;
}
void Push(sqstacktp *s,char ch) //入栈
{
s->elem[s->top]=ch;
s->top++;
}
char Pop(sqstacktp *s) //弹出栈顶运算符
{
s->top--;
return s->elem[s->top];
}
int precedence(char ch) //求运算符优先数
{
int z=0;
switch(ch)
{
case '+':z=1;break;
case '-':z=1;break;
case '*':z=2;break;
case '/':z=2;break;
case '(':z=3;break;
case ')':z=4;break;
case '#':z=0;break;
default:printf("error1!\n"); //输入其他字符,则显示error!
}
return z; //此z即是运算符优先数
}
int operate(int x,char ch,int y) //进行二元运算
{
int z=0;
switch(ch)
{
case '+':z=x+y;break;
case '-':z=x-y;break;
case '*':z=x*y;break;
case '/':z=x/y;break;
default:printf("error2!\n");
}
return z; //此z即是每一次的运算结果
}
int exp_reduced() //算术表达式求值的运算符优先数算法
{
char ch,theta,op[8];
sqstacktp *OPTR,*OPND;
OPTR=(sqstacktp*)malloc(sizeof(sqstacktp));
OPND=(sqstacktp*)malloc(sizeof(sqstacktp));
char x,y;
int result;
strcpy(op,"+-*/#)("); //op为运算符的集合,strcpy把字符串复制给op
InitStack(OPTR); //初始化运算符栈OPTR
Push(OPTR,'#'); //栈初始化,并在运算符栈OPTR的栈底压入表达式左边虚设的字符“#”
InitStack(OPND); //初始化操作数栈OPND
scanf("%c",&ch); //从终端读入一个字符
while(ch!='#'||OPTR->elem[OPTR->top-1]!='#') //运算结束条件是:ch=='#'&&OPTR->elem[OPTR->top-1]=='#'
{
if(!strchr(op,ch)) //判定ch是不是运算符,不是则执行以下操作
{
Push(OPND,ch); /不是运算符,则压入操作数栈
ch=getchar(); //继续从终端读入下一个字符
}
else if(precedence(ch)>precedence(OPTR->elem[OPTR->top-1])&&precedence(ch)!=4) //比较优先数
{
Push(OPTR,ch); /的优先数大于栈顶运算符优先数,则将ch压入栈中
ch=getchar(); //继续从终端读入下一个字符
}
else if(precedence(ch)<precedence(OPTR->elem[OPTR->top-1])&&precedence(OPTR->elem[OPTR->top-1])==3)
//若ch为运算符,且小于OPTR栈顶的运算符优先数,但OPTR栈顶的运算符为"(",则将ch压入栈中
{
Push(OPTR,ch);
ch=getchar();
}
else if(precedence(ch)==4) //若ch为运算符")"
{
theta=Pop(OPTR); //弹出栈顶运算符
Pop(OPTR); //抛出运算符优先数为3的"("
y=Pop(OPND);x=Pop(OPND); //连续弹出两个操作数
result=operate(x-'0',theta,y-'0'); //进行x和y的运算
Push(OPND,result+'0'); //将运算结果压入操作数栈
ch=getchar();
}
else //若ch为运算符,且小于等于OPTR栈顶的运算符优先数,则取出两个栈顶的操作数进行运算
{
theta=Pop(OPTR); //弹出栈顶运算符
y=Pop(OPND);x=Pop(OPND); //连续弹出两个操作数
result=operate(x-'0',theta,y-'0'); //进行x和y的运算
Push(OPND,result+'0'); //将运算结果压入操作数栈
}
}
return OPND->elem[OPND->top-1]-'0'; //从操作数栈顶取出表达式运算结果返回
}
int main()
{
int result;
printf("请输入算术表达式(以符号#结束):\n");
result=exp_reduced();
printf("结果是:\n%d\n",result);
return 0;
}
注意:输入算术表达式时括号需用英文的括号。