实验四:栈ADT应用:中缀表达式求值

3 篇文章 0 订阅

栈ADT应用:中缀表达式求值


栈ADT应用:中缀表达式求值

表达式求值是进行数据处理的最基本操作。请编写程序完成一个简单算术表达式的求值。要求如下:

(1) 运算符包括:+、-、*、-、^(乘方)、括号

(2)运算量为数值常量,根据自己的能力可以对运算量做不同的约束,例如1位整数、多位整数、实数等(会有不同的测试用例);

输入:一行,即表达式,以“=”结束。例如:

       5*(8-3)+6/5=

输出:一行,即表达式的值。结果值为整数时输出为整数,如果有小数时保留5位小数。

       26.20000

测试用例

输入Result
5+(3-1)/2=6

总结:
因为老师让练习写栈的ADT,所以就没用stl的栈。
另外,<stdlib.h>中的 double atof(char &x)可以将字符串转化为数字,直至遇到第一个不为数字的字符

#include <iostream>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <iomanip>
using namespace std;

class SeqStack1            //运算符栈
{
    //顺序栈类定义
public:
    char *elements;        //数组存放栈元素
    int top=-1;            //栈顶指示器
    int maxSize;           //栈最大容量
    void overflowProcess();    //栈的溢出处理

    SeqStack1() {}
    SeqStack1(int sz);         //构造函数
    ~SeqStack1()
    {
        delete []elements;
    }
    void Push(char x);          //进栈
    bool Pop(char x);           //出栈
    bool GetTop(char &x);       //取栈顶内容
    bool IsEmpty()const
    {
        return top==-1;
    }
    bool IsFull()const
    {
        return top==maxSize-1;
    }
    int GetSize()const
    {
        return top+1;
    }
    void MakeEmpty()
    {
        top=-1;
    }
    //friend ostream&operator<<(ostream &os,SeqStack &S);       //重载运算符<<
};
bool SeqStack1::GetTop(char &x)
{
    if(top==-1)
    {
        return false;
    }
    else
    {
        x=elements[top];
        return true;
    }

}
SeqStack1::SeqStack1(int sz)          //构造函数
{
    elements=new char[sz];           //申请连续空间
    assert(elements!=NULL);          //头文件,#include <assert.h>,宏断言,如果括号内语句是假就结束程序
    top=-1;                         //栈顶指示器指向栈底
    maxSize=sz;                     //栈的最大空间
}
void SeqStack1::overflowProcess()
{
    //私有函数,当栈满则执行扩充栈存储空间处理
    char *newArray=new char[2*maxSize];   //创建更大的存储数组
    for(int i=0; i<=top; i++)
    {
        newArray[i]=elements[i];
    }
    maxSize+=maxSize;        //栈空间扩大
    delete []elements;       //释放原来的连续空间
    elements=newArray;        //改变elements指针
}
void SeqStack1::Push(char x)
{
    //若栈满,则溢出处理,将元素X插入该栈栈顶
    if(IsFull()==true)
        overflowProcess();       //栈满
    top++;
    elements[top]=x;            //栈顶指针先+1.再元素进栈
}
bool SeqStack1::Pop(char x)
{
    //若栈不空,函数退出栈顶元素并将栈顶元素赋值给X
    //返回true,否则返回false
    if(IsEmpty()==true)
        return false;
    x=elements[top--];          //先去元素,栈顶指针退1
    return true;                //退栈成功
}

class SeqStack2
{
    //顺序栈类定义
public:
    double *elements;              //数组存放栈元素
    int top=-1;                   //栈顶指示器
    int maxSize;                 //栈最大容量
    void overflowProcess();     //栈的溢出处理

