C++用栈求解简单的算术表达式

问题描述

这里限定的简单算术表达式求值问题是,用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果。

设计运算算法

  1. 中缀表达式
    在算术表达式中,运算符位于两个操作数中间的表达式称为中缀表达式。
    例:1 + 2 * 3
    中缀表达式运算一般遵循“先乘除,后加减,从左至右,先括号内,再括号外”的规则。一次中缀表达式不仅要依赖运算符优先级,还要处理括号。
  2. 后缀表达式
    后缀表达式就是运算符在操作数的后面
    例:1 + 2 * 3 的后缀表达式为 1 2 3 * +
    对于后缀表达式,它已经考虑了运算符的优先级,没有括号,只有操作数和运算符。其求值过程是,从左到右读入后缀表达式,若读入的是操作数,将它入数值栈,若读入的是一个运算符,从数值栈中连续出栈两个元素(两个操作数),并将结果入数值栈。对整个后缀表达式读入结束后,栈顶元素就是计算结果。

代码实现

1.定义一个Calculator类

#define MAX  100
#include<stack>
#include<cstring>
#include<iostream> 
using namespace std;

class Calculator{
	public:
		void convert();//将中缀表达式转化为后缀表达式
		void calculate();//计算后缀表达式
		int priority(const char c);//得到运算符优先级
		void input();//输入算术表达式
	private:
		char* exp;//存放中缀表达式
		char postExp[MAX];//存放后缀表达式
		int len,pnum;
};

2.得到运算符优先级

int Calculator::priority(const char c){
	switch(c){
		case '+':
		case '-':
			return 1;
			break;
		case '*':
		case '/':
			return 2;
			break;
	}
}

3.输入算术表达式

void Calculator::input(){
	exp = new char[MAX];
	cout << "请输入算式:" ;
	string str; 
	cin >> str;
	strcpy(exp,str.c_str());
	len = str.length(); //len表示中缀表达式长度
}

4.将中缀表达式转换成后缀表达式

void Calculator::convert(){
	stack<char> op;
	int i=0,j=0;//i,j分别作为exp和postExp的下标
	for(i=0;i<len;i++){
		if(exp[i]>='0'&&exp[i]<='9')//如果是数字,直接放入postExp
		{
			postExp[j++] = exp[i];
			if(exp[i+1]<'0'||exp[i+1]>'9'){
				postExp[j++] = '#';//用‘#’标识有个数值串结束
			}
		}else if(exp[i]=='+'||exp[i]=='-'||exp[i]=='*'||exp[i]=='/'){
			while(true){
				if(op.empty()||op.top()=='('){//当栈为空,或栈顶为(
					op.push(exp[i]);
					break;
				}else if(priority(exp[i])>priority(op.top())){//当当前运算符优先级大于栈顶优先级
					op.push(exp[i]);
					break;
				}else{
					postExp[j++]=op.top();//小于等于
					op.pop();
				}
			}
		}else{
			if(exp[i]=='('){//直接压入
				op.push(exp[i]);
			}else{//当当前运算符为)时
				while(op.top()!='('){
					postExp[j++] = op.top();
					op.pop();
				}
				op.pop();//把(退栈
			}
		}
	} 
	
	while(!op.empty()){//将栈中所有运算符退栈并放入postExp中
		postExp[j++] = op.top();
		op.pop();
	}
	
	pnum = j;//保存在postExp中字符的个数
	
}

5.计算后缀表达式

void Calculator::calculate(){
	stack<double> st;
	double a,b,c;
	int i=0;
	char ch;
	while(i<pnum){
		ch=postExp[i];
		switch(ch){
			case '+':
				a=st.top();
				st.pop();
				b=st.top();
				st.pop();
				st.push(b+a);
				break;
			case '-':
				a=st.top();
				st.pop();
				b=st.top();
				st.pop();
				st.push(b-a);
				break;
			case '*':
				a=st.top();
				st.pop();
				b=st.top();
				st.pop();
				st.push(b*a);
				break;
			case '/':
				a=st.top();
				st.pop();
				b=st.top();
				st.pop();
				if(a!=0){
					st.push(b/a);
				}else{
					cout << "除数不能为0" << endl;
					exit(0);
				} 
				break;
			default://处理数字字符
				c=0;
				while(ch>='0'&&ch<='9'){
					c = 10*c+(ch-'0');//将连续的字符转换成数值存放到c
					i++;
					ch=postExp[i];
				}
				st.push(c);//将数组c进栈
				break;
		}
		i++;
	}
	cout << "计算结果为:" << st.top();//栈顶元素即为求值结果
}

6.主函数

int main(){
	Calculator c;
	c.input();
	c.convert();
	c.calculate();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值