栈实现的表达式求值

主要是中缀表达式求值。

1.字符转数字

double Translation(int& pos)   //将字符转换为数字
{
	double integer = 0.0;    // 整数部分
	//double remainder = 0.0;  //(double类型情况时)余数部分
	while (s[pos] >= '0' && s[pos] <= '9')
	{
		integer *= 10;
		integer += (s[pos] - '0');  //这一句是重点,将字符转换为数字即:减去‘0’
		pos++;
	}
	/*if (s[pos] == '.')
	{
		pos++;
		int c = 1;
		while (s[pos] >= '0' && s[pos] <= '9')
		{
			double t = s[pos] - '0';
			t *= pow(0.1, c);
			c++;
			remainder += t;
			pos++;
		}
	}*/
	return integer;
}

字符转数字这部分的重点就在于用字符减去'0'可得其数值,前一位乘十,加上这一位。不断继续,直到输入的不是数字为止。

 

2.返回运算符级别

int GetLevel(char ch)
{
	switch (ch)
	{
	case '+':
	case '-':
		return 1;
	case '*':
	case '/':
		return 2;
	case '(':
		return 0;
	case '#':
		return -1;
	};
}

3.对两个数进行运算

double Operate(double a1, char op, double a2)
{
	switch (op)
	{
	case '+':
		return a1 + a2;
	case '-':
		return a1 - a2;
	case '*':
		return a1 * a2;
	case '/':
		return a1 / a2;
	};
}

4.主要运算函数(用栈)

double Compute()
{
	stack<char> optr;    // 操作符栈
	stack<int> opnd;  // 操作数栈
	optr.push('#');      //置于符栈顶
	int len = strlen(s);
	bool is_minus = true;  // 判断'-'是减号还是负号, true表示负号
	for (g_pos = 0; g_pos < len;)
	{
		//1. 负号
		if (s[g_pos] == '-' && is_minus)  // 是负号
		{
			opnd.push(0);
			optr.push('-');
			g_pos++;
		}
		//2. 是右括号 )
		else if (s[g_pos] == ')')
		{
			is_minus = false;  //括号后不会出现负号,只可能是减号
			g_pos++;
			while (optr.top() != '(')
			{
				double a2 = opnd.top();
				opnd.pop();
				double a1 = opnd.top();
				opnd.pop();
				char op = optr.top();
				optr.pop();
				double result = Operate(a1, op, a2);
				opnd.push(result);
			}
			optr.pop();  // 删除'('
		}
		//3. 数字
		else if (s[g_pos] >= '0' && s[g_pos] <= '9')
		{
			is_minus = false;   //数字后不会出现负号,只可能是减号
			opnd.push(Translation(g_pos));
		}
		//4. ( 左括号
		else if (s[g_pos] == '(')
		{
			is_minus = true;  //左括号后不会出现减号,只可能是负号
			optr.push(s[g_pos]);
			g_pos++;
		}
		//5. + - * / 四种
		else
		{
			while (GetLevel(s[g_pos]) <= GetLevel(optr.top()))    //当前优先级小于栈尾优先级
			{
				double a2 = opnd.top();
				opnd.pop();
				double a1 = opnd.top();
				opnd.pop();
				char op = optr.top();
				optr.pop();
				double result = Operate(a1, op, a2);
				opnd.push(result);
			}
			optr.push(s[g_pos]);
			g_pos++;
		}
	}

(虽然学校oj上的题目降低了难度,参数为正整数,既不用考虑小数点又不用考虑'-'是负号还是减号,但是这里都体现出来了。)

除去这些,总共需要考虑四种情况。

(1)左括号:

遇到左括号,直接入运算符栈。

(2)右括号:

注意!)当运算符栈顶元素不为左括号时:进行运算直至运算符栈顶元为左括号为止。

运算过程:取数字栈栈顶并赋值-弹栈-取数字栈栈顶并赋值-弹栈-取运算符栈顶-弹栈-运算-将运算结果入栈(循环此过程直至运算符栈顶元素为左括号)

(3)数字:

遇到数字,直接入数字栈。

(4)+、-、*、/   四种运算符:

(注意!)当当前运算符的优先级小于或等于栈顶运算符优先级时【也就是三种情况:①当前为+、-,栈顶为*、/②当前为+、-栈顶也为+、-③当前为*、/栈顶也为*、/。即先运算优先级高的或者优先级相同时在前面的(从左到右计算)】,先不入栈!先进行运算【(与以上运算过程相同)】。直至当前运算符优先级大于栈顶运算符(*、/在最后,不用先运算)。再将当前运算符入栈。

 

看着别人的代码总结了一下注意点,重点还是要自己敲一遍,把各种逻辑理清,到时候暴露出来的问题才是真正的大问题,到时候再来解决。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值