哈工大数据结构与算法 实验1——算术表达式求值

实验题目:算术表达式求值(算术计算器)

实验内容:

        表达式求值是实现程序设计语言的基本问题之一,也是栈的应用的一个典型例子。一个算术表达式是由操作数(operand)、运算符(operator)和界限符 (delimiter)组成的。假设操作数是正整数,运算符只含加减乘除等四种二元运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。引入表达式起始、结束符是为了方便。设计一个程序,演示算术表达式求值的过程。

实验要求:

1. 从文本文件输入任意一个语法正确的(中缀)表达式。
2. 利用栈结构,把(中缀)表达式转换成后缀表达式,并以适当的方式展示栈的状态变化过程和所得到的后缀表达式。
3. 利用栈结构,对后缀表达式进行求值,并以适当的方式展示栈的状态变化过程和最终结果。

目录

实验题目:算术表达式求值(算术计算器)

存储结构

中缀表达式转后缀表达式

后缀表达式求值

测试结果

反思与总结

完整代码


存储结构

typedef struct stack
{
    int top;
    ElemType elements[maxlength];
}STACK;

typedef struct stack_int
{
    int top;
    Elem elements[maxlength];
}STACK_Int;

/*将栈置为空*/
void MakeNull(STACK *s)
{
    s->top=maxlength;
}

void MakeNull_Int(STACK_Int *s)
{
    s->top=maxlength;
}

/*判断是否为空,为空返回1,否则返回0*/
int Empty(STACK s)
{
    if(s.top<maxlength)
        return 0;
    else
        return 1;
}

int Empty_Int(STACK_Int s)
{
    if(s.top<maxlength)
        return 0;
    else
        return 1;
}

/*返回栈顶元素,若stack为空则返回0*/
ElemType Top(STACK s)
{
    if(Empty(s)==1)
    {
        return 0;
    }
    else
    {
        return s.elements[s.top];
    }
}

Elem Top_Int(STACK_Int s)
{
    if(Empty_Int(s)==1)
    {
        return 0;
    }
    else
    {
        return s.elements[s.top];
    }
}

void Display(STACK s)
{
    while(s.top!=maxlength)
    {
        printf("%c ",s.elements[s.top]);
        s.top++;
    }
}

void Display_Int(STACK_Int s)
{
    while(s.top!=maxlength)
    {
        printf("%d ",s.elements[s.top]);
        s.top++;
    }
}

/*删除栈顶元素*/
void Pop(STACK *s)
{
    if(Empty(*s) == 1)
    {
        printf("Stack is empty!");
    }
    else
    {
        s->top=s->top+1;
    }
}

void Pop_Int(STACK_Int *s)
{
    if(Empty_Int(*s) == 1)
    {
        printf("Stack is empty!");
    }
    else
    {
        s->top=s->top+1;
    }
}

/*将元素x压入栈顶*/
void Push(STACK *s,ElemType x)
{
    if(s->top==0)
    {
        printf("Stack is full!");
    }
    else
    {
        s->top=s->top-1;
        s->elements[s->top]=x;
    }
}

void Push_Int(STACK_Int *s,Elem x)
{
    if(s->top==0)
    {
        printf("Stack is full!");
    }
    else
    {
        s->top=s->top-1;
        s->elements[s->top]=x;
    }
}

中缀表达式转后缀表达式

        初始化一个栈,用于保存暂时还不能确定运算顺序的运算符,从左到右处理各个元素,直到末尾。可能遇到三种情况:

  1. 遇到操作数。直接加入后缀表达式。
  2. 遇到 '(' 直接入栈;遇到 ')' 则依次弹出栈内运算符并加入后缀表达式,直到遇到界限符 '(' 为止。注意:'(' 不加入后缀表达式。
  3. 遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到 '(' 或栈空则停止,之后再把当前运算符入栈。

        按上述方法处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式。

