stack实现表达式计算(附源码)

例子主要实现带括号的+、-、*、/的运算,如“3+(5*5)”的表达式的数值运算。本例是在Dev C++11中编译通过。源码请点击如下链接:

点击打开链接

1.逻辑思路:
  1.遇到(,+、-、*、/符号是压入栈中;
  2.遇到),弹出栈中表达式进行计算,直到遇到(为止,并将计算总值压入栈中
  3.遇到数字,查看栈顶是否为*或/运算符,如果是弹出运算符和数字进行计算再将计算结果压入栈中

  4.其他字符跳过

2.实现算法逻辑
①首先定义如下类

class Calculator
{
	friend ostream& operator<<(ostream&, Calculator&);		//打印表达式和计算结果 
	
public:
	Calculator(const string& s):expression(s),cur_pos(0){}	//构造函数 
	
	void   reset(const string& s) { expression=s; }
	double calculate();										//计算结果 

private:
	inline void	    clear();		//清空 
	inline double   getNumber();	//从cur_pos位置获取expersion表达式中的数值 
	inline void	    next();			//移动cur_pos到下一个关键字符 
	inline CalcType unitType();		//获取cur_pos当前指向的字符类型 
	inline void 	calcAll();		 
	inline void     calcBracket();	//计算带左括号的运算块 
	inline double   calcTop();
	inline void     highOper();
			 
private:
	size_t			cur_pos;		//解析表达式的位置 
	string  		expression;		//存储表达式 
	typedef pair<CalcType, double> stack_type;	
	
	stack<stack_type> opers;		//栈 
	static map<CalcType, function<double (double, double)>> binops; //二目运算操作 
	static map<string, CalcType> symbol;	
	static string           numbers;
};
根据逻辑思路实现calculate
double Calculator::calculate()
{
	clear();
	do
	{
		CalcType type = unitType();	//获取当前指向的类型
		switch(type)
		{
			case Calc_Left: //"("压 
			case Calc_Add:
			case Calc_Minus:
			case Calc_Muti:
			case Calc_Divi:
				opers.push(stack_type(type, 0)); //遇到(,+、-、*、/符号是压入栈中;
				break;
			
			case Calc_Right:
				calcBracket();//遇到),弹出栈中表达式进行计算,直到遇到(为止,并将计算总值压入栈中
				break;
				
			case Calc_Number:		
				highOper();//遇到数字,查看栈顶是否为*或/运算符,如果是弹出运算符和数字进行计算再将计算结果压入栈中
				break;
		}
		next();	
	}while((cur_pos != string::npos) && (cur_pos < expression.length()));
	
	calcAll(); 
		
	if(1 != opers.size())
		throw logic_error("表达式不正确!");	
		
	stack_type result(opers.top());
	return result.second;
}
③关键实现
 1) 采用map记录+,-,*,/运算:
 1)采用map记录+,-,*,/运算:
 //定义类静态变量的二目运算map,通过function定义函数指针
map<CalcType, function<double (double, double)>> Calculator::binops = 
	{{Calc_Add,   std::plus<double>()},
	 {Calc_Minus, std::minus<double>()},
	 {Calc_Muti,  std::multiplies<double>()},
	 {Calc_Divi,  std::divides<double>()}}; 
	 
//当进行+运算式只需这样操作即可
 double result = binops[Calc_Add](2, 1);  //result值等于3
 ②) 采用map实现字符串关键字查找,并通过string.find_first_of()查找数字后通过stod转发为double
//定义不同字符串的具体意思
map<string, CalcType> Calculator::symbol = {{"(",Calc_Left},
						{")",Calc_Right},
						{"+",Calc_Add},
					    {"-",Calc_Minus},
					    {"*",Calc_Muti},
					    {"/",Calc_Divi}};

CalcType Calculator::unitType()
{	//numbers="0123456789",查询是否为数值
	if(cur_pos == expression.find_first_of(numbers, cur_pos))
		return Calc_Number;
	//通过map查询是关键字符的枚举类型
	auto iter = symbol.find(expression.substr(cur_pos, 1));
	if(iter == symbol.end())
		return Calc_Error;
	else
		return iter->second;

④运行效果

编写测试函数,打印输出如下所示

int main(int argc, char** argv) 
{
	Calculator exper("(21-1+10)*((1-2)-1/2)");
	cout<< exper << endl;
	
	exper.reset("12 + (4/2)");
	cout<< exper << endl;
	
	exper.reset("12 + (4/2) + (3 * 10)");
	cout<< exper << endl;
	
	exper.reset("13 + (23*10) - 3 +");
	cout<< exper << endl;
	
	exper.reset("13 + (23*10 - 3");
	cout<< exper << endl;
	
	exper.reset("13 + 23*10) - 3");
	cout<< exper << endl;
	return 0;
}

//打印结果
(21-1+10)*((1-2)-1/2) = -15
12 + (4/2) = 14
12 + (4/2) + (3 * 10) = 44
13 + (23*10) - 3 + -> 表达式不正确
13 + (23*10 - 3 -> 表达式不正确
13 + 23*10) - 3 -> 表达式不正确

--------------------------------
Process exited after 0.4188 seconds with return value 0
请按任意键继续. . .
实现源码: 点击打开链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值