问题 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;
}