void Infix_to_Suffix(char suffix[20])
{
    char ch,p;
    STACK s;
    int i=0,tag=1;
    MakeNull(&s);
    FILE *fp;
    fp=fopen("Input.txt","r+");//打开文件
    if(fp == NULL)
    {
        printf("Fail!");
        exit(0);
    }
    ch=fgetc(fp);
    while(ch != '#')//读到第一个界限符#处
    {
        ch=fgetc(fp);
    }

    while(ch != EOF)
    {
        ch=fgetc(fp);
        if(ch >= '0'&&ch <= '9')//数字直接加入表达式中
        {
            suffix[i]=ch;
            i++;
        }
        else if(ch == '(')//遇到左括号直接入栈
        {
            Push(&s,ch);
        }
        else if(ch == ')')//依次弹出栈内符号
        {
            p=Top(s);
            while(p != '(')
            {
                suffix[i]=p;
                i++;
                Pop(&s);
                p=Top(s);
            }
            Pop(&s);//弹出左括号
        }
        else if(ch=='+'||ch=='-')
        {
            if(Empty(s))//栈为空
            {
                Push(&s,ch);
            }
            else
            {
                p=Top(s);
                while(Empty(s)==0 && p!='(')//栈为空或遇到左括号停止
                {
                    suffix[i]=p;
                    i++;
                    Pop(&s);
                    p=Top(s);
                }
                Push(&s,ch);
            }
        }
        else if(ch=='*'||ch=='/')
        {
            if(Empty(s))//栈为空
            {
                Push(&s,ch);
            }
            else if(Top(s)=='+'||Top(s)=='-')
            {
                Push(&s,ch);
            }
            else
            {
                p=Top(s);
                while((p=='*'||p=='/')&&(p!='('))
                {
                    suffix[i]=p;
                    i++;
                    Pop(&s);
                    p=Top(s);
                }
            }
        }
        printf("第%2d轮栈中元素 ",tag);//显示栈变化
        tag++;
        Display(s);
        printf("\n");

    }//全部读取完后栈中剩余元素出栈
    while(!Empty(s))
    {
        suffix[i]=Top(s);
        i++;
        Pop(&s);
    }
    suffix[i]='#';
}

后缀表达式求值

        用栈实现后缀表达式的计算,从左往右扫描下一个元素,直到处理完所有元素

  1. 若扫描到操作数则压入栈
  2. 若扫描到运算符,则弹出两个栈顶元素,执行相应运算,运算结果压回栈顶
void Calculation(char suffix[20])
{
    int i=0,tag;
    int value;
    int temp1,temp2;
    STACK s;
    MakeNull(&s);//字符栈
    STACK_Int a;
    MakeNull_Int(&a);//数值栈
    while(suffix[i] != '#')
    {
        if(suffix[i]>='0'&&suffix[i]<='9')
        {

                Push_Int(&a,suffix[i]-48);

        }
        else
        {
            temp1=Top_Int(a);
            Pop_Int(&a);
            temp2=Top_Int(a);
            Pop_Int(&a);
            if(suffix[i]=='+')
            {
                value=temp2+temp1;
            }
            else if(suffix[i]=='-')
            {
                value=temp2-temp1;
            }
            else if(suffix[i]=='*')
            {
                value=temp2*temp1;
            }
            else if(suffix[i]=='/')
            {
                value=temp2/temp1;
            }
            Push_Int(&a,value);
        }
        printf("第%2d轮栈中元素为:",tag);//记录栈的变化
        Display_Int(a);
        tag++;
        printf("\n");
        i++;
    }
    printf("结果为%d",Top_Int(a));
}

测试结果

Code::Blocks下读入文件和测试结果如下:

 

反思与总结

  • 从文件读入时使用fgetc()函数,一次仅读入一个字符,未考虑数值为两位数及更多位数的情况
  • 减法和除法时注意相减和相除的顺序
  • 栈的实现时使用了分别定义了字符栈和整型栈,有些繁杂,需考虑是否可以适当简化

完整代码

#include <stdio.h>
#include <stdlib.h>
#define maxlength 30
#define ElemType char
#define Elem int

typedef struct stack
{
    int top;
    ElemType elements[maxlength];
}STACK;

typedef struct stack_int
{
    int top;
    Elem elements[maxlength];
}STACK_Int;

/*将栈置为空*/
void MakeNull(STACK *s)
{
    s->top=maxlength;
}

void MakeNull_Int(STACK_Int *s)
{
    s->top=maxlength;
}

/*判断是否为空,为空返回1,否则返回0*/
int Empty(STACK s)
{
    if(s.top<maxlength)
        return 0;
    else
        return 1;
}

int Empty_Int(STACK_Int s)
{
    if(s.top<maxlength)
        return 0;
    else
        return 1;
}

/*返回栈顶元素,若stack为空则返回0*/
ElemType Top(STACK s)
{
    if(Empty(s)==1)
    {
        return 0;
    }
    else
    {
        return s.elements[s.top];
    }
}

Elem Top_Int(STACK_Int s)
{
    if(Empty_Int(s)==1)
    {
        return 0;
    }
    else
    {
        return s.elements[s.top];
    }
}

void Display(STACK s)
{
    while(s.top!=maxlength)
    {
        printf("%c ",s.elements[s.top]);
        s.top++;
    }
}

