C++简易计算器

功能

可以处理{} [] () 及+ - * /,公式必须以=结束,否则判断为无效公式

在计算时,按照程序员式计算方式,别如3/2=1,而不是1.5,如需按照普通模式,稍作修改即可。

逻辑

主逻辑

先处理括号,并从()开始:

1.从左往右找第一个),记录位置posend

2.从posend往左找与其闭合的(

3.截取()中间的字符串进行处理(处理过程见基础运算),计算结果,并以字符串形式返回,

4用3中返回的字符串替换(),形成新的字符串,重复1-4

5如果没有找到),结束开始处理[],步骤与()类似,然后是{},一直到所有括号全部处理完毕,最后就是没有括号的基础运算。

基础运算逻辑

将字符串进行分割,遇到+-*/运算符就进行分割,但是因为有负数存在-1,所以,如果再-前面如果有运算符存在,或者-位于0位置,那么该-归到下一个数字中,而不作为运算符。

分割完毕后,字符存储在list中,并按照从左到右,从*/到+-的顺序开始计算。

代码

1.程序员逻辑代码(即3/2=1)


#include <iostream>
#include <string>
#include <list>
using namespace std;
//判断是否合法
bool isValid(string &str)
{
	char spec[] = {'+','-','*','/','{','}','[',']','(',')'};
	//删除空格
	unsigned int i=0,j=0;
	char buf[100] = {0};
	while(i<str.length())
	{
		if(str.at(i)== ' ')
		{
			i++;
			continue;
		}
		else
		{
			buf[j++] = str.at(i);
			i++;
		}
	}
	str = buf;
	unsigned int len = str.length();
	if (str.at(len -1) != '=')
	{
		cout << "公式需以=结束"<< endl;
		return false;
	}else
		str = str.substr(0,len-1);
	//判断是否有非数字的内容
	i = 0;
	len = str.length();
	while(i < len)
	{
		if(str.at(i)< '0' || str.at(i) > '9'   )
		{
			for (j =0;j<10;j++)
			{
				if(str.at(i) == spec[j])
					break;
			}
			if(j == 10)
			{
				cout << "公式中存在非法字符:" << str.at(i)<< endl;
				return false;
			}
		}
		i++;
	}

	//遇到3(2+3)、(2+3)3这种直接提示错误,不默认插入*
	i= 0;
	while(i < str.length()-1)
	{
		if(str.at(i) >= '0' && str.at(i) <= '9')
		{
			if(str.at(i+1)== '(' || str.at(i+1) == '[' || str.at(i+1) == '{')
			{
				cout << "在" << str.at(i) << "和" << str.at(i+1) << "之间需要添加运算符" << endl;
				return false;
			}
		}
		if(str.at(i)== ')' || str.at(i) == ']' || str.at(i) == '}')
		{
			if(str.at(i+1) >= '0' && str.at(i+1) <= '9')
			{
				str.insert(i+1,1,'*');
				cout << "在" << str.at(i) << "和" << str.at(i+1) << "之间需要添加运算符" << endl;
				return false;
			}
		}
		i++;
	}
	return true;
}
//判断是否是数字
bool isNmb(string s)
{
	unsigned int i = 0;
	if(s.empty())
		return false;
	if(s.at(0) == '-')
	{
		i=1;
		while(i<s.length())
		{
			if(s.at(i) == '.')
			{
				i++;
				continue;
			}
			if(s.at(i)< '0' || s.at(i) >'9')
				return false;
			i++;
		}
	}else
	{
		i = 0;
		while(i<s.length())
		{
			if(s.at(i) == '.')
			{
				i++;
				continue;
			}
			if(s.at(i)< '0' || s.at(i) >'9')
				return false;
			i++;
		}
	}
	return true;
}
//判断数字是否是整数
bool isZs(string s)
{
	unsigned int i = 0;
	while(i<s.length())
	{
		if(s.at(i) == '.')
			return false;
		i++;
	}
	return true;
}
//处理一个最简单的计算公式
bool DealSmple(string str,string &out)
{
	//cout << "    -->"<< str << endl;
	unsigned int i =0,j=0;
	//将字符串分隔
	list<string> vp;
	int prepos =0;
	while(i<str.length())
	{
		if (str.at(i) == '+'  || str.at(i)=='*' || str.at(i) == '/' )
		{
			string tmp = str.substr(prepos,i-prepos);
			vp.push_back(tmp);
			vp.push_back(str.substr(i,1));
			i++;
			prepos = i;
		}else if( str.at(i) =='-') //查找连续--的情况
		{
			if( (i == 0) || (vp.size() > 0 && (str.at(i-1) == '+' || str.at(i-1) == '-' || str.at(i-1) == '*' || str.at(i-1) == '/')) ) //如果上一字符是-号,那么把当前的-留给下面的字符
				i++;
			else
			{
				string tmp = str.substr(prepos,i-prepos);
				vp.push_back(tmp);
				vp.push_back(str.substr(i,1));
				i++;
				prepos = i;
			}
		}
		else
			i++;
	}
	if(prepos == str.length())
	{
		cout << "公式中存在以"<< str.at(str.length()-1) << "结尾的非法公式段"<<endl;
		return false;
	}
	vp.push_back(str.substr(prepos,str.length() - prepos));
	//如果只有一个元素,直接退出
	if(vp.size() == 1)
	{
		out = vp.front();
		return true;
	}
	//计算乘法除法
	list<string>::iterator it = vp.begin();
	list<string>::iterator tmp;
	for (;it != vp.end();)
	{
		if(it->compare("*")==0 )//先处理乘法和除法
		{
			if (it == vp.begin())
			{
				cout << "*出现在公式的开头"<< endl;
				return false;
			}
			it++;
			if (it == vp.end())
			{
				cout << "*出现在公式的末尾" << endl;
				return false;
			}
			string nmb2 = *it;
			tmp = it;
			tmp--;
			vp.erase(it);
			it = tmp;
			tmp--;
			vp.erase(it);
			it = tmp;
			string nmb1 = *it;
			//判断是否是数字
			if ((!isNmb(nmb1)) || (!isNmb(nmb2)))
			{
				cout << "存在多个连续的运算符或者数字个数不正确" << endl;
				return false;
			}

			char val[20]={0};
			//判断两个数是否都是整数
			if (isZs(nmb1) && isZs(nmb2))
			{
				int a = atoi(nmb1.c_str());
				int b = atoi(nmb2.c_str());
				int c = a*b;
				itoa(c,val,10);
			}else
			{
				double a = atof(nmb1.c_str());
				double b = atof(nmb2.c_str());
				double c = a*b;
				gcvt(c,10,val);
			}
			it = vp.insert(it,val);
			it++;
			vp.erase(it);

			it = vp.begin();
		}else if (it->compare("/") == 0)
		{
			if (it == vp.begin())
			{
				cout << "/出现在公式的开头"<< endl;
				return false;
			}
			it++;
			if (it == vp.end())
			{
				cout << "/出现在公式的末尾" << endl;
				return false;
			}
			string nmb2 = *it;
			tmp = it;
			tmp--;
			vp.erase(it);
			it = tmp;
			tmp--;
			vp.erase(it);
			it = tmp;
			string nmb1 = *it;
			//判断是否是数字
			if ((!isNmb(nmb1)) || (!isNmb(nmb2)))
			{
				cout << "存在多个连续的运算符或者数字个数不正确" << endl;
				return false;
			}
			char val[20]={0};
			//判断两个数是否都是整数
			if (isZs(nmb1) && isZs(nmb2))
			{
				int a = atoi(nmb1.c_str());
				int b = atoi(nmb2.c_str());
				if(b==0)
				{
					cout << "除数为0"<< endl;
					return false;
				}
				int c = a/b;
				itoa(c,val,10);
			}else
			{
				double a = atof(nmb1.c_str());
				double b = atof(nmb2.c_str());
				if(b==0.0)
				{
					cout << "除数为0"<< endl;
					return false;
				}
				double c = a/b;
				gcvt(c,10,val);
			}
			it = vp.insert(it,val);
			it++;
			vp.erase(it);
			it = vp.begin();
		}else
			it++;
	}
	//计算加减
	bool iszhs = true;
	for (it=vp.begin();it != vp.end(); it++)
	{
		if (!isZs(*it))
		{
			iszhs = false;
			break;
		}
	}
	if (vp.size() == 1)
	{
		out = vp.front();
		return true;
	}else
	{
		if (iszhs)
		{
			int sum = 0;
			it = vp.begin();
			string tt = *it;
			sum += atoi(tt.c_str());
			it++;
			while(it != vp.end())
			{
				string ts = *it;
				it++;
				if(it == vp.end())
				{
					cout << "公式运算中出现以运算符结尾的情况"<< endl;
					return false;
				}
				string nmb3 = *it;
				if (ts.compare("+") == 0)
				{
					sum += atoi(nmb3.c_str());
				}else if (ts.compare("-") == 0)
				{
					sum -= atoi(nmb3.c_str());
				}else
				{
					cout << "公式出现不匹配的运算符" << endl;
					return false;
				}
				it++;
			}
			char bufout[20] ={0};
			itoa(sum,bufout,10);
			out = bufout;
			return true;
		}else
		{
			double sum = 0.0;
			it = vp.begin();
			string tt = *it;
			sum += atof(tt.c_str());
			it++;
			while(it != vp.end())
			{
				string ts = *it;
				it++;
				if(it == vp.end())
				{
					cout << "公式运算中出现以运算符结尾的情况"<< endl;
					return false;
				}
				string nmb3 = *it;
				if (ts.compare("+") == 0)
				{
					sum += atof(nmb3.c_str());
				}else if (ts.compare("-") == 0)
				{
					sum -= atof(nmb3.c_str());
				}else
				{
					cout << "公式出现不匹配的运算符" << endl;
					return false;
				}
				it++;
			}
			char bufout[20] ={0};
			gcvt(sum,10,bufout);
			out = bufout;
			return true;
		}
	}

	return true;
}
//处理括号
bool DealKuhao(string &strSrc, char ch,char ch2)
{
	//先处理小括号
	while(1)
	{
		int posEnd = strSrc.find(ch);
		if(posEnd < 0)
			return true;
		else if(posEnd == 0)
		{
			cout << ch <<"缺少对应的左括号" << endl;
			return false;
		}else
		{
			//找到与之对应的大括号
			int i = posEnd -1;
			while(i >=0 && strSrc.at(i) != ch2)
				i--;
			if(i < 0)
			{
				cout << ch << "没有与之配对的左括号" << endl;
				return false;
			}
			string tmp = strSrc.substr(i+1,posEnd - i-1); //截取()之间的字符串
			string strout="";
			if(DealSmple(tmp,strout))  //处理()之间的公式,并返回处理结果
			{
				strSrc = strSrc.substr(0,i) + strout + strSrc.substr(posEnd+1,strSrc.length() - posEnd);
				//cout << "DealSmple " << ch << "  " << strSrc << endl;
			}else
				return false;
		}
	}
	return true;
}


