四则运算表达式计算(栈,c++)

问题 A: 数据结构作业02 – 四则运算表达式计算

题目描述
计算非负整常数四则运算表达式,可用的运算符有:+ - * / ( ) 。
输入格式
一组非负整常数四则运算表达式,每个表达式输入一行,长度不超过1024个字符,每对括号内一定包含数字。
输出格式
每个表达式的计算结果输出一行,错误的表达式输出error。
输入样例

12+5
-4-7
3-*5
((12-3)/2)+5
3+7/(2-2)

输出样例

17
error
error
9
error

数据范围与提示
算法流程:
E1:设立运算符栈和操作数栈;
E2:开始运算符#入栈,向表达式串尾添加结束运算符#;
E3:逐词读入表达式,并处理:
E31:若读入为操作数,则入栈;
E32:若读入为运算符,则与栈顶运算符相比较:
E321:若栈顶运算符优先级高于读入运算符:
弹出栈顶运算符和两个操作数,计算并将结果入栈,执行步骤E32;
E322:若栈顶运算符优先级低于读入运算符:
则将读入运算符入栈,执行步骤E3;
E323:若栈顶运算符优先级等于读入运算符:
若为#,计算结束,若为括号,则弹出运算符,执行步骤E3。
E4:检查栈状态,得到计算结果;
下面是上述方法的手算实例展示:
在这里插入图片描述
(本人写的时候没有加入‘#‘,直接判断栈空了没有)
分析输入输出样例,给出的错误情况有三种(其实四种):1.第一个入栈的是字符不是数(题目要求数是非负整数);2.连着两个运算符(括号不算);3.分母为0;(通过测试数据发现)4.括号匹配问题。

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<string>
#include<vector>
using namespace std;

struct Stack{
    int data[1024];
    int len;
};

void InitStack(Stack &S){
    S.len = 0;
}

bool IsEmpty(const Stack& S){
    return (S.len==0);
}

int Pushop(Stack& S,char e){
    S.data[S.len++] = e;
    return 0;
}

int Pushshu(Stack& S,int e){
    S.data[S.len++] = e;
    return 0;
}

int Pop(Stack& S){
    return S.data[--S.len];
}

int Topshu(Stack& S){
    int e;
    int index=S.len-1;
    e = S.data[index];
    return e;
}

char Topop(Stack& S){
    char e;
    int index=S.len-1;
    e = S.data[index];
    return e;
}

int Priority(char op)
{
    switch(op){
        case'(':return 3;
        case'*':
        case'/':return 2;
        case'+':
        case'-':return 1;
        default: return 0;
    }
}

int main()
{
    int flag,shangyige;
    Stack Sop,Shu;
    string exp;
    while(cin>>exp){
        shangyige = 0;//此是用来判断错误情况2.的
        			//个人认为错误情况2最麻烦
        flag = 1;//用于标记是否break了
        		//如果不标记一下的话输出error也会输出Top
        int i=0,temp=0;
        InitStack(Sop);
        InitStack(Shu);
        while(exp[i]!='\0'||Shu.len>1){//字符串读入完毕并不代表计算结束
            if( IsEmpty(Shu) && exp[i]!='(' && (exp[i]<'0'||exp[i]>'9') ){//判断错误情况1
                cout<<"error"<<endl;
                flag = 0;
                break;
            }else if(exp[i]==')'&&IsEmpty(Sop)){//错误情况4.的右括号比左括号多
                cout<<"error"<<endl;
                flag = 0;
                break;                
            }
            if(exp[i]>='0'&&exp[i]<='9'){
                temp = temp*10 +exp[i]-'0';//解决不是个位数的数字
                i++;
                if(exp[i]>'9'||exp[i]<'0'){
                    Pushshu(Shu,temp);
                    temp = 0;
                    shangyige = 0;
                }
            }else{
            	//右括号遇到左括号直接出栈
                if(Topop(Sop)=='(' && exp[i]==')'){
                    Pop(Sop);
                    i++;
                    continue;
                }
                if(Priority(exp[i])>Priority(Topop(Sop)) ||Topop(Sop)=='('&&exp[i]!=')'){
                    if((exp[i]=='+'||exp[i]=='-'||exp[i]=='*'||exp[i]=='/')&&shangyige!=0){
                        cout<<"error"<<endl;
                        flag = 0;
                        break;
                    }
                    Pushop(Sop,exp[i]);
                    if(exp[i]=='+'||exp[i]=='-'||exp[i]=='*'||exp[i]=='/') shangyige=1;
                    else shangyige=0;
                    i++;
                    continue;
                }
                if(Priority(exp[i])<=Priority(Topop(Sop)) || exp[i]=='\0'&&!IsEmpty(Sop) ||exp[i]==')'){
                    int num1,num2;
                    num1 = Pop(Shu);
                    num2 = Pop(Shu);
                    switch(Pop(Sop)){
                        case'+':Pushshu(Shu,num2+num1);break;
                        case'-':Pushshu(Shu,num2-num1);break;
                        case'*':Pushshu(Shu,num2*num1);break;
                        case'/':if(num1==0){//判断错误3.
                            cout<<"error"<<endl;
                            flag = 0;
                            break;
                        }Pushshu(Shu,num2/num1);
                        shangyige = 0;                      
                    }
                }
            }
            if(flag==0) break;     
        }
        if(flag!=0&&!IsEmpty(Sop)){//判断错误4的左括号比右括号多
            cout<<"error"<<endl;
            flag = 0;
        }
        if(flag) cout<<Topshu(Shu)<<endl;
    }    
    return 0;
}

上述方法操作符用字符栈,数用整数栈,Pushshu,Pushop什么的都是分着写的甚是愚笨。看老师视频学了些模板写法,再改一改自己的代码。(本来想直接按照老师的思路再敲一遍,但实在是教科书式繁琐就放弃了)(狗头保命)。

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 1024
template<typename T>

struct Stack{
    T data[MAXSIZE];
    int len;
    Stack(){//自动执行,ly再也不怕忘了初始化了
        len = 0;
    }
    void InitStack(){
        len = 0;
    }
    int Push(T t){
        data[len++] = t;
        return 0;
    }
    bool IsEmpty(){
        return len==0;
    }
    T Top(){
        return data[len-1];
    }
    int Pop(){
        return data[--len];
    }
} ;

int Priority(char op)
{
    switch(op){
        case '(':return 3;
        case '*':
        case '/':return 2;
        case '+':
        case '-':return 1;
        default: return 0;
    }
}

int main()
{
    freopen("/config/workspace/answer/test.in","r",stdin);
    int flag,shangyige;
    Stack<char> Sop;
    Stack<int> Shu;
    string exp;
    while(cin>>exp){
        Sop.InitStack();
        Shu.InitStack();
        shangyige = 0;
        flag = 1;
        int i=0,temp=0;
        while(exp[i]!='\0'||Shu.len>1){
            if( Shu.IsEmpty() && exp[i]!='(' && (exp[i]<'0'||exp[i]>'9') ){
                cout<<"error"<<endl;
                flag = 0;
                break;
            }else if(exp[i]==')'&&Sop.IsEmpty()){
                cout<<"error"<<endl;
                flag = 0;
                break;                
            }
            if(exp[i]>='0'&&exp[i]<='9'){
                temp = temp*10 +exp[i]-'0';
                i++;
                if(exp[i]>'9'||exp[i]<'0'){
                    Shu.Push(temp);
                    temp = 0;
                    shangyige = 0;
                }
            }else{
                if(Sop.Top()=='(' && exp[i]==')'){
                    Sop.Pop();
                    i++;
                    continue;
                }
                if(Priority(exp[i])>Priority(Sop.Top()) ||Sop.Top()=='('&&exp[i]!=')'){
                    if((exp[i]=='+'||exp[i]=='-'||exp[i]=='*'||exp[i]=='/')&&shangyige!=0){
                        cout<<"error"<<endl;
                        flag = 0;
                        break;
                    }
                    Sop.Push(exp[i]);
                    if(exp[i]=='+'||exp[i]=='-'||exp[i]=='*'||exp[i]=='/') shangyige=1;
                    else shangyige=0;
                    i++;
                    continue;
                }
                if(Priority(exp[i])<=Priority(Sop.Top()) || exp[i]=='\0'&&!Sop.IsEmpty() ||exp[i]==')'){
                    int num1,num2;
                    num1 = Shu.Pop();
                    num2 = Shu.Pop();
                    switch(Sop.Pop()){
                        case '+':Shu.Push(num2+num1);break;
                        case '-':Shu.Push(num2-num1);break;
                        case '*':Shu.Push(num2*num1);break;
                        case '/':if(num1==0){
                            cout<<"error"<<endl;
                            flag = 0;
                            break;
                        }Shu.Push(num2/num1);
                        shangyige = 0;                      
                    }
                }
            }
            if(flag==0) break;     
        }
        if(flag!=0&&!Sop.IsEmpty()){
            cout<<"error"<<endl;
            flag = 0;
        }
        if(flag) cout<<Shu.Top()<<endl;
    }    
    return 0;
} 

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜·肉多多·狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值