数据结构实验:计算表达式的值--顺序栈

Posted 希声lx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构实验:计算表达式的值--顺序栈相关的知识,希望对你有一定的参考价值。

实验题目:栈的应用-算术表达式求值                      

实验环境:    Visual C++ 6.0                    

实验目的 :

1 .掌握栈的定义及实现;

2 .掌握利用栈求解算术表达式的方法。

实验内容:

通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法。对算法3.4中调用的几个函数要给出其实现过程:

(1) 函数In(c):判断c是否为运算符;

(2) 函数Precede(t1,t2):判断运算符t1和t2的优先级;

(3) 函数Operate(a,theta,b):对a和b进行二元运算theta。

程序运行时,输入合法的算术表达式(中间值及最终结果要在0~9之间,可以包括加减乘除和括号),便可输出相应的计算结果。如下图:

 

 

实验提示 : (仅供参考,每个函数的具体实现可以有多种方法,希望有创新)

1. 将栈的定义和实现单独保存在头文件“stack.h”中,然后在表达式求值的源程序中包含此头文件(即#include“stack.h”)。

2. 表达式求值源程序的具体实现

(1) 主函数如下:

void main()

 {

   Printf(“ 请输入算术表达式,并以#结束.\n”);

  Printf(“the result of expression is:%d\n”,EvaluateExpression());

 }

(2) 函数EvaluateExpression的实现见算法3.22

(3) 函数In(c)的实现可以采用以下方式:

Status In(SElemType c)// 应在前面有定义typedef char SElemType;

 { // 判断c是否为运算符

   switch(c)

   {

     case‘+‘:return TRUE;

     ……// 补充完整

default:return FALSE;

   }

 }

(4) 函数Precede(t1,t2)的实现可以采用以下形式:

SElemType Precede(SElemType t1,SElemType t2)

 { // 根据教材表3.1,判断两个运算符的优先关系

   SElemType f;

   switch(t2)

   {

     case ‘+‘:

     case ‘-‘:if(t1==‘(‘||t1==‘#‘)

                f=‘<‘;

              else

                f=‘>‘;

              break;

……// 补充完整

}

   return f;

}

(5) 函数Operate(a,theta,b)的实现可以采用以下方式:

SElemType Operate(SElemType a,SElemType theta,SElemType b)

 {

   SElemType c;

   a=a-48;

   b=b-48;

   switch(theta)

   {

     case‘+‘:c=a+b+48;

             break;

……// 补充完整

   }

   return c;

 }

 

 

选做内容: 进一步改进,使表达式的中间值及最终结果不局限于0~9之间的个位数。(如果完成要在实验报告中注明),如下图:

 

 

实验要求 :

(1) 程序要添加适当的注释,程序的书写要采用 缩进格式 。

(2) 程序要具在一定的 健壮性,即当输入数据非法时, 程序也能适当地做出反应。

(3) 程序要做到 界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

(4) 根据实验报告模板详细书写实验报告,在实验报告中给出 表达式求值算法的流程图 。

(5) 上传源程序到Sakai网络教学平台。顺序表的源程序保存为 calculator.cpp。

#include<stdio.h> 
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define OVERFLOW -2
#define MAXSIZE 100
#define OK 1 
#define ERROR 0
#define TRUE 1
#define FALSE 0
#include<iostream>
using namespace std;

typedef int Status;
typedef char SElemType;

//--------顺序栈的存储结构------
typedef struct 
{
    SElemType *base;    //栈底指针 
    SElemType *top;    //栈顶指针 
    int stacksize;     //占可用的最大容量 
}SqStack; 


Status InitStack (SqStack &S)
{//构造一个空栈 
    S.base=new SElemType[MAXSIZE];   //为顺序栈动态分配一个最大容量为MAXSIZE的数组空间 
    if (!S.base) exit(OVERFLOW);    //动态分配失败
    S.top=S.base;     //top初始为base,空栈 
    S.stacksize=MAXSIZE;   //stacksize置为栈的最大容量MAXSIZE 
    return OK;
    
}

Status Push(SqStack &S,SElemType e) 
{//插入元素e为新的栈顶元素
    if(S.top-S.base==S.stacksize)   return ERROR;   //栈满 
    *S.top++=e;    //元素e压入栈顶,栈顶指针加1 
    return OK;
    
}

Status Pop(SqStack &S,SElemType &e)
{//删除s的栈顶元素,用e返回其    
    if (S.top==S.base)  return ERROR;  //栈顶 
    e=*--S.top;   // 栈顶指针减1,将栈顶元素为e 
    return OK;
    
} 

SElemType GetTop(SqStack S) 
{//返回S的栈顶元素,不修改栈顶指针、
    if(S.top!=S.base)   //栈非空
        return *(S.top-1);   //返回栈顶元素的值,栈顶指针不变 
    
}


Status In(SElemType c)
{
    switch(c)          //判断读入的字符是哪一种运算符, 
    {
        case +:
            return TRUE;
            break; 
        case -:
            return TRUE;
            break;
        case *:
            return TRUE;
            break;
        case /:
            return TRUE;
            break;
        case (:
            return TRUE;
            break;
        case ):
            return TRUE;
            break;
        case #:
            return TRUE;
            break;
        default:
            return FALSE;
            
    }
}

SElemType Precede(SElemType t1,SElemType t2)
{
    SElemType f;       
    switch(t2)     //判断运算符栈的栈顶元素和读入的运算符之间谁的优先级更高,并返回结果 
    {
        case +:
            if (t1==(||t1==#)
                f=<;
            else
                f=>;
            break;
            
        case -:
            if (t1==(||t1==#)
                f=<;
            else
                f=>;
            break;
            
        case *:
            if (t1==+||t1==-||t1==(||t1==#)
                f=<;
            else
                f=>;
            break;
            
        case /:
            if (t1==+||t1==-||t1==(||t1==#)
                f=<;
            else
                f=>;
            break;
                
        case (:
            if (t1==+||t1==-||t1==(||t1==#||t1==*||t1==/)
                f=<;
            break;
            
        case ):
            if (t1==+||t1==-||t1==*||t1==/||t1==))
                f=>;
            else if (t1==()
                f==;
            break;
            
        case #:
            if (t1==#)
                f==;
            else
                f=>;
            break;    
        default:
            cout<<"输入超出范围。。。";
        
    }
    return f;
}


SElemType Operate(SElemType a,SElemType theta,SElemType b)
{    
    SElemType c;
    a=a-0;      //因为a,b均为字符型,所以转化成int型 
    b=b-0;
    switch(theta)
    {
        case +:
            c=a+b+0;break;        //再将计算的结果转化为字符型 
        case -:
            c=a-b+0;break;
        case *:
            c=a*b+0;break;
        case /:
            c=a/b+0;break;        
    }
    return c;   //返回计算结果 
}

char EvaluateExpression()
{//算数表达式求值的算符优先算法,设OPTR和 OPND分别为运算符栈和操作数栈
    SqStack OPND,OPTR;
    char ch,theta,a,b,c,x,w;
    InitStack(OPND);  //初始化OPND栈 
    InitStack(OPTR);  //初始化OPTR栈 
    Push(OPTR,#);   //将表达式起始符“#”OPTR栈 
    cin>>ch;
    while (ch!=#||GetTop(OPTR)!=#)    //表达式没有扫描完毕或者OPTR的栈顶元素不为“#” 
    {
        if (!In(ch))     //判断ch是不是运算符,不是则压入OPND栈 
            {
                Push(OPND,ch);
                cin>>ch;
            }
        else
            switch(Precede(GetTop(OPTR),ch))   // 比较OPTR的栈顶元素和ch的优先级 
            {
                case <:
                    Push(OPTR,ch);        //当前字符ch压入OPTR栈 ,读入下一个字符ch 
                    cin>>ch;
                    break;
                case >:
                    Pop(OPTR,theta);    //弹出OPTR栈顶的运算符 
                    Pop(OPND,b);        //弹出OPND栈顶的运算数, 
                    Pop(OPND,a);        //弹出OPND栈顶的运算数,
                    Push(OPND,Operate(a,theta,b));     //将运算结果压入OPND栈 
                    break;
                case =:               //OPTR的栈顶元素是“(”且ch是“)”
                    Pop(OPTR,x);        //弹出OPTR栈顶的"(",
                    cin>>ch;            //读入下一个字符ch 
                    break;
                
            }
    }
    return GetTop(OPND);              //OPND栈顶元素即为表达式求值结果 
    
}
int main()
{
    char w;
    cout<<"请输入算数表达式,并以#结束\n";
    w=EvaluateExpression();    //将运算结果赋值给w 
    w=w-48;         //将字符转换成数字 
    printf("The result of expression is %d\n",w); 
                   
}

 

以上是关于数据结构实验:计算表达式的值--顺序栈的主要内容,如果未能解决你的问题,请参考以下文章

用调度场算法计算表达式的值,javascript实现

山东大学数据结构实验六

Java计算字符串中的数学表达式的值算法怎么写?

c++实验4 栈及栈的应用+回文+中后缀表达式

头歌实验三Python顺序结构程序设计

头歌实验三Python顺序结构程序设计