int main()
{
	string strSrc,strout = "";
	cout << "请输入公式,以=号结束:" << endl;;
	getline(cin,strSrc);
	if(!isValid(strSrc))
		return 0;
	if(!DealKuhao(strSrc,')','('))
		return 0;
	if(!DealKuhao(strSrc,']','['))
		return 0;
	if(!DealKuhao(strSrc,'}','{'))
		return 0;
	DealSmple(strSrc,strout);
	cout << strout << endl;
	return 0;
}

2.普通逻辑(3/2=1.5)

#include <iostream>
#include <string>
#include <list>
using namespace std;
//判断是否合法
bool isValid(string &str)
{
	char spec[] = {'+','-','*','/','{','}','[',']','(',')'};
	//删除空格
	unsigned int i=0,j=0;
	char buf[100] = {0};
	while(i<str.length())
	{
		if(str.at(i)== ' ')
		{
			i++;
			continue;
		}
		else
		{
			buf[j++] = str.at(i);
			i++;
		}
	}
	str = buf;

	unsigned int len = str.length();
	if (str.at(len -1) != '=')
	{
		cout << "公式需以=结束"<< endl;
		return false;
	}else
		str = str.substr(0,len-1);
	//判断是否有非数字的内容
	i = 0;
	len = str.length();
	while(i < len)
	{
		if(str.at(i)< '0' || str.at(i) > '9'   )
		{
			for (j =0;j<10;j++)
			{
				if(str.at(i) == spec[j])
					break;
			}
			if(j == 10)
			{
				cout << "公式中存在非法字符:" << str.at(i)<< endl;
				return false;
			}

		}
		i++;
	}


	//遇到3(2+3)、(2+3)3这种直接提示错误,不默认插入*
	i= 0;
	while(i < str.length()-1)
	{
		if(str.at(i) >= '0' && str.at(i) <= '9')
		{
			if(str.at(i+1)== '(' || str.at(i+1) == '[' || str.at(i+1) == '{')
			{
				cout << "在" << str.at(i) << "和" << str.at(i+1) << "之间需要添加运算符" << endl;
				return false;
			}

		}
		if(str.at(i)== ')' || str.at(i) == ']' || str.at(i) == '}')
		{
			if(str.at(i+1) >= '0' && str.at(i+1) <= '9')
			{
				str.insert(i+1,1,'*');
				cout << "在" << str.at(i) << "和" << str.at(i+1) << "之间需要添加运算符" << endl;
				return false;
			}
		}
		i++;
	}
	return true;
}
//判断是否是数字
bool isNmb(string s)
{
	unsigned int i = 0;
	if(s.empty())
		return false;
	if(s.at(0) == '-')
	{
		i=1;
		while(i<s.length())
		{
			if(s.at(i) == '.')
			{
				i++;
				continue;
			}
			if(s.at(i)< '0' || s.at(i) >'9')
				return false;
			i++;
		}
	}else
	{
		i = 0;
		while(i<s.length())
		{
			if(s.at(i) == '.')
			{
				i++;
				continue;
			}
			if(s.at(i)< '0' || s.at(i) >'9')
				return false;
			i++;
		}
	}
	return true;
}

