功能
可以处理{} [] () 及+ - * /,公式必须以=结束,否则判断为无效公式
在计算时,按照程序员式计算方式,别如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;
}