中缀表达式转后缀表达式求值

刚开始想一鼓作气把整个过程全部实现,但白费了那几个小时,调试了半天也没做出来,后来我是通过先实现中缀表达式转化为后缀表达式,然后实现后缀表达式的求值,然后将两块代码进行合成,刚才同学还笑着说:模块化编程。。。

直接在代码中解释。

中缀表达式转后缀表达式:

# include <iostream>
# include <string>
# include <sstream>
# include <cctype>                //程序中需使用isdigit()函数,目的在于判别字符是否为数字,将符号和数字区别开来
using namespace std;
struct sign                      //建立存储符号的结构体
{
	char sign;
	int level;
	struct sign *next_1;
};
class linkstack
{
private:
	struct sign *top;
public:
	linkstack() { top = NULL; }   //无参构造函数,top头指针初始化为零
	char push_out();              //将栈顶元素出栈
	void push_in(char new_sign);  //给栈中添加新元素
	char print_top();             //返回栈顶元素中的符号内容
	int print_level();            //返回栈顶元素符号的优先级
};
int compare(char compared_sign)   //给每个符号赋予优先级
{
	int level;
	switch (compared_sign) {
	case '(':
		level = -10; break;
	case ')':
		level = -10; break;
	case '+':
		level = 0; break;
	case '-':
		level = 0; break;
	case '*':
		level = 1; break;
	default:                     //default要加上
		level = 1; break;
	}
	return level;
}
char linkstack::print_top()
{
	char result;
	result = top->sign;
	return result;
}
int linkstack ::print_level()
{
	return top->level;
}
char linkstack::push_out()               //删除栈顶元素
{
	char char_result;
	struct sign *p;
	char_result = top->sign;
	p = top;
	top = top->next_1;
	delete p;
	return char_result;                  //删除后需要给sting对象b中追加,所以需要返回
}
void linkstack::push_in(char new_sign)
{
	struct sign *s;
	s = new struct sign;                 //添加栈顶元素
	s->sign = new_sign;
	s->level = compare(new_sign);
	s->next_1 = top;
	top = s;
}
int main()
{
	int count = 0; double m;           //count用来记录符号栈中的个数,用top!=NULL也可以
	string a,b;
	cin >> a;                          //string对象a是转化前的,b是转换后的
	linkstack one;
	for (auto c = a.begin(); c != a.end(); c++) {          //从a的第一个元素开始扫描
		if (isdigit(*c)) {
			b.push_back(*c);  continue;            //如果是数字isdigit(*c)为真,就给b中追加,进行下一个循环
		}
		else {
			if (*c != ')'&&count==0) {            //如果栈为空,直接加入栈顶元素
				one.push_in(*c);
				count++;                         //记录栈元素的个数
				continue;                        //进行下一个循环
			}
			if (*c==')') {                      //进行括号中的运算
				while (one.print_top()!= '(') {             //一直循环到栈顶元素不等于‘(’
					b.push_back(one.print_top());           //将目前栈顶元素追加给b
					one.push_out(); count--;                //追加完后,删除栈顶元素,个数减一
				}
				one.push_out(); count--;                   //最后记得还要把左括号删除,以避免对下一个运算影响
				continue;
			}
			if (compare(*c) <= one.print_level()) {     //如果当前符号优先级小于栈顶元素的优先级(即上一个运算符)
				b.push_back(one.print_top());           //将栈顶运算符元素追加给b
				one.push_out();                         //紧跟着删除刚才的栈顶元素
				one.push_in(*c);                        //将当前的运算符号压入栈
				continue;                               //进行下一个循环
			}
			if (compare(*c)>one.print_level()) {        //如果当前运算符优先级大于栈顶元素(即前一个运算符)
				one.push_in(*c); count++;               //直接压入栈,个数加一,并进行下一个循环
				continue;
			}
		}
	}
	if (count) {                                        //如果栈不空则还剩余一个符号没有追加给b
		b.push_back(one.print_top());                   //追加栈中剩余的符号
		one.push_out();
	}
	cout << b << endl;
	system("pause");
	return 0;
}

后缀表达式求值:

# include <iostream>
# include <string>
# include <sstream>                    //下边程序中从string类型到double中要用到,具体的用法在以前的博客中我有详细提及
using namespace std;
struct operate         
{
	double member;         
	struct operate *next;
};
class new_linkstack
{
public:
	new_linkstack() { top = NULL; }      //初始化,top为NULL;
	void push_in(double x);              //将数字压入栈
	double push_out();                   //删除栈顶元素
	void print_result();                 //打印运算完后的结果,也就是最后的栈顶元素
private:
	struct operate *top;
};
void new_linkstack::push_in(double in_number)
{
	struct operate *s;
	s = new operate;
	s->member = in_number;
	s->next = top;
	top = s;
}
double new_linkstack::push_out()
{
	struct operate *p;
	if (top == NULL)throw"下溢";
	double out_member;
	out_member = top->member; p = top;
	top = top->next;
	delete p;
	return out_member;
}
void new_linkstack::print_result()
{
	cout << top->member << endl;
}
int main()
{
	double x, y, result,b;
	string new_a;
	cin >> new_a;
	new_linkstack one;
	for (auto c = new_a.begin(); c != new_a.end(); c++) {   //从头到尾扫描new_a中的元素
		if (isdigit(*c)) {              //如果当前元素为数字,直接入栈
			stringstream sstream;
			sstream << *c;
			sstream >> b;              //string类型到double类型的转换
			one.push_in(b);
			sstream.clear();           //将stringstream流清空
		}
		else {                         //如果当前元素为运算符
			x = one.push_out();        //将前两个栈顶的元素取出 
			y = one.push_out(); 
			switch (*c)                //new_a中的运算符不能直接用来做运算
			{
			case '+':
				result = x + y; one.push_in(result); continue;//运算完后,将当前运算结果压入栈,进行下一个循环
			case '-':
				result = y - x; one.push_in(result); continue;
			case '*':
				result = x * y; one.push_in(result); continue;
			case '/':
				result = y / x; one.push_in(result); continue;
			}
		}
	}
	one.print_result();               //打印最终结果
	system("pause");
	return 0;
}

这样就将一个大的问题分成了两个小的问题,下边的代码是我合成之后的:

# include <iostream>
# include <string>
# include <cctype>
# include <sstream>
using namespace std;
struct sign
{
	char sign;
	int level;
	struct sign *next_1;
};
struct operate
{
	double member;
	struct operate *next;
};
class new_linkstack
{
public:
	new_linkstack() { top = NULL; }
	void push_in(double x);
	double push_out();
	void print_result();
private:
	struct operate *top;
};
class linkstack
{
private:
	struct sign *top;
public:
	linkstack() { top = NULL; }
	char push_out();
	void push_in(char new_sign);
	char print_top();
	int print_level();
};
int compare(char compared_sign)
{
	int level;
	switch (compared_sign) {
	case '(':
		level = -10; break;
	case ')':
		level = -10; break;
	case '+':
		level = 0; break;
	case '-':
		level = 0; break;
	case '*':
		level = 1; break;
	default:                         
		level = 1; break;
	}
	return level;
}
char linkstack::print_top()
{
	char result;
	result = top->sign;
	return result;
}
int linkstack::print_level()
{
	return top->level;
}
char linkstack::push_out()
{
	char char_result;
	struct sign *p;
	char_result = top->sign;
	p = top;
	top = top->next_1;
	delete p;
	return char_result;
}
void linkstack::push_in(char new_sign)
{
	struct sign *s;
	s = new struct sign;
	s->sign = new_sign;
	s->level = compare(new_sign);
	s->next_1 = top;
	top = s;
}
void new_linkstack::push_in(double in_number)
{
	struct operate *s;
	s = new operate;
	s->member = in_number;
	s->next = top;
	top = s;
}
double new_linkstack::push_out()
{
	struct operate *p;
	if (top == NULL)throw"下溢";
	double out_member;
	out_member = top->member; p = top;
	top = top->next;
	delete p;
	return out_member;
}
void new_linkstack::print_result()
{
	cout << top->member << endl;
}
int main()
{
	int count = 0; double m;
	string a, b;
	cin >> a;
	linkstack one;
	for (auto c = a.begin(); c != a.end(); c++) {
		if (isdigit(*c)) {
			b.push_back(*c);  continue;
		}
		else {
			if (*c != ')'&&count == 0) {
				one.push_in(*c);
				count++;
				continue;
			}
			if (*c == ')') {
				while (one.print_top() != '(') {
					b.push_back(one.print_top());
					one.push_out(); count--;
				}
				one.push_out(); count--;
				continue;
			}
			if (compare(*c) <= one.print_level()) {
				b.push_back(one.print_top());
				one.push_out();
				one.push_in(*c);
				continue;
			}
			if (compare(*c) > one.print_level()) {
				one.push_in(*c); count++;
				continue;
			}
		}
	}
	if (count) {
		b.push_back(one.print_top());
		one.push_out();
	}
	double x, y, result, new_b;
	string new_a(b);
	new_linkstack two;
	for (auto c = new_a.begin(); c != new_a.end(); c++) {
		if (isdigit(*c)) {
			stringstream sstream;
			sstream << *c;
			sstream >> new_b;
			two.push_in(new_b);
			sstream.clear();
		}
		else {
			x = two.push_out();
			y = two.push_out();
			switch (*c)
			{
			case '+':
				result = x + y; two.push_in(result); continue;
			case '-':
				result = y - x; two.push_in(result); continue;
			case '*':
				result = x * y; two.push_in(result); continue;
			case '/':
				result = y / x; two.push_in(result); continue;
			}
		}
	}
	two.print_result();
	system("pause");
	return 0;
}

这也算是个人狭义上的第一次模块化的编程吧。。。。。。

发布了37 篇原创文章 · 获赞 12 · 访问量 9277

猜你喜欢

转载自blog.csdn.net/weixin_43265881/article/details/88849201