project 计算器

坑爹的计算器,终于写好了!

先是遇到了栈不会用的问题,接着又遇到了转成逆波兰的问题,百度的结果五花八门,真是!

然而现在写好了,蛮有成就感的!

#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;
}

你可能感兴趣的:(project 计算器)