字符串的四则运算

个人知道的有俩种解法

1、渐降解析法,弄不好容易出错,不太推荐,参看华为机试-2014

2、逆波兰式的方法。将中序表达式转成后序!((Reverse Polishnotation,RPN)

逆波兰式的规则如下:参见:http://www.cnblogs.com/stay-foolish/archive/2012/04/25/2470590.html

(1)首先,需要分配2个栈,栈s1用于临时存储运算符(含一个结束符号),此运算符在栈内遵循越往栈顶优先级越高的原则;栈s2用于输入逆波兰式,为方便起见,栈s1需先放入一个优先级最低的运算符,在这里假定为'#';

(2)从中缀式的左端开始逐个读取字符x,逐序进行如下步骤:

  1.若x是操作数,则分析出完整的运算数(在这里为方便,用字母代替数字),将x直接压入栈s2;

  2.若x是运算符,则分情况讨论:

    若x是'(',则直接压入栈s1;

    若x是')',则将距离栈s1栈顶的最近的'('之间的运算符,逐个出栈,依次压入栈s2,此时抛弃'(';

    若x是除'('和')'外的运算符,则再分如下情况讨论:

      若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;

      若当前栈s1的栈顶元素不为'(',则将x与栈s1的栈顶元素比较,若x的优先级大于栈s1栈顶运算符优先级,则将x直接压  入栈s1。否者(小于等于),将栈s1的栈顶运算符弹出,压入栈s2中,直到栈s1的栈顶运算符优先级别低于(不包括等  于)x的优先级,或栈s2的栈顶运算符为'(',此时再则将x压入栈s1;

(3)在进行完(2)后,检查栈s1是否为空,若不为空,则将栈中元素依次弹出并压入栈s2中(不包括'#');

(4)完成上述步骤后,栈s2便为逆波兰式输出结果。但是栈s2应做一下逆序处理,因为此时表达式的首字符位于栈底;


对于逆波兰式的求解,只需将逆波兰式压入一个栈中,遇到操作符,就弹出俩个数进行求解。计算时想判断是否有俩个数。再者0不能为除数!!

以下为代码:

#include <iostream>
#include <string>
#include <stack>
using namespace std;

string rpn_str(string &str);
int calculate(string &str);

bool error_my = false;

int main()
{
	string str,str_res;
	int res ;
	cin>>str; 
	str_res = rpn_str(str);
	 
	if (str_res.size() > 0)
	{
		cout<< "calculate ";
	  res = calculate(str_res);
	}
	else
	{
		error_my = true;
	}
	if (error_my )
	{
		cout<<"false"<<endl;
	}
	else
	{
		cout<<res<<endl;
	}
	return 0;
}

string rpn_str(string &str)
{
	if (str.empty())
	{
		return string("");
	}
	stack<char> op;
	stack<char> res;
	
	op.push('#');
	int i = 0;
	while(str[i] != '\0')
	{
		if (str[i] >= '0' && str[i] <= '9')
		{
			res.push(str[i]);
			i++;//下标增加
			continue;
		}

		switch (str[i])
		{
			case  '(':
				op.push('(');
				break;
			
			case  '+':
			case  '-':
			{
				
				char ch = op.top();
				while(ch == '+'||ch == '-'||ch == '*'||ch == '/')
				{
					op.pop();
					res.push(ch);
					ch = op.top();//再取栈顶
				}
				op.push(str[i]);
			}
				break;

			case  '*':
			case  '/':
			{
				char ch = op.top();
				while(ch == '*'||ch == '/')
				{
					op.pop();
					res.push(ch);
					ch = op.top();//再取栈顶
				}
				op.push(str[i]);
			 }
				break;

			case  ')':
			{			
				char ch = op.top();

				while(ch != '(' && ch != '#')
				{
					op.pop();
					res.push(ch);
					ch = op.top();//再取栈顶
				}
				if (ch != '(')
				{
					return string("");
				}
				op.pop();
			}
				break;
			default: 
				return string("");
				break;
		}	
		i++;//下标增加
	}

	while(op.size() > 1)
	{
		res.push(op.top());
		op.pop();
	}
	
	string final(res.size(),'0');
	int k = res.size();
	while(!res.empty())
	{
		
		final[k-1] = res.top();
		k--;
		res.pop();
	}
	 
	return final;

}

int calculate(string &str)
{
	
	error_my = false; 
	if (str.size() == 0)
	{
		error_my = true;
		return -1;
	}
	cout<<str<<endl;
	stack<int> temp_stack;

	int i =0;
	
	int left,right;
	while(i < str.size())
	{
		if (str[i] >= '0' &&str[i] <= '9' )
		{
				temp_stack.push(str[i]-'0');
				i++;
				continue;
		}
		
		switch(str[i])
		{

			case '+':
				
				if (temp_stack.size() < 2)
				{
					error_my = true;
					return -1;
				}
				right =  temp_stack.top();
				temp_stack.pop();
				left =  temp_stack.top();
				temp_stack.pop();
				temp_stack.push(left+right);
			
				break;

			case '-':
				if (temp_stack.size() < 2)
				{
					error_my = true;
					return -1;
				}
				right =  temp_stack.top();
				temp_stack.pop();
				left =  temp_stack.top();
				temp_stack.pop();
				temp_stack.push(left-right);
				
				break;

			case '*':

				if (temp_stack.size() < 2)
				{
					error_my = true;
					return -1;
				}
				right =  temp_stack.top();
				temp_stack.pop();
				left =  temp_stack.top();
				temp_stack.pop();
				temp_stack.push(left*right);

				break;

			case '/':

				if (temp_stack.size() < 2)
				{
					error_my = true;
					return -1;
				}
				right =  temp_stack.top();
				temp_stack.pop();
				if (right == 0)//除数不为0
				{
					error_my = true;
					return -1;
				}
				left =  temp_stack.top();
				temp_stack.pop();
				temp_stack.push(left/right);
				
				break;
			
		}
		i++;
	}

	if (temp_stack.size() == 1)
	{
		return temp_stack.top();
	}
	else
	{
		error_my = true;
		return -1;
	}
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值