//处理一个最简单的计算公式
bool DealSmple(string str,string &out)
{
	unsigned int i =0,j=0;

	//将字符串分隔
	list<string> vp;
	int prepos =0;
	while(i<str.length())
	{
		if (str.at(i) == '+'  || str.at(i)=='*' || str.at(i) == '/' )
		{
			string tmp = str.substr(prepos,i-prepos);
			vp.push_back(tmp);
			vp.push_back(str.substr(i,1));
			i++;
			prepos = i;
		}else if( str.at(i) =='-') //查找连续--的情况
		{
			if( (i == 0) || (vp.size() > 0 && (str.at(i-1) == '+' || str.at(i-1) == '-' || str.at(i-1) == '*' || str.at(i-1) == '/')) ) //如果上一字符是-号,那么把当前的-留给下面的字符
				i++;
			else
			{
				string tmp = str.substr(prepos,i-prepos);
				vp.push_back(tmp);
				vp.push_back(str.substr(i,1));
				i++;
				prepos = i;
			}
		}
		else
			i++;
	}
	if(prepos == str.length())
	{
		cout << "公式中存在以"<< str.at(str.length()-1) << "结尾的非法公式段"<<endl;
		return false;
	}
	vp.push_back(str.substr(prepos,str.length() - prepos));

	//如果只有一个元素,直接退出
	if(vp.size() == 1)
	{
		out = vp.front();
		return true;
	}

	//计算乘法除法
	list<string>::iterator it = vp.begin();
	list<string>::iterator tmp;
	for (;it != vp.end();)
	{
		if(it->compare("*")==0 )//先处理乘法和除法
		{
			if (it == vp.begin())
			{
				cout << "*出现在公式的开头"<< endl;
				return false;
			}
			it++;
			if (it == vp.end())
			{
				cout << "*出现在公式的末尾" << endl;
				return false;
			}
			string nmb2 = *it;
			tmp = it;
			tmp--;
			vp.erase(it);
			it = tmp;
			tmp--;
			vp.erase(it);
			it = tmp;
			string nmb1 = *it;

			//判断是否是数字
			if ((!isNmb(nmb1)) || (!isNmb(nmb2)))
			{
				cout << "存在多个连续的运算符或者数字个数不正确" << endl;
				return false;
			}
			char val[20]={0};
			double a = atof(nmb1.c_str());
			double b = atof(nmb2.c_str());
			double c = a*b;
			gcvt(c,10,val);


			it = vp.insert(it,val);
			it++;
			vp.erase(it);


			it = vp.begin();
		}else if (it->compare("/") == 0)
		{
			if (it == vp.begin())
			{
				cout << "/出现在公式的开头"<< endl;
				return false;
			}
			it++;
			if (it == vp.end())
			{
				cout << "/出现在公式的末尾" << endl;
				return false;
			}
			string nmb2 = *it;
			tmp = it;
			tmp--;
			vp.erase(it);
			it = tmp;
			tmp--;
			vp.erase(it);
			it = tmp;
			string nmb1 = *it;

			//判断是否是数字
			if ((!isNmb(nmb1)) || (!isNmb(nmb2)))
			{
				cout << "存在多个连续的运算符或者数字个数不正确" << endl;
				return false;
			}

			char val[20]={0};
			double a = atof(nmb1.c_str());
			double b = atof(nmb2.c_str());
			if(b==0)
			{
				cout << "除数为0"<< endl;
				return false;
			}
			double c = a/b;
			gcvt(c,10,val);


			it = vp.insert(it,val);
			it++;
			vp.erase(it);

			it = vp.begin();
		}else
			it++;
	}

	//计算加减
	if (vp.size() == 1)
	{
		out = vp.front();
		return true;
	}else
	{
		double sum = 0.0;
		it = vp.begin();
		string tt = *it;
		sum += atof(tt.c_str());
		it++;
		while(it != vp.end())
		{
			string ts = *it;
			it++;
			if(it == vp.end())
			{
				cout << "公式运算中出现以运算符结尾的情况"<< endl;
				return false;
			}
			string nmb3 = *it;
			if (ts.compare("+") == 0)
			{
				sum += atof(nmb3.c_str());
			}else if (ts.compare("-") == 0)
			{
				sum -= atof(nmb3.c_str());
			}else
			{
				cout << "公式出现不匹配的运算符" << endl;
				return false;
			}
			it++;
		}

		char bufout[20] ={0};
		gcvt(sum,10,bufout);
		out = bufout;
		return true;
	}
	return true;
}

