数据结构习题集之算数表达式求值演示

数据结构习题集实习之算数表达式求值演示

问题描述:设计一个程序,演示用算符优先法对算数表达式求值的过程

基本要求:以字符形式从终端输入语法正确的,不含变量的整数表达式。利用教科书表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("步骤\tOPTR栈\tOPND栈\t        输入字符\t主要操作\n");
    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’ )\n",Value);
             Step++;
             ShowUp(Step);
             PrintString(0);
             flag=Read();
        }
        else
        {
            if(PriorityCom(Cur,C)<0)//优先级大于栈顶字符,入栈
            {
                PushSq(&OPTR,C);
                printf("PUSH(OPTR,‘%c’)\n",C);
                Step++;
                ShowUp(Step);
                PrintString(0);
                flag=Read();
            }
            else
            {
                if(PriorityCom(Cur,C)==0)//优先级相等,为()的情况,出栈
                {
                    char D;
                    PopSq(&OPTR,&D);
                    printf("POP(OPTR){消去一对括号}\n");
                    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’)\n",A,theta,B);
                    Step++;
                    ShowUp(Step);
                    PrintString(1);
                    flag=Read();
                }
            }
        }//字符串结尾#与操作符栈#相遇是跳出循环
        GetSqTop(&OPTR,&Cur);//结果出栈
    }
    printf("RETURN(GETTOP(OPND))\n");
    int Result;
    PopTq(&OPND,&Result);//打印结果
    printf("\n运算结果是:%d",Result);
    return;
}
int Read()//从字符串中读取操作符和操作数,其中操作数需要需要根据数个数字字符得到值
{
    int i=0;
    while(Express[i]!='\0')
    {
        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("输入表达式出现语法错误\n");
            exit(-1);
        }
        if(B=='+'||B=='-'||B=='*'||B=='/'||B=='(')
            return -1;
    }
    if(A==')')
    {
        if(B=='+'||B=='-'||B=='*'||B=='/'||B==')'||B=='#')
            return 1;
        if(B=='(')
        {
            printf("输入表达式出现语法错误\n");
            exit(-1);
        }
    }
    if(A=='#')
    {
        if(B=='+'||B=='-'||B=='*'||B=='/'||B=='(')
            return -1;
        if(B=='#')
            return 0;
        if(B==')')
        {
            printf("输入表达式出现语法错误\n");
            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\t",Step);
    TravelSq(&OPTR);
    TravelTq(&OPND);
    return;
}
void PrintString(int flag)//打印字符串,碰到'$’不打印
{
    char *ptr=Express;
    while((*ptr)!='\0')
    {
        if((*ptr)=='$')
            ptr++;
        else
            break;
    }
    if(flag==1)
    {
        ptr--;
        *ptr=C;
    }
    printf("%16s",ptr);
    printf("\t");
    return;
}

最后一个打印没有控制整齐,略微的瑕疵,但是结果是正确的。

posted on 2019-07-09 12:58  偷影子的人儿  阅读(80)  评论(0编辑  收藏  举报