数据结构习题集实习之算数表达式求值演示
问题描述:设计一个程序,演示用算符优先法对算数表达式求值的过程
基本要求:以字符形式从终端输入语法正确的,不含变量的整数表达式。利用教科书表3.1给出的算符优先关系,实现对算数四则混合运算表达式的求值,并仿照教科书的例子3-1演示在求值中运算符栈、运算数栈、输入字符和主要操作的变化过程。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SqStack_char.h"
#include "SqStack_int.h"
SqStack OPTR;
TqStack OPND;
char Express[50];
int Value;
char C='$';
void Start();
void Run();
int Read();
int IsNum(int dex);
int PriorityCom(char A,char B);
int Calculate(int A,char theta,int B);
void ShowUp(int Step);
void PrintString(int flag);
int main()
{
system("color 1e");
Start();
Run();
return 0;
}
void Start()
{
InitSqStack(&OPTR);//定义操作符栈,里面是存char字符
InitTqStack(&OPND);//定义操作数栈,里面存int 整形
PushSq(&OPTR,'#');//将一个#压入栈
scanf("%s",Express);//输入表达式
int n=strlen(Express);
Express[n]='#';//将字符串结尾以#,与保持对称
return;
}
void Run()
{
int Step=1;
printf("步骤 OPTR栈 OPND栈 输入字符 主要操作
");
ShowUp(Step);
PrintString(0);
char Cur;
int flag;
flag=Read();
GetSqTop(&OPTR,&Cur);
while(C!='#'||Cur!='#')
{
if(flag==1)
{
PushTq(&OPND,Value);//读到数值,进操作数栈
printf("PUSH(OPND,‘%d’ )
",Value);
Step++;
ShowUp(Step);
PrintString(0);
flag=Read();
}
else
{
if(PriorityCom(Cur,C)<0)//优先级大于栈顶字符,入栈
{
PushSq(&OPTR,C);
printf("PUSH(OPTR,‘%c’)
",C);
Step++;
ShowUp(Step);
PrintString(0);
flag=Read();
}
else
{
if(PriorityCom(Cur,C)==0)//优先级相等,为()的情况,出栈
{
char D;
PopSq(&OPTR,&D);
printf("POP(OPTR){消去一对括号}
");
Step++;
ShowUp(Step);
PrintString(0);
flag=Read();
}
else//优先级小于栈顶,进行求值操作
{
char theta;
int A,B;
PopSq(&OPTR,&theta);//操作符出栈
PopTq(&OPND,&B);//操作数出栈
PopTq(&OPND,&A);
PushTq(&OPND,Calculate(A,theta,B));//计算结果入栈
printf("operate(‘%d’,‘%c’,‘%d’)
",A,theta,B);
Step++;
ShowUp(Step);
PrintString(1);
flag=Read();
}
}
}//字符串结尾#与操作符栈#相遇是跳出循环
GetSqTop(&OPTR,&Cur);//结果出栈
}
printf("RETURN(GETTOP(OPND))
");
int Result;
PopTq(&OPND,&Result);//打印结果
printf("
运算结果是:%d",Result);
return;
}
int Read()//从字符串中读取操作符和操作数,其中操作数需要需要根据数个数字字符得到值
{
int i=0;
while(Express[i]!=' ')
{
if(Express[i]=='$')//已经读取过的字符化为‘$'将被跳过
i++;
else
{
if(IsNum(i)==0)
{
C=Express[i];
Express[i]='$';//将读取了的字符化为'$'
return 0;
}
else
{
Value=0;
while(IsNum(i)==1)
{
int b=Express[i]-'0';
Express[i]='$';//将读取了的字符化为'$'
Value=Value*10+b;//数字字符串转换为整形数
i++;
}
return 1;
}
}
}
return -1;
}
int IsNum(int dex)//判断是否是数字字符常量
{
if(Express[dex]>='0'&&Express[dex]<='9')
return 1;
return 0;
}
int PriorityCom(char A,char B)//对于前后两个操作符优先级的比较,确定后续操作
{
if(A=='+'||A=='-')
{
if(B=='*'||B=='/'||B=='(')
return -1;
if(B=='+'||B=='-'||B==')'||B=='#')
return 1;
}
if(A=='*'||A=='/')
{
if(B=='+'||B=='-'||B=='*'||B=='/'||B==')'||B=='#')
return 1;
if(B=='(')
return -1;
}
if(A=='(')
{
if(B==')')
return 0;
if(B=='#')
{
printf("输入表达式出现语法错误
");
exit(-1);
}
if(B=='+'||B=='-'||B=='*'||B=='/'||B=='(')
return -1;
}
if(A==')')
{
if(B=='+'||B=='-'||B=='*'||B=='/'||B==')'||B=='#')
return 1;
if(B=='(')
{
printf("输入表达式出现语法错误
");
exit(-1);
}
}
if(A=='#')
{
if(B=='+'||B=='-'||B=='*'||B=='/'||B=='(')
return -1;
if(B=='#')
return 0;
if(B==')')
{
printf("输入表达式出现语法错误
");
exit(-1);
}
}
return 0;
}
int Calculate(int A,char theta,int B)
{
int Result=0;
switch(theta)
{
case '+':
{
Result=A+B;
break;
}
case '-':
{
Result=A-B;
break;
}
case '*':
{
Result=A*B;
break;
}
case '/':
{
Result=A/B;
break;
}
}
return Result;
}
/*有flag的原因是进行运算前读取的操作符既没有进栈,也没有出栈,
但是在字符串中被抹去,当后面打印字符串时无法打印出这个字符,但后面又需要显示
*/
void ShowUp(int Step)
{
printf("%d ",Step);
TravelSq(&OPTR);
TravelTq(&OPND);
return;
}
void PrintString(int flag)//打印字符串,碰到'$’不打印
{
char *ptr=Express;
while((*ptr)!=' ')
{
if((*ptr)=='$')
ptr++;
else
break;
}
if(flag==1)
{
ptr--;
*ptr=C;
}
printf("%16s",ptr);
printf(" ");
return;
}
最后一个打印没有控制整齐,略微的瑕疵,但是结果是正确的。