//处理括号
bool DealKuhao(string &strSrc, char ch,char ch2)
{
	//先处理小括号
	while(1)
	{
		int posEnd = strSrc.find(ch);
		if(posEnd < 0)
			return true;
		else if(posEnd == 0)
		{
			cout << ch <<"缺少对应的左括号" << endl;
			return false;
		}else
		{
			//找到与之对应的大括号
			int i = posEnd -1;
			while(i >=0 && strSrc.at(i) != ch2)
				i--;
			if(i < 0)
			{
				cout << ch << "没有与之配对的左括号" << endl;
				return false;
			}
			string tmp = strSrc.substr(i+1,posEnd - i-1); //截取()之间的字符串
			string strout="";
			if(DealSmple(tmp,strout))  //处理()之间的公式,并返回处理结果
			{
				strSrc = strSrc.substr(0,i) + strout + strSrc.substr(posEnd+1,strSrc.length() - posEnd);
				cout << "DealSmple " << ch << "  " << strSrc << endl;
			}else
				return false;
		}
	}
	return true;
}




int main()
{
	string strSrc,strout = "";
	cout << "请输入公式,以=号结束:" << endl;;
	getline(cin,strSrc);

	if(!isValid(strSrc))
		return 0;

	if(!DealKuhao(strSrc,')','('))
		return 0;
	if(!DealKuhao(strSrc,']','['))
		return 0;
	if(!DealKuhao(strSrc,'}','{'))
		return 0;
	DealSmple(strSrc,strout);
	cout << strout << endl;

	return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qfl_sdu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值