void Display_Int(STACK_Int s)
{
    while(s.top!=maxlength)
    {
        printf("%d ",s.elements[s.top]);
        s.top++;
    }
}

/*删除栈顶元素*/
void Pop(STACK *s)
{
    if(Empty(*s) == 1)
    {
        printf("Stack is empty!");
    }
    else
    {
        s->top=s->top+1;
    }
}

void Pop_Int(STACK_Int *s)
{
    if(Empty_Int(*s) == 1)
    {
        printf("Stack is empty!");
    }
    else
    {
        s->top=s->top+1;
    }
}

/*将元素x压入栈顶*/
void Push(STACK *s,ElemType x)
{
    if(s->top==0)
    {
        printf("Stack is full!");
    }
    else
    {
        s->top=s->top-1;
        s->elements[s->top]=x;
    }
}

void Push_Int(STACK_Int *s,Elem x)
{
    if(s->top==0)
    {
        printf("Stack is full!");
    }
    else
    {
        s->top=s->top-1;
        s->elements[s->top]=x;
    }
}

void Infix_to_Suffix(char suffix[20])
{
    char ch,p;
    STACK s;
    int i=0,tag=1;
    MakeNull(&s);
    FILE *fp;
    fp=fopen("Input.txt","r+");//打开文件
    if(fp == NULL)
    {
        printf("Fail!");
        exit(0);
    }
    ch=fgetc(fp);
    while(ch != '#')//读到第一个界限符#处
    {
        ch=fgetc(fp);
    }

    while(ch != EOF)
    {
        ch=fgetc(fp);
        if(ch >= '0'&&ch <= '9')//数字直接加入表达式中
        {
            suffix[i]=ch;
            i++;
        }
        else if(ch == '(')//遇到左括号直接入栈
        {
            Push(&s,ch);
        }
        else if(ch == ')')//依次弹出栈内符号
        {
            p=Top(s);
            while(p != '(')
            {
                suffix[i]=p;
                i++;
                Pop(&s);
                p=Top(s);
            }
            Pop(&s);//弹出左括号
        }
        else if(ch=='+'||ch=='-')
        {
            if(Empty(s))//栈为空
            {
                Push(&s,ch);
            }
            else
            {
                p=Top(s);
                while(Empty(s)==0 && p!='(')//栈为空或遇到左括号停止
                {
                    suffix[i]=p;
                    i++;
                    Pop(&s);
                    p=Top(s);
                }
                Push(&s,ch);
            }
        }
        else if(ch=='*'||ch=='/')
        {
            if(Empty(s))//栈为空
            {
                Push(&s,ch);
            }
            else if(Top(s)=='+'||Top(s)=='-')
            {
                Push(&s,ch);
            }
            else
            {
                p=Top(s);
                while((p=='*'||p=='/')&&(p!='('))
                {
                    suffix[i]=p;
                    i++;
                    Pop(&s);
                    p=Top(s);
                }
            }
        }
        printf("第%2d轮栈中元素 ",tag);//显示栈变化
        tag++;
        Display(s);
        printf("\n");

    }//全部读取完后栈中剩余元素出栈
    while(!Empty(s))
    {
        suffix[i]=Top(s);
        i++;
        Pop(&s);
    }
    suffix[i]='#';
}

void Calculation(char suffix[20])
{
    int i=0,tag;
    int value;
    int temp1,temp2;
    STACK s;
    MakeNull(&s);//字符栈
    STACK_Int a;
    MakeNull_Int(&a);//数值栈
    while(suffix[i] != '#')
    {
        if(suffix[i]>='0'&&suffix[i]<='9')
        {

                Push_Int(&a,suffix[i]-48);

        }
        else
        {
            temp1=Top_Int(a);
            Pop_Int(&a);
            temp2=Top_Int(a);
            Pop_Int(&a);
            if(suffix[i]=='+')
            {
                value=temp2+temp1;
            }
            else if(suffix[i]=='-')
            {
                value=temp2-temp1;
            }
            else if(suffix[i]=='*')
            {
                value=temp2*temp1;
            }
            else if(suffix[i]=='/')
            {
                value=temp2/temp1;
            }
            Push_Int(&a,value);
        }
        printf("第%2d轮栈中元素为:",tag);//记录栈的变化
        Display_Int(a);
        tag++;
        printf("\n");
        i++;
    }
    printf("结果为%d",Top_Int(a));
}

int main()
{
    char suffix[20];
    Infix_to_Suffix(suffix);
    int i=0;
    while(suffix[i]!='#')
    {
        printf("%c ",suffix[i]);
        i++;
    }
    printf("\n");
    Calculation(suffix);
    return 0;
}

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值