    SeqStack2() {}
    SeqStack2(int sz);         //构造函数
    ~SeqStack2()
    {
        delete []elements;
    }
    void Push(double x);          //进栈
    bool Pop(double x);           //出栈
    bool GetTop(double &x);       //取栈顶内容
    bool IsEmpty()const
    {
        return top==-1;
    }
    bool IsFull()const
    {
        return top==maxSize-1;
    }
    int GetSize()const
    {
        return top+1;
    }
    void MakeEmpty()
    {
        top=-1;
    }
    //friend ostream&operator<<(ostream &os,SeqStack &S);       //重载运算符<<
};
SeqStack2::SeqStack2(int sz)          //构造函数
{
    elements=new double[sz];         //申请连续空间
    assert(elements!=NULL);          //头文件,#include <assert.h>,宏断言,如果括号内语句是假就结束程序
    top=-1;                         //栈顶指示器指向栈底
    maxSize=sz;                     //栈的最大空间
}
void SeqStack2::overflowProcess()
{
    //私有函数,当栈满则执行扩充栈存储空间处理
    double *newArray=new double[2*maxSize];   //创建更大的存储数组
    for(int i=0; i<=top; i++)
    {
        newArray[i]=elements[i];
    }
    maxSize+=maxSize;         //栈空间扩大
    delete []elements;        //释放原来的连续空间
    elements=newArray;        //改变elements指针
}
void SeqStack2::Push(double x)
{
    //若栈满,则溢出处理,将元素X插入该栈栈顶
    if(IsFull()==true)
        overflowProcess();       //栈满
    top++;
    elements[top]=x;            //栈顶指针先+1.再元素进栈
}
bool SeqStack2::Pop(double x)
{
    //若栈不空,函数退出栈顶元素并将栈顶元素赋值给X
    //返回true,否则返回false
    if(IsEmpty()==true)
        return false;
    x=elements[top--];          //先去元素,栈顶指针退1
    return true;                //退栈成功
}

int isp(char a)        //优先数
{                      
    if(a=='#')
    {
        return 0;
    }
    else if(a=='=')
    {
        return 0;
    }
    else if(a=='(')
    {
        return 0;
    }
    else if(a=='^')
    {
        return 5;
    }
    else if(a=='*'||a=='/')
    {
        return 4;
    }
    else if(a=='+' || a=='-')
    {
        return 3;
    }
    else if(a==')')
    {
        return 0;
    }
}
void DoOperator(SeqStack1 &op,SeqStack2 &figer)
{
    //取两个操作数,根据操作符op形成运算指令并计算
    double left,right,value;
    right=figer.elements[figer.top];       //最上边的操作符取出来,出栈
    figer.Pop(right);                      
    left=figer.elements[figer.top];
    figer.Pop(left);
    char opp=op.elements[op.top];         //令op=栈顶运算符
//取操作数成功,计算并进栈
        if(opp=='+')
        {
            value=left+right;            //计算结果
            figer.Push(value);           //结果压入栈中
        }
        else if(opp=='-')
        {
            value=left-right;
            figer.Push(value);
        }
        else if(opp=='*')
        {
            value=left*right;
            figer.Push(value);
        }
        else if(opp=='/')
        {
            if(right==0.0)
            {
                cerr<<"除数不能为零"<<endl;
            }
            else
            {
                value=left/right;
                figer.Push(value);
            }
        }
        else if(opp=='^')
        {
            value=pow(left,right);
            figer.Push(value);
        }
        op.Pop(opp);       //运算完的数字出栈

}
int main()
{
   SeqStack1 op(100);
   SeqStack2 figer(100);
   string str;
   cin>>str;
   for(int i=0;i<str.length();i++)
   {
       if(isdigit(str[i]))        //如果这个数是数字
       {
           double p=atof(&str[i]);      //取整个数字
           figer.Push(p);               //把整个数字入栈了
            while(isdigit(str[i]) || str[i]=='.')
            {
                i++;                    //把i移动到整个数字之后
            }
            i--;
       }
       else
       {
           if(str[i]=='(')  op.Push('(');   //括号单独处理
           else if(str[i]==')')
           {
               while(op.elements[op.top]!='(')
                        DoOperator(op,figer);
               op.Pop('(');
           }
           else if(op.IsEmpty() || isp(str[i])>isp(op.elements[op.top]))
           //空栈或当前运算符比栈顶运算符优先,当前运算符进栈
           {
               op.Push(str[i]);
           }
           else if(op.IsEmpty()==false && op.top==0 && op.elements[op.top]=='=')
           //栈不为空,且栈内只剩下一个‘=’时,出循环
           {
               break;
           }
           else if(op.IsEmpty()==false && isp(str[i])<=isp(op.elements[op.top]))
           //栈不为空,且栈顶运算符优先于当前运算符时
           {
               while(op.IsEmpty()==false  &&isp(str[i])<=isp(op.elements[op.top]))  //栈顶运算符出栈运算直到当前运算符优先于栈顶运算符,当前运算符入栈
               {
                   DoOperator(op,figer);
               }
                    op.Push(str[i]);
           }
       }
   }
  // 这时候,运算符栈已经空了,数字栈还剩最后一个结果,
  //判断这个结果是不是小数,选择不同的输出方式
   if(ceil(figer.elements[0])!=floor(figer.elements[0]))
   {
        cout<<fixed<<setprecision(5)<<figer.elements[0];
   }
   else
    cout<<figer.elements[0];
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值