C++实现简易计算器

代码

具体讲解见代码注释

#include <bits/stdc++.h>
using namespace std;

set<char> operator_set;//运算符集合(括号也算在里面)
set<string> operator_str_set;//存的是字符串,方便inTOPost函数
vector<string> inOrder,postOrder;//中序表达式,以及后序表达式
map<string,int> prio;//各运算符优先级

/*
  一些初始化工作
 */
void init(){
//	operator_set.insert('+');
//	operator_set.insert('-');
//	operator_set.insert('*');
//	operator_set.insert('/');
//	operator_set.insert('%');
//	operator_set.insert('(');
//	operator_set.insert(')');
//	operator_str_set.insert("+");
//	operator_str_set.insert("-");
//	operator_str_set.insert("*");
//	operator_str_set.insert("/");
//	operator_str_set.insert("%");
//	operator_str_set.insert("(");
//	operator_str_set.insert(")");
	char s[10]={'+','-','*','/','%','(',')'};
	string t="";
	for(int i=0;i<7;i++){
		operator_set.insert(s[i]);
		t+=s[i];
		operator_str_set.insert(t);
		t="";
	}
	prio["("]=1;
	prio["+"]=2;
	prio["-"]=2;
	prio["*"]=3;
	prio["/"]=3;
	prio["%"]=3;
}

/*
  将字符串s按照运算符以及(),
  分割为若干字符串,并返回到向量vs;
 */
void getStr(string s,vector<string> &vs){
	int len = s.size();
	string t="";
	for(int i=0;i<len;i++){
		if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'||s[i]=='%'||s[i]=='('||s[i]==')'){//需要改一下
			if(t!="")
				vs.push_back(t);
			string temp(1,s[i]);
			vs.push_back(temp);
			t="";
		}
		else{
			t+=s[i];
		}
	}
	if(t!=""){
		vs.push_back(t);
	}
} 

/*
  将中序表达式,转为后序表达式
 */
void inToPostOrder(vector<string>& in,vector<string>& post){
	stack<string> st;//辅助实现中序转后序;
	string top="";
	for(auto &in_ele : in){
		if(in_ele=="+"||in_ele=="-"||in_ele=="*"||in_ele=="/"||in_ele=="%"){
			if(st.empty()){
				st.push(in_ele);
				continue;
			}
			//此时st绝对不会为空,所以取栈顶可以不加判断
			top=st.top();
//			while(!st.empty()||prio[in_ele]<prio[top]){
//				post.push_back(top);
//				st.pop();
//				top=st.top();
//			}//弹出结束,压入当前元素in_ele
			while(prio[in_ele]<=prio[top]){
				post.push_back(top);
				st.pop();
				if(st.empty()){
					break;
				}
				top=st.top();
			}
			st.push(in_ele);
		}
		else if(in_ele=="("){
			st.push(in_ele);
		}
		else if(in_ele==")"){
			while(1){
				top = st.top();
				st.pop();
				if(top != "("){
					post.push_back(top);
				}
				else{
					break;
				}
			}
		}
		else{
			post.push_back(in_ele);
		}
	}
	while(!st.empty()){
		post.push_back(st.top());
		st.pop();
	}
}

/*
  根据后序表达式计算得到答案;
 */
int calAns(vector<string> &post){
	stack<string> st;
	string top1,top2,temps;
	int temp=0;
	for(auto &ele:post){
		if(ele=="+"||ele=="-"||ele=="*"||ele=="/"||ele=="%"){
			top2=st.top();
			st.pop();
			top1=st.top();
			st.pop();
			if(ele=="+"){
				temp=(int)(stoi(top1))+(int)(stoi(top2));
			}
			else if(ele=="-"){
				temp=(int)(stoi(top1))-(int)(stoi(top2));
			}
			else if(ele=="*"){
				temp=(int)(stoi(top1))*(int)(stoi(top2));
			}
			else if(ele=="/"){
				if(top2=="0"){
					cout<<"除数为0,计算结束\n";
					return -1;
				}
				temp=(int)(stoi(top1))/(int)(stoi(top2));
			}
			else if(ele=="%"){
				if(top2=="0"){
					cout<<"除数为0,计算结束\n";
					return -1;
				}
				temp=(int)(stoi(top1))%(int)(stoi(top2));
			}
			temps = to_string(temp);
			st.push(temps);
		}
		else{
			st.push(ele);
		}
	}
	return stoi(st.top());
}

bool judge(vector<string> in){
	//检查括号是否匹配
	int left=0;
	for(auto& x:in){
		if(x=="("){
			left++;
		}
		else if(x==")"){
			left--;
			if(left<0){
				cout<<"括号不匹配\n";
				return 0;
			}
		}
	}
	if(left>0) return 0;
	//检查运算符对不对
	//为了简化,本计算器不支持输入负数
	int len = in.size();
	bool flag = (operator_str_set.find(in[len-1])!=operator_str_set.end())&&(in[len-1]!="(")&&(in[len-1]!=")")
				||(operator_str_set.find(in[0])!=operator_str_set.end())&&(in[0]!="(")&&(in[0]!=")");
	if(flag){//如果条件成立,则in[0] or in[len-1]是一个+-*/运算符
		return 0;
	}
	//+-*%运算符不能在一起;
	bool flag1,flag2,flag3;//flag123代表是不是+-*/%
	for(int i=1;i<len-1;i++){
		flag1 = (operator_str_set.find(in[i-1])!=operator_str_set.end())&&(in[i-1]!="(")&&(in[i-1]!=")");
		flag2 = (operator_str_set.find(in[i])!=operator_str_set.end())&&(in[i]!="(")&&(in[i]!=")");
		flag3 = (operator_str_set.find(in[i+1])!=operator_str_set.end())&&(in[i+1]!="(")&&(in[i+1]!=")");
		if(flag2==1&&(flag==1||flag3==1)){
			cout<<"存在两个运算符在一起的情况\n";
			return 0;
		}
	}
	//更多功能还待开发。(最近作业太多,做完了再来弄这个)
	return 1;
}

void reset(){
	inOrder.clear();
	postOrder.clear();
}

void solve(){
	init();
	cout<<"输入一个中序表达式字符串:\n";
	string s;
	cin>>s;
	getStr(s,inOrder);
	if(!judge(inOrder)){
		cout<<"检查到不合法表达式,请重新输入\n";
		reset();
		return ;
	}
	inToPostOrder(inOrder,postOrder);
	cout<<calAns(postOrder)<<endl;
	reset();
}

int main(){
	while(1){
		cout<<"*******************\n";
		cout<<"*                 *\n";
		cout<<"* 简易计算器实验  *\n";
		cout<<"* 本人水平有限    *\n";
		cout<<"* bug可能很多     *\n";
		cout<<"* 欢迎大佬们的指正*\n";
		cout<<"*                 *\n";
		cout<<"*******************\n";
		solve();
		system("pause");
		system("cls");
	}
	return 0;
}

//5*(4+(6+7))/2%8

一些运行样例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
做的很粗糙,请多多指教

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值