关于使用栈将一般运算式翻译为后缀表达式并实现三级运算的方法及实例(cpp版)

#include <iostream>
#include <stack>
#include <vector>
#include <string>
#define uint unsigned int
using namespace std;

//判断该字符是否为运算符 是则返回真 否则返回假
inline bool isOperator(char opr)
{
	switch(opr)
	{
	case '*':
		return true;
	case '/':
		return true;
	case '+':
		return true;
	case '-':
		return true;
	default:
		return false;
	}
}
//Sufexp(string& ,vector<string>& );	//翻译为后缀表达式	suffic expression
//第一个参数为输入表达式字符串引用,第二个参数为放置后缀表达式的向量引用
//从首至尾分别为数字和运算符 没有检查功能
void Sufexp(string &str,vector<string> &str_vec)		
{
	stack<string,vector<string> > sta;
	
	string::size_type longth = str.size();
	int last_flag = -1;
	for(int i = 0;i < longth;i++)
	{
		//如果第i个字符串是运算符 则进入大判断
		if(str.at(i) == '*' || str.at(i) == '/' || str.at(i) == '+' || str.at(i) == '-'  || str.at(i) == '(' || str.at(i) == ')'|| str.at(i) == '=')
		{
			//如果是左括号则需要改变last_flag
			if(str.at(i) == '(' )
			{
				last_flag = i;
			}
			//如果右括号右边紧跟运算符则需要改变last_flag
			else if(str.at(i-1) == ')' && isOperator(str.at(i)))
			{
				last_flag = i;
			}
			//遇到右括号紧跟等号也不需要分割	遇到右括号紧跟运算符不需要分割
			else if(!((str.at(i-1) == ')' && str.at(i) == '=') || (str.at(i-1) == ')' && isOperator(str.at(i)))))
			{
				str_vec.push_back(str.substr(last_flag + 1,i - last_flag -1));
				last_flag = i;
			}
			
			//如果栈为空 直接将符号入栈
			if(sta.size()==0)
			{
				char ch[1] = {str.at(i)};
				string str_1(ch,1);
				sta.push(str_1);
			}
			
			//如果栈不为空
			//如果检测到 '(' 直接入栈
			else if(str.at(i) == '(')
			{
				char ch[] = {str.at(i)};
				string str_1(ch,1);
				sta.push(str_1);
			}
			//如果检测到的是高级运算符先将之前的高级弹出的字符串项链在将新运算符入栈		
			else if(str.at(i) == '*' || str.at(i) == '/')
			{
				if(sta.top() == "*" || sta.top() == "/")
				{
					str_vec.push_back(sta.top());
					sta.pop();
				}
				char ch[] = {str.at(i)};
				string str_1(ch,1);
				sta.push(str_1);
			}
			//如果检测到的是低级运算符需要将高级运算符弹出 同级运算符也需要先弹出再入栈  低级运算符再入栈
			else if(str.at(i) == '+' || str.at(i) == '-')
			{
				bool once = false ;
				//判断之前的运算符是否为高级运算符	如果是
				while((sta.top() == "*" || sta.top() == "/") && sta.size() != 0 )
				{
					
					//先将 高级 运算符弹出放入字符串向量

					str_vec.push_back(sta.top());
					sta.pop();

					once = true;
					if(sta.size() == 0)	break;
					
				}
				
				//如果曾经把高级运算符弹出去过 就不用将现在栈顶运算符弹出了 否则就弹出一次
				if(once == false && sta.size() != 0)
				{
					if(sta.top() == "+" || sta.top() == "-") 
					{
						str_vec.push_back(sta.top());
						sta.pop();
						//if(sta.size() == 0)	break;
					}
				}
				//再将低级运算符压栈
				char ch[] = {str.at(i)};
				string str_1(ch,1);
				sta.push(str_1);
			}
			//如果检测到 ')' 将栈中的符号逐个弹出 直至遇到 '('
			else if(str.at(i) == ')')
			{
				while(sta.top() != "(")
				{
					str_vec.push_back(sta.top());
					sta.pop();
					if(sta.size() == 0)	break;
				}
				//将'('直接弹出而不放入字符串向量
				if(sta.top() == "(")
				{
					//cout << sta.top() << endl;
					sta.pop();
				}
				
			}
			//如果检测到是 '=' 将栈中数据全部弹出至字符串向量 最后将'='存入字符串向量
			//输出后缀表达式
			else if(str.at(i) == '=')
			{	
				
				//将栈中数据全部弹出至字符串向量
				while(sta.size() != 0)
				{
					str_vec.push_back(sta.top());
					sta.pop();
				}

				//最后将'='存入字符串向量
				str_vec.push_back("=");

				vector<string>::iterator begin = str_vec.begin();
				vector<string>::iterator end = str_vec.end();

				//如果向量中有空字符串 可以去除有括号与运算符紧挨在一起由substr引起的空字符串
				/*for( ;begin != str_vec.end(); begin++)
				{	
					if((*begin) == "")
					{	
						str_vec.erase(begin);
						begin--;
					}
				}*/
				
				//输出后缀表达式
				/*cout << "后缀表达式:" << endl;
				begin = str_vec.begin();
				end = str_vec.end();
				for( ;begin != end;begin++)
				{
					//显示第n个元素的下标与对应元素内容
					cout << distance(str_vec.begin(),begin) << "\t" << *begin << endl;
				}
				cout << endl;*/
			}		
		}
	}
}

//向量内的元素遍历显示
void showVecFac(vector<string> str_vec)
{
	vector<string>::iterator begin = str_vec.begin();
	vector<string>::iterator end = str_vec.end();
	for(;begin != end;begin++)
	{
		cout << *begin << "\t" ;
	}
	cout << endl;
}


//计算后缀表达式
void calSuf(vector<string> &str_vec)
{
	//向量遍历
	for(vector<string>::iterator begin = str_vec.begin();begin != str_vec.end();begin++)
	{
		vector<string>::iterator temp_begin = begin;	//中间迭代器变量
		const char *first_char;
		const char *second_char;
		string result;
		char temp_str_result[50];
		double temp_double;

		const char *answer;
		bool point = false;
		uint last_num = 0;
		uint i = 0;


		//将字符串转换为char形
		const char *temp_char = (*begin).c_str();

		//处理基本运算
		switch(*temp_char)
		{
		case '*':
			//提取运算符前边两个数据 用于计算
			--temp_begin;
			second_char = (*temp_begin).c_str();
			--temp_begin;
			first_char = (*temp_begin).c_str();
			

			//运算
			temp_double = atof(first_char) * atof(second_char);	

			/*cout << "first_char :  " << first_char << endl;	
			cout << "second_char :  " << second_char << endl;  
			cout << temp_double << endl;*/

			//将数据替换到begin
			sprintf(temp_str_result, "%lf", temp_double);	
			result = temp_str_result;
			(*begin) = result;


			//清除空余数据	
			str_vec.erase(temp_begin);
			begin--;
			str_vec.erase(temp_begin);
			begin--;
			break;
		case '/':
			//提取运算符前边两个数据 用于计算
			--temp_begin;
			second_char = (*temp_begin).c_str();
			--temp_begin;
			first_char = (*temp_begin).c_str();
			

			//运算
			temp_double = atof(first_char) / atof(second_char);	

			//将数据替换到begin
			sprintf(temp_str_result, "%lf", temp_double);	
			result = temp_str_result;
			(*begin) = result;


			//清除空余数据	
			str_vec.erase(temp_begin);
			begin--;
			str_vec.erase(temp_begin);
			begin--;
			break;

		case '+':
			//提取运算符前边两个数据 用于计算
			--temp_begin;
			second_char = (*temp_begin).c_str();
			--temp_begin;
			first_char = (*temp_begin).c_str();
			

			//运算
			temp_double = atof(first_char) + atof(second_char);

			//将数据替换到begin
			sprintf(temp_str_result, "%lf", temp_double);	
			result = temp_str_result;
			(*begin) = result;


			//清除空余数据	
			str_vec.erase(temp_begin);
			begin--;
			str_vec.erase(temp_begin);
			begin--;
			break;
		case '-':
			//提取运算符前边两个数据 用于计算
			--temp_begin;
			second_char = (*temp_begin).c_str();
			--temp_begin;
			first_char = (*temp_begin).c_str();
			

			//运算
			temp_double = atof(first_char) - atof(second_char);	

			//将数据替换到begin
			sprintf(temp_str_result, "%lf", temp_double);	
			result = temp_str_result;
			(*begin) = result;


			//清除空余数据	
			str_vec.erase(temp_begin);
			begin--;
			str_vec.erase(temp_begin);
			begin--;
			break;
	
		case '=':
			//判断结构是否为小数
			//判断是否为整数
			answer = (*(begin-1)).c_str();
			point = false;
			last_num = 0;
			i = 0;
			while(answer[i])
			{
				
				if(answer[i] == '.')
				{
					point = true;
				}
				if(point == true && answer[i] != '0')
				{
					last_num = i;
				}
				
				i++;
			}
			//判断最后一位是不是小数点	区别对待
			if(answer[last_num] == '.')
			{
				--last_num;
			}
			*(begin-1) = (*(begin-1)).substr(0,last_num + 1);
			break;
		default:
			break;
		}
	}
	//清除末尾的等号 只存储最终结果
	str_vec.erase(str_vec.end()-1);
}

//用于输出结果
void showAnswer(vector<string> & str_vec)
{
	cout << "the result is :  " << *(str_vec.begin()) << endl;
}


int main()
{
	string str;
	cin >> str;
	//末尾自动添加 等号
	str += "=";
	//用于存放后缀表达式
	vector<string> str_vec;	
	//通过函数 得到后缀表达式的向量 存放在str_vec向量中
	//第一个参数为输入表达式字符串引用,第二个参数为放置后缀表达式的向量引用,从首至尾分别为数字和运算符 
	//没有检查功能
	Sufexp(str,str_vec);

	//计算后缀表达式 并存放在str_vec向量中
	calSuf(str_vec);
	
	showAnswer(str_vec);
	
	//直接输入运算符可以借用上一次结果继续运算 
	while(1)
	{
		cin >> str;
		str += "=";
		//如果紧跟上次的结果的是运算符 就接着运算 否则展开新运算与上次结果无关
		if(str.at(0) == '*' || str.at(0) == '/' || str.at(0) == '+' || str.at(0) == '-')
		{
			str = (*(str_vec.end()-1)) + str;
		}

		str_vec.clear();
		Sufexp(str,str_vec);
		//计算后缀表达式 并存放在str_vec向量中
		calSuf(str_vec);

		showAnswer(str_vec);
	}

	
	
	return 0;
}
posted @ 2017-08-12 09:23  春雨冰河  阅读(269)  评论(0编辑  收藏  举报