坑爹的计算器,终于写好了!
先是遇到了栈不会用的问题,接着又遇到了转成逆波兰的问题,百度的结果五花八门,真是!
然而现在写好了,蛮有成就感的!
#include<iostream>
#include<cstdio>
#include<stack>
#include<string>
#include<cstring>
#include<cctype>
#include<map>
#include<cstdlib>
#include<iomanip>
#include<cmath>
#include<windows.h>
using namespace std;
class project
{
public:
void scanf(){getline(cin,str);}
string get_str(){return str;}
string get_nib(){return nib;}
void clear(){nib.clear();}
bool check(string);
void to_nib(string);
double calulate(string);
void welcome();
void deletespace(string);
private:
string nib;
string str;
double answer;
};
void project::welcome()
{
cout<<" ";
cout<<"欢迎使用pjr版计算器!"<<endl<<endl;
cout<<"该计算器具有如下功能:"<<endl<<endl;
cout<<"\t1.能够计算四则混合运算\n";
cout<<"\t2.在四则混合运算中允许括号的使用(但括号必须是英文版括号)\n";
cout<<"\t3.能够计算浮点数,计算结果保留两位小数\n";
cout<<"\t4.在混合运算时能够计算幂次\n";
cout<<endl<<endl;
cout<<"请输入要计算的次数:";
}
检查格式错误
bool project::check(string str)
{
int len=str.size(),cnt=0;
if(str[0]=='*'||str[0]=='/'||str[0]=='+') return 0;
for(int i=0;i<len;i++)//看是否存在1+2a的形式
{
if(isdigit(str[i])!=0||str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]==' '||str[i]=='('||str[i]==')'||str[i]=='^'||str[i]=='.')
cnt++;
}
if(cnt<len) return 0;
for(int i=0;i<len;i++)//看是否存在3+-2这种形式
{
if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/')
{
int p=i+1;
while(str[p]==' '&&p<len) p++;
if(str[p]=='+'||str[p]=='-'||str[p]=='*'||str[p]=='/') return 0;
}
}
for(int i=0;i<len;i++)//判断是否存在1 2+3型
{
if((isdigit(str[i])!=0||str[i]=='.')&&str[i+1]==' ')
{
int p=i+1;
while(str[p]==' '&&p<len) p++;
if(str[p]!='+'&&str[p]!='-'&&str[p]!='*'&&str[p]!='/') return 0;
}
}
int cnt1=0,cnt2=0;//判断括号数量是否一一对应
for(int i=0;i<len;i++)
{
if(str[i]=='(') cnt1++;
else if(str[i]==')') cnt2++;
}
if(cnt1!=cnt2) return 0;
for(int i=0;i<len;i++) //判断是否存在3(6+4)7这种情况
{
if(str[i]=='(')
{
while(str[i]==' '&&i>0) i--;
if(isdigit(str[i])!=0) return 0;
}
else if(str[i]==')')
{
while(str[i]==' '&&i<len) i++;
if(isdigit(str[i])!=0||str[i]=='(') return 0;
}
}
int j=0;//判断3+)3+4(这种情况
while(str[j]==' '||str[j]=='.'||isdigit(str[j])!=0||str[j]=='+'||str[j]=='-'||str[j]=='*'||str[j]=='/'||str[j]=='^') j++;
if(str[j]==')') return 0;
for(int i=0;i<len;i++)//判断3.14.14这种情况
{
string tem;int b=i;
if(str[b]=='.')
{
while(isdigit(str[b+1])!=0&&b<len) b++;
if(str[b+1]=='.') return 0;
}
}
return 1;//都无误返回1
}
/清除所有的空格
void project::deletespace(string tem)
{
string tmp;
for(int i=0;i<tem.size();i++)
{
if(tem[i]!=' ')
tmp+=tem[i];
}
str=tmp;
}
///转成逆波兰
void project::to_nib(string str)
{
int cnt=0;
for(int i=0;i<str.size();i++)
{
if(str[i]=='.'||isdigit(str[i])!=0)
cnt++;
}
if(cnt==str.size()) str="0+"+str;
if(str[0]=='(') str="0+"+str;
if(str[0]=='-') str='0'+str;
string tmp;
for(int i=0;i<str.size();i++)
{
if(str[i]=='(')
{
if(str[i+1]=='+'||str[i+1]=='-')
tmp+='0';
}
tmp+=str[i];
}
str=tmp;
int i=0,k=0;
string tem[81];
stack<string> num;
stack<char> symbol;
map<char,int> f;
f['+']=0;f['-']=0;
f['*']=1;f['/']=1;
f['^']=2;f['(']=-1;
while(i<str.size())
{
while((isdigit(str[i])!=0||str[i]=='.')&&i<str.size())
{
tem[k]+=str[i];
nib+=str[i++];
}
nib+='~';
num.push(tem[k++]);
line:
if(isdigit(str[i])==0&&(str[i]=='('||symbol.empty()!=0)&&i<str.size())
{
symbol.push(str[i++]);
goto line;
}
else if(str[i]==')')
{
while(symbol.top()!='(')
{
nib+=symbol.top();
symbol.pop();
}
symbol.pop();i++;
goto line;
}
else if(isdigit(str[i])==0&&f[str[i]]>f[symbol.top()]&&i<str.size())
{
symbol.push(str[i++]);
goto line;
}
else if(f[str[i]]<=f[symbol.top()]&&isdigit(str[i])==0&&i<str.size())
{
while(symbol.size()>0&&f[str[i]]<=f[symbol.top()])
{
nib+=symbol.top();
symbol.pop();
}
symbol.push(str[i++]);
goto line;
}
}
while(symbol.size()>1)
{
nib+=symbol.top();
symbol.pop();
}
nib+=symbol.top();
}
/计算部分
double project::calulate(string str)
{
int i=0,j=0,k=0;
stack<double> num;
string tem[80];
double x,y;
while(i<str.size())
{
while((str[i]=='.'||isdigit(str[i])!=0)&&i<str.size())
{
tem[k]+=str[i];
i++;
}
if(isdigit(tem[k][0])!=0)
{
num.push(atof(tem[k].c_str()));
k++;
}
while((str[i]=='~'||str[i]==' ')&&i<str.size()) i++;
if(isdigit(str[i])!=0&&i<str.size()) continue;
else
{
switch(str[i])
{
case '+':
x=num.top();num.pop();
y=num.top();num.pop();
num.push(y+x);
break;
case '-':
x=num.top();num.pop();
y=num.top();num.pop();
num.push(y-x);
break;
case '*':
x=num.top();num.pop();
y=num.top();num.pop();
num.push(y*x);
break;
case '/':
x=num.top();num.pop();
y=num.top();num.pop();
num.push(y/x);
break;
case '^':
x=num.top();num.pop();
y=num.top();num.pop();
num.push(pow(y,x));
}
i++;
}
}
answer=num.top();
return answer;
}
int main()
{
project A;
A.welcome();
int n;
cin>>n;
getchar();
while(n--)
{
cout<<endl;
cout<<"请正确输入您的计算式:";
A.scanf();
if(A.check(A.get_str())==0) cout<<"PE"<<endl;
else
{
A.deletespace(A.get_str());
A.to_nib(A.get_str());
cout<<endl<<"上式的计算结果为:";
cout<<fixed<<setprecision(2);
cout<<A.calulate(A.get_nib())<<endl;
A.clear();
}
}
return 0;
}