【存档】逆波兰后缀式:表达式求值

可以double(小数点后一位),不能负数。

#include<iostream>
#include<string.h>
#include <sstream>
using namespace std;

//链栈的存储结构
typedef struct StackNode
{
	string data;
	struct StackNode *next;
}StackNode,*LinkStack;

LinkStack S,op,S1,S2;

//初始化
void InitStack(LinkStack&S)
{
	S=NULL;	
} 

//入栈
void Push(LinkStack &S,string e) 
{
	LinkStack p=new StackNode;
	p->data=e;
	p->next=S;
	S=p;
}

//出栈
int Pop(LinkStack &S,string &e)
{
	if(S==NULL) return 0;
	e=S->data;
	LinkStack p=S;
	S=S->next;
	delete p;
	return 1;
} 

//取栈顶 
string GetTop(LinkStack S)
{
	if(S!=NULL) return S->data;
}

//判是否为空,空1 
int Empty(LinkStack S)
{
	if(S==NULL) return 1;
	else return 0;
} 

//比较操作符优先级
int cmp(string a,string b)
{
	int a1,b1;
	if(a=="*"||a=="/") a1=1;
	else if(a=="+"||a=="-") a1=0;
	else if(a=="(") a1=-1;
	if(b=="*"||b=="/")  b1=1;
	else if(b=="+"||b=="-") b1=0;
	else if(b=="(") b1=-1;
	if(a1==b1) return 0;
	else if(a1>b1) return 1;
	else if(a1<b1) return -1;
} 

//获取式子
void GetSz(LinkStack &S,LinkStack &op)
{
	cout<<"请输入式子:"<<endl;
	string a,b;
	getline(cin,a);
	b=a;
	
	//把符号的位置空出来,为了获取double  
	for(int i=0;b[i];i++)
	{
		if(b[i]=='+'||b[i]=='-'||b[i]=='*'||b[i]=='/'||b[i]=='('||b[i]==')'||b[i]=='('||b[i]==')') b[i]=' ';
	}
	b=b+" ";
	a=a+" ";
	string c;
	for(int i=0;b[i];i++)
	{
		if(i==0&&(a[i]=='('||a[i]=='('))
		{
			c="(";
			Push(op,c);
			c.clear();
			continue;
		}
		if(b[i]!=' ')
		{
			c=c+b[i];
		}
		else
		{
			//是空格,这里有操作符 
			if(c.size())
			{
				Push(S,c);
				//cout<<c<<endl;
				c.clear();
			}
			
			//放不是右括号的操作符
			if(a[i]!=')'&&a[i]!=' '&&a[i]!=')') 
			{
				string d;
				d.clear();
				d=d+a[i];
				
				//若op是空的就直接放进去 
				if(Empty(op)) Push(op,d);
				//不是空的
				else
				{
					if(d=="(") 
					{
						Push(op,d);
						d.clear();
						continue;
					}
					int comp=cmp(d,GetTop(op));
					if(comp==0) //优先级相同 
					{
						string t=GetTop(op);
						Push(S,t);
						Pop(op,t);
						Push(op,d);
					}
					
					else if(comp==1) Push(op,d);//高 
					else
					{
						while(comp==-1)//低 
						{
							string e=GetTop(op);
							Push(S,e);
							Pop(op,e);
							if(GetTop(op)=="(") break; 
							comp=cmp(d,GetTop(op));
						}
						Push(op,d);
					}
				} 
			}
			else
			{
				if(a[i]==' ') continue;
				string d;
				while(GetTop(op)!="(")
				{
					Pop(op,d);
					Push(S,d);
				}
				//删除(
				if(GetTop(op)=="(") Pop(op,d);
				
				
			}
			
		}
	}
	
	//数字放完了,放op剩下的操作符
	while(!Empty(op)) 
	{
		string e=GetTop(op);
		Push(S,e);
		Pop(op,e);
	}
	
} 

//单位double to string 函数
string DWdts(int a)
{
	//a:0~9
	switch(a)
	{
		case 0:
			return "0";
		case 1:
			return "1";
		case 2:
			return "2";
		case 3:
			return "3";
		case 4:
			return "4";
		case 5:
			return "5";
		case 6:
			return "6";
		case 7:
			return "7";
		case 8:
			return "8";
		case 9:
			return "9";
	}
} 

//double to string 函数
string DoubleToString(double a)
{
	//用强制转换来判断是否有小数点
	int ta=int(a);
	int temp;
	string ans,ans1;
	//无小数点 
	if(ta==a) 
	{
		if(ta==0) ans1="0";
		while(ta!=0)
		{
			temp=ta%10;
			ta=ta/10;
			ans=ans+DWdts(temp);
		}
		
		//反转回来 
		for(int i=ans.size()-1;i>=0;i--)
		{
			ans1=ans1+ans[i];
		}
		ans=ans1;
	}
	
	//有小数点
	else
	{		
		//小数点后的tb 
		int tb=10*a-10*ta;
		if(ta==0) ans1="0";
		while(ta!=0)
		{
			temp=ta%10;
			ta=ta/10;
			ans=ans+DWdts(temp);
		}
		
		//反转回来 
		for(int i=ans.size()-1;i>=0;i--)
		{
			ans1=ans1+ans[i];
		}
		ans=ans1;
		ans=ans+".";
		
		//将tb转为整数				
		int tbb=tb;		
		ans1.clear();
		while(tbb!=0)
		{
			temp=tbb%10;
			tbb=tbb/10;
			ans1=ans1+DWdts(temp);
		}
		for(int i=ans1.size()-1;i>=0;i--)
		{
			ans=ans+ans1[i];
		}
	} 
	
	return ans;
} 

//3个string 计算的函数
string calculate(string a,string b,string op)
{
	double ta,tb,ans;
	stringstream sa,sb;
	sa<<a;
	sa>>ta;
	sb<<b;
	sb>>tb;
	
	if(op=="+") ans=tb+ta;
	else if(op=="-") ans=tb-ta;
	else if(op=="*") ans=tb*ta;
	else if(op=="/") ans=tb/ta;
	
	//double to string 
	string ans1=DoubleToString(ans);
	return ans1;
} 

//转置栈
void TurnStack(LinkStack S,LinkStack &S2)
{
	string a;
	while(!Empty(S))
	{
		Pop(S,a);
		Push(S2,a);
	}
}


//得出答案的运算函数
string GetAns(LinkStack &S2,LinkStack &S1)
{
	string a;
	while(!Empty(S2))
	{
		Pop(S2,a);
		//cout<<a<<endl;
		if(a=="+"||a=="-"||a=="*"||a=="/")
		{
			string b,c;
			Pop(S1,b);
			Pop(S1,c);
			//cout<<b<<" "<<c<<endl;
			string ans=calculate(b,c,a);
			//cout<<ans<<endl;
			Push(S2,ans);
		}
		else Push(S1,a);
	}
	return GetTop(S1);
} 

//用来测试栈S里元素的顺序的函数
void show(LinkStack S) 
{
	while(!Empty(S))
	{
		cout<<GetTop(S)<<endl;
		string temp;
		Pop(S,temp);
	}
}

int main()
{
	InitStack(S);
	InitStack(S1);
	InitStack(S2);
	InitStack(op);
	GetSz(S,op);
//	show(S);
//	return 0;
	TurnStack(S,S2);	
	string a;
	a=GetAns(S2,S1);
	cout<<"答案是:";
	cout<<a;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

karshey

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

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

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

打赏作者

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

抵扣说明:

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

余额充值