c++ 中缀表达式转后缀表达式 计算器

calc_res里面使用空格分割是个很不好的情况..需要保证转换的后缀式+-/*操作符是连在一起的 每个数字都需要用空格分离 ... 

我懒的改了..这样导致代码逻辑有些乱 因为计算的后缀式res需要整理好才能计算正确  


//数据结构与算法分析 栈c++实现  
//缺点 需要一次性分配足够的栈空间 没有实现动态变长 
//优点 大部分操作的消耗都是常量级别的

template <class type>
class stack
{
public:
	stack(){}
	~stack() { destroy(); }

	void	create_stack(size_t max_element)
	{
		if (!m_stack_base_ptr)
		{
			m_stack_base_ptr = new type[max_element];
			m_max_element = max_element;
		}
	}

	void	push(type &t)
	{
		if(!is_full())
			m_stack_base_ptr[++m_top_index] = t;
	}
	type&	pop()
	{
		if(!is_empty())
			--m_top_index;
		return m_stack_base_ptr[m_top_index + 1];
	}
	type&		top()
	{
		return is_empty() ? m_stack_base_ptr[0] : m_stack_base_ptr[m_top_index];
	}

	bool	is_full()
	{
		return m_top_index >= m_max_element - 1;
	}
	bool	is_empty()
	{
		return m_top_index == -1;
	}
	type&	at(int idx)
	{
		return m_stack_base_ptr[idx];
	}
	void	clear()
	{
		m_top_index = -1;
	}
	void destroy()
	{
		if (m_stack_base_ptr)
			delete[]m_stack_base_ptr;
		m_stack_base_ptr = nullptr;
	}
	size_t size()
	{
		return m_top_index + 1;
	}
private:
	type*		m_stack_base_ptr = nullptr;
	int		m_top_index = -1;
	int		m_max_element = 0;
};

 
class input_argment
{
public:
	input_argment(){}
	input_argment(double number, bool is_operator = false, char op = '+')
	{
		m_number = number;
		m_is_operator = is_operator;
		m_operator = op;
	}
	double	m_number;
	bool	m_is_operator = false;
	char	m_operator;
};

bool	is_operator(char c, int &priority)
{
	bool is_operator = true;
	switch (c)
	{
	case '+':
	case '-':	break;
	case '*':	priority = 1;		break;
	case '/':	priority = 1;		break;
	case '(':	priority = 100;		break;
	case ')':	priority = 100;		break;
	default:
		is_operator = false;
		break;
	}
	return is_operator;
}

bool is_operator(char c)
{
	int p;
	return is_operator(c, p);
}

//只看逻辑的话请把对res字符串操作的部分都删了...我看着都恶心
std::string reverse_polish(std::string &s)
{
	stack<input_argment>  my_stack;
	my_stack.create_stack(100);
	std::string res;
	int idx = 0;
	char op;
	for (; idx < s.size(); ++idx)
	{
		bool is_operator_ = true;	
		int	 priority = 0;
		op = s.at(idx);

		//判断是不是操作符
		is_operator_ = is_operator(op, priority);
		res += s.at(idx);
		//不是操作符就跳过当前循环
		if (!is_operator_)
			continue;
		res.erase(--res.end());//删除输出的操作符 
		if (res.size()>0&&  res[res.size()-1]!=' ')
			res += ' ';
		//栈为空 或者当前的操作符比栈顶操作符的优先级要高或者为(就直接压栈,  )操作符的处理不需要压栈
		if (my_stack.is_empty() || (!my_stack.is_empty() && my_stack.top().m_number < priority &&op != ')') ||op=='(')
		{
			my_stack.push(input_argment(priority, true, op));
		}
		else 
		{	//出栈
			if (priority == 100) //遇到右括号了
			{
				//把(之前的操作符全部出栈
				while (!my_stack.is_empty()&& my_stack.top().m_operator!='(')
					res += my_stack.pop().m_operator;
				my_stack.pop();//(出栈
			}
			else  
			{
				//把所有优先级大于等于当前操作符的操作符全部出栈 直到遇到优先级更低的操作符或者(
				while (!my_stack.is_empty() && my_stack.top().m_number >= priority &&my_stack.top().m_number != 100)
					res += my_stack.pop().m_operator;
				my_stack.push(input_argment(priority, true, op));//当前操作符压栈
				
			}
			//有时候会出现 1 2 3 * - 这个情况...因为我下面的计算是用空格来分割的,为了方便计算就每次加入一个操作符的时候就看看有没有这样 
			if (res.size() > 3 && res[res.size() - 2] == ' '&&is_operator(res[res.size() - 1]) &&is_operator(res[res.size() - 3]))
				res.erase(----res.end());

			res += ' ';
		}
	}

	if (res[res.size() - 1] == ' ')
		res.erase(--res.end());
	else if(!is_operator(res[res.size()-1]))
		res += ' ';

	//将剩下的操作符出栈
	while (!my_stack.is_empty())
		res += my_stack.pop().m_operator;
	//去掉多余的空格 
	auto p = res.find("  ");
	while ( p!=std::string::npos )
	{
		res.erase(res.begin()+p);
		p = res.find("  ");

	}
	return res;
}

void	conver_notation_to_stack(std::string &s, stack<input_argment> &my_stack)
{
	int priority = 0;
	for (int i = s.size() - 1; i >= 0; --i)
	{
		if (is_operator(s[i], priority))
		{
			my_stack.push(input_argment(0, true, s[i]));
		}
		else
		{
			std::string res;
			auto start = s.rfind(' ', i - 1);	
			if (start == std::string::npos)
				res.assign(s.begin(), s.begin() + i+1);
			else 
				res.assign(s.begin()+start, s.begin() + i+1);
			my_stack.push(input_argment(atof(res.data())));		
			if (start == 0)
				return;
			else
				i = s.rfind(' ',start-1) == std::string::npos ? start+1:start; //判断是不是只剩下一个数字了
		}
	}
}

double calc_res(stack<input_argment> &my_stack)
{
	double v1, v2;
	for (int i = my_stack.size() - 1; i >= 0; --i)
	{
		if (my_stack.at(i).m_is_operator)
		{	 
			v2 = my_stack.pop().m_number;
			v1 = my_stack.pop().m_number;
			switch (my_stack.at(i).m_operator)
			{
			case '+':	my_stack.push(input_argment(v1 + v2));	break;
			case '-':	my_stack.push(input_argment(v1 - v2));	break;
			case '*':	my_stack.push(input_argment(v1 * v2));	break;
			case '/':	my_stack.push(input_argment(v1 / v2));	break;
			}
		}
		else
		{
			my_stack.push(my_stack.at(i));
		 
		}
	}
	return my_stack.top().m_number;
}
int main()
{
 
	std::string s,res;
	s = "1+2+(1+2-3.5+(10*10-(10-20+((30-10)-(1+1.0)+1)-2)+(2-2)+3)-4)+100";
	stack<input_argment> my_stack;
	my_stack.create_stack(100);
	//转化成计算式
	res = reverse_polish(s);
	//输出转化的计算公式
	cout << res.data() << endl;
	//将转化的计算式字符串转换为数据
	conver_notation_to_stack(res, my_stack);
 
	cout << calc_res(my_stack) << endl;
    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值