C++中实现表达式的求解

要写一个计算器,如果要进行连续运算,则要将中缀表达式转化为后缀表达式再求解。

步骤:

1) 从中缀表达式中提取每一项、存放到队列中;2) 将中缀表达式转换成后缀表达式;3) 计算后缀表达式的值。

功能:1、+-/*四则运算2、小数运算

 

先将字符串保存到中缀表达式队列中:

struct node
{
	double num;
	char symbol;
	bool sign;//判断是数字或者符号,false即 为符号
	double dot;
	int priority;
};
	queue<node> Q1;		//Q1保存中缀表达式
	queue<node> Q2;		//Q2保存后缀表达式
	stack<node> Sc;    //中—后
void save()1) 从中缀表达式中提取每一项、存放到队列中;
{
node tmp;//临时节点

	char str[100];
 	scanf("%s",str);//输入中缀表达式
	for(int i=0;str[i]!='\0';i++)
	{
		if(Q1.empty()==0&&Q1.back().sign==false)//当前队列尾部元素是数值
		{
			if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
			{
				if(	Q1.back().dot>0)
				{
					Q1.back().dot/=10;
					Q1.back().num=Q1.back().num+(str[i]-48)*Q1.back().dot;
				}
				else Q1.back().num=Q1.back().num*10+str[i]-48;
			}
			else if(str[i]=='.')
			{
					Q1.back().dot=1;
			}
			else //新加入的元素是符号
			{
				tmp.sign=true;
				tmp.symbol=str[i];
				if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
				else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
				Q1.push(tmp);
			}
		}
		else 
		{
			if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
			{
				tmp.sign=false;
				tmp.num=str[i]-48;
				Q1.push(tmp);
			}
			else //新加入的元素是符号
			{
				tmp.sign=true;
				tmp.symbol=str[i];
				if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
				else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
				Q1.push(tmp);
			}
		}

	}
}


将中缀表达式转换为后缀表达式:

具体算法:

自左至右扫描iQ1,读入每项并分析其对应的语法成分:
1)当输入的是操作数,则直接输出到Q2中。
2)当输入的是运算符op( 四则运算+ - */ 之一)时:
       A)循环,当(栈非空  and 栈顶运算符的优先级不低于输入运算符的优先级时),反复操作:将栈顶元素弹出,输出到Q2中。
       B)把输入的运算符op压栈。
3)最后,当中缀表达式Q1的符号序列全部读入后,在栈中可能还会一些项,它们是原来压入还没有处理的语法成分。对待它们的方法是:把它们依次从栈中弹出,并输出到后缀表达式Q2的尾部。

 

void change()//2) 将中缀表达式转换成后缀表达式;
{
	while(Q1.empty()==0)
	{
		if(Q1.front().sign==false)//是数字,放入队列
		{
			Q2.push(Q1.front());
		}
		else
		{
			if(Q1.front().symbol=='(')//当输入的是左括号,则把它压栈。
			   Sc.push(Q1.front());
			else if(Sc.empty()==1)
				Sc.push(Q1.front());
			else if(Q1.front().priority<=Sc.top().priority)
			{
				while(Sc.empty()==0&&Q1.front().priority<=Sc.top().priority)
				{
					Q2.push(Sc.top());
					Sc.pop();
				}
				Sc.push(Q1.front());
			}
			else 
				Sc.push(Q1.front());
			
		}
		Q1.pop();
	}
	while(!Sc.empty())
	{
		Q2.push(Sc.top());
		Sc.pop();
	}
	/*printf("转换为后缀表达式:\n");
	while(Q2.empty()==0)
	{
		if(Q2.front().sign==false)  printf("%f ",Q2.front().num);
		else if(Q2.front().sign==true)   printf("%c ",Q2.front().symbol);
		Q2.pop();
	}*/
	
}


后缀表达式的求解:

算法:

1如果读入的是一个操作数,则压栈;
2如果读入的是一个运算符,则从栈中两次取出栈顶的项,按照该运算符对这两个操作数进行计算,然后将计算结果压入栈顶。

 

double calculate()
{
	stack<node> stmp;
	double num1=0;
	double num2=0;
	node tmp;
	while(Q2.empty()==0)
	{
		if(Q2.front().sign==false)
		{
			stmp.push(Q2.front());
		}
		else if(Q2.front().sign==true) 
		{
			num2=stmp.top().num;
			stmp.pop();
			num1=stmp.top().num;
			stmp.pop();
			if(Q2.front().symbol=='+')  
			{
				tmp.num=num1+num2;
				tmp.priority=1;
				tmp.sign=false;
			}
			else if(Q2.front().symbol=='-')
			{
				tmp.num=num1-num2;
				tmp.priority=1;
				tmp.sign=false;
			}
			else if(Q2.front().symbol=='*')
			{
				tmp.num=num1*num2;
				tmp.priority=2;
				tmp.sign=false;
			}
			else if(Q2.front().symbol=='/')
			{
				tmp.num=num1/num2;
				tmp.priority=2;
				tmp.sign=false;
			}
			stmp.push(tmp);
		}
		Q2.pop();
	}
	return stmp.top().num;
}


总体代码:

/*步骤:
1) 从中缀表达式中提取每一项、存放到队列中;
2) 将中缀表达式转换成后缀表达式;
3) 计算后缀表达式的值。

功能:
1、+-/*四则运算
2、无()小括号
3、小数运算
*/
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;

struct node
{
	double num;
	char symbol;
	bool sign;//判断是数字或者符号,false即 为符号
	double dot;
	int priority;
};
	queue<node> Q1;		//Q1保存中缀表达式
	queue<node> Q2;		//Q2保存后缀表达式
	stack<node> Sc;    //中—后
void save()1) 从中缀表达式中提取每一项、存放到队列中;
{
node tmp;//临时节点

	char str[100];
 	scanf("%s",str);//输入中缀表达式
	for(int i=0;str[i]!='\0';i++)
	{
		if(Q1.empty()==0&&Q1.back().sign==false)//当前队列尾部元素是数值
		{
			if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
			{
				if(	Q1.back().dot>0)
				{
					Q1.back().dot/=10;
					Q1.back().num=Q1.back().num+(str[i]-48)*Q1.back().dot;
				}
				else Q1.back().num=Q1.back().num*10+str[i]-48;
			}
			else if(str[i]=='.')
			{
					Q1.back().dot=1;
			}
			else //新加入的元素是符号
			{
				tmp.sign=true;
				tmp.symbol=str[i];
				if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
				else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
				Q1.push(tmp);
			}
		}
		else 
		{
			if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
			{
				tmp.sign=false;
				tmp.num=str[i]-48;
				Q1.push(tmp);
			}
			else //新加入的元素是符号
			{
				tmp.sign=true;
				tmp.symbol=str[i];
				if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
				else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
				Q1.push(tmp);
			}
		}

	}
}

void change()//2) 将中缀表达式转换成后缀表达式;
{
	while(Q1.empty()==0)
	{
		if(Q1.front().sign==false)//是数字,放入队列
		{
			Q2.push(Q1.front());
		}
		else
		{
			if(Q1.front().symbol=='(')//当输入的是左括号,则把它压栈。
			   Sc.push(Q1.front());
			else if(Sc.empty()==1)
				Sc.push(Q1.front());
			else if(Q1.front().priority<=Sc.top().priority)
			{
				while(Sc.empty()==0&&Q1.front().priority<=Sc.top().priority)
				{
					Q2.push(Sc.top());
					Sc.pop();
				}
				Sc.push(Q1.front());
			}
			else 
				Sc.push(Q1.front());
			
		}
		Q1.pop();
	}
	while(!Sc.empty())
	{
		Q2.push(Sc.top());
		Sc.pop();
	}
	/*printf("转换为后缀表达式:\n");
	while(Q2.empty()==0)
	{
		if(Q2.front().sign==false)  printf("%f ",Q2.front().num);
		else if(Q2.front().sign==true)   printf("%c ",Q2.front().symbol);
		Q2.pop();
	}*/
	
}

double calculate()
{
	stack<node> stmp;
	double num1=0;
	double num2=0;
	node tmp;
	while(Q2.empty()==0)
	{
		if(Q2.front().sign==false)
		{
			stmp.push(Q2.front());
		}
		else if(Q2.front().sign==true) 
		{
			num2=stmp.top().num;
			stmp.pop();
			num1=stmp.top().num;
			stmp.pop();
			if(Q2.front().symbol=='+')  
			{
				tmp.num=num1+num2;
				tmp.priority=1;
				tmp.sign=false;
			}
			else if(Q2.front().symbol=='-')
			{
				tmp.num=num1-num2;
				tmp.priority=1;
				tmp.sign=false;
			}
			else if(Q2.front().symbol=='*')
			{
				tmp.num=num1*num2;
				tmp.priority=2;
				tmp.sign=false;
			}
			else if(Q2.front().symbol=='/')
			{
				tmp.num=num1/num2;
				tmp.priority=2;
				tmp.sign=false;
			}
			stmp.push(tmp);
		}
		Q2.pop();
	}
	return stmp.top().num;
}



int main()
{
	save();//1) 从中缀表达式中提取每一项、存放到队列中;
    change();
		double result=calculate();
		printf("%f ",result);
	
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值