表达式求值(递归和栈)

问题:输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。

输入格式
  输入一行,包含一个表达式。
输出格式
  输出这个表达式的值。
样例输入
1-2+3*(4-5)
样例输出
-4
数据规模和约定
  表达式长度不超过100,表达式运算合法且运算过程都在int内进行。

1.用递归的方式:


#include<iostream>
#include<cctype>
using namespace std; 

int expression();//表达式 
int term();//项 
int factor();//因子 

int main()
{
	cout << expression() <<endl;
	return 0;
}

int expression()
{
	int result = term();
	char c = cin.peek();
	while(c == '+' || c == '-')
	{
		cin.get();
		if(c == '+')
		result += term();
		else if(c == '-')
		result -= term();
		c = cin.peek();
	}
	return result;
}

int term()
{
	int result = factor();
	char c = cin.peek();
	while(c == '*' || c == '/')
	{
		cin.get();
		if(c == '*')
		result *= factor();
		if(c == '/')
		result /= factor();
		c = cin.peek();
	}
	return result;
}

int factor()
{
	int result = 0;
	char c = cin.peek();
	if(c == '(')
	{
		cin.get();
		result += expression();
		cin.get();
	}
	else while(isdigit(c))
	{
		cin.get();
		result = result * 10 + c - '0';
		c = cin.peek();
	}
	
	return result;
}


2.用栈的方式

(1):首先设置操作数栈为空栈,设置运算符栈以‘#’为栈底元素(其优先级最低)。

(2):通过为栈内栈外运算符设置值而比较其优先级

(3):依次去找到表达式中的所有运算符和操作数,对于操作数直接入栈,运算符则和运算符栈的栈顶运算进行比较优先级,若栈内优先级大,则进行相应操作并操作数和栈内运算符都出栈,若优先级相等只需栈内运算符出栈继续查找下一个运算符即可,若栈内优先级低则栈外运算符入栈。依次循环知道分析完表达式中的所有运算符和操作数可。

(4):最后在操作数栈中将只会剩下唯一的一个元素,而该元素也将就会是所求表达式的值。



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

/*判断符号间的优先关系函数
*1表示>,0表示=,-1表示<
*c1栈内的算符,c2栈外的算符
*/
int Judge(char c1,char c2)
{
	int a1,a2;
	if('+'==c1||'-'==c1) a1 = 3;
	if('*'==c1||'/'==c1)a1 = 5;
	if('('==c1) a1 = 1;
	if(')'==c1) a1 = 7;
	if('#'==c1) a1 = 0;

	if('+'==c2||'-'==c2)a2 = 2;
	if('*'==c2||'/'==c2)a2 = 4;
	if('('==c2) a2 = 6;
	if(')'==c2) a2 = 1;
	if('#'==c2) a2 = 0;
	if(a1>a2) return 1;
	if(a1==a2) return 0;  //只有(),#才可能相等 
	if(a1<a2) return -1;
}
//符号运算函数
double run(char c ,double d1,double d2)
{
	switch (c)
	{
	case '+':
		return d1+d2;
		break;
	case '-':
		return d1-d2;
		break;
	case'*' :
		return d1*d2;
		break;
	case '/':
		return d1/d2;
		break;
	default:
		return 0.0;
		break;
	}
}
int main()
{
	char op[9] = "+-*/()#";
	string str ;
	cin>>str;
	//给表达式字符串str添加'#'结束标识符
	str.append(1,'#'); //string &append(int n,char c):在当前字符串结尾添加n个字符c
	stack<char> OPTR;//运算符栈
	stack<double> OPND;//操作数栈
	int a = -1;
	//先将#符号入栈
	OPTR.push('#');
	while(true)
	{
	 int b = a+1;
	 a = str.find_first_of(op,a+1);//s.find_first_of(letter, pos)),意思是在s中寻找首个letter中有的字符,从pos开始搜索
	 if(a==string::npos) break; //npos 是一个常数,用来表示不存在的位置
	 if(a!=b)
	 {
	 string ss(str,b,a-b);
	 double d=atof(ss.c_str());//atof()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结                                   //束时('\0')才结束转换,并将结果返回;将字串转换成浮点型数
	 //数据先入栈
	 OPND.push(d);
	 }
	 //运算符优先级比较
	 int ju = Judge(OPTR.top(),str[a]);
	 if(-1==ju)//栈外优先级大直接入栈
	 {
	     OPTR.push(str[a]);
	 }
	 if(0==ju)//后括号遇到前括号直接出栈 
	 {
		 OPTR.pop();
	 }
	 if(1==ju)//栈内优先级大,出栈进行运算
	 {
		 double d1 = OPND.top();
		 OPND.pop();
		 double d2 = OPND.top();
		 OPND.pop();
		 d1 = run(OPTR.top(),d2,d1);
		 //运算结果入栈
		 OPND.push(d1);
		 OPTR.pop();
		 a--;  //表达式的下标 
	 }
	}
	//删除表达式最后的'#'结束标识符
	str.erase(str.length()-1,1);
	cout<<OPND.top()<<endl;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值