类封装版表达式计算器
前些日子,写了个c语言的表达式计算器,感觉缺点很多,首先速度不够快,再来可复用性太差,难以移植到别的代码中,再就是兼容性不够,不好修改优化.。
这次我写了个c++ 版本的,封装成了类,类名是repre_calor,类定义文件叫repre_calor.h和 repre_calor.cpp,main.cpp是调用实验用的,如果在一个project里要用repre_calor的话,必须包含头文件repre_calor.h,然后把repre_calor.h和 repre_calor.cpp复制到project中,方可使用。
这次程序,栈利用了标准库中的stack类型,经测试,大大提高了速度和安全性,其他的c++标准化改动不列举了。。。。。。。呵呵。。。。。。
这是原先c语言版本http://www.cnblogs.com/huanyan/archive/2010/10/23/1858802.html
文件:repre_calor.h
#pragma once
#ifndef REPRE_CALOR_H
#define REPRE_CALOR_H
#define ASCII_NUMBER_MAX 256
#include<vector>
#include<stack>
#include<string>
class repre_calor
{
public:
repre_calor()
{
state=false;
input_error=false;
brackets_error=false;
calculation_error=false;
wrong_brackets=false;
ans=0.0;
string_cursor=0;
detail_error=false;
importance.resize(ASCII_NUMBER_MAX,0);
inim(importance);
}
bool state;//若true,则表明有错误发生
void error_output();//可以向用户输出具体发生了什么错误
bool work();//实际计算的成员函数
void initialize();//这个成员函数可以初始化表达式计算类
bool shuzi(std::string& ab);//判断字符串ab中的字符是否都是合法字符,合法返回0,否则返回1
bool kuohao(std::string& s);//判断字符串s中的左右括号个数是否匹配,匹配返回0,不匹配返回1
inline void inim(std::vector<int>& ck);//初始化合法字符列表ck
void nospace(std::string& s);//去除字符串s中的空格
void input(std::istream& incoming);//调用这个成员函数从流incoming输入表达式
void input(std::string& incoming);//input另一个重载版本,支持用string类型重置pin
double ans;//最后结果
bool detail_error;//若出错,是否输出详细错误信息?默认为输出(true)
private:
void calit(std::stack<double,std::vector<double> > &s1,std::stack<char,std::vector<char> > &s2,char tem);
double change(std::string& s,std::string::size_type &st);
bool input_error;//若输入非法字符,则为true
bool brackets_error;//若括号不匹配,则为true
bool calculation_error;//若表达式内出现非法计算单元,则为true
bool wrong_brackets;//"()"这样的输入是不被允许的
std::string pin;//键盘输入
std::vector<int> importance;//优先级容器
std::stack<double,std::vector<double> > stack1;//stack1为操作数栈
std::stack<char,std::vector<char> > stack2;//stack2 为符号栈
char temp;/*stack2 为符号栈*/
std::string::size_type lenth,string_cursor;
std::string calculation_error_infor;
};
inline void repre_calor::inim(std::vector<int>& ck)
{
ck['+']=1;
ck['-']=1;
ck['*']=2;
ck['^']=3;
ck['/']=2;
ck['(']=10;
ck[')']=-1;
ck['#']=-2;
ck['a']=-3;
ck[' ']=-3;
ck['.']=-3;
ck['1']=-3;
ck['A']=-3;
ck['2']=-3;
ck['3']=-3;
ck['7']=-3;
ck['4']=-3;
ck['8']=-3;
ck['5']=-3;
ck['9']=-3;
ck['6']=-3;
ck['0']=-3;
}
inline void repre_calor::input(std::istream& incoming)
{
std::getline(incoming,pin);
}
inline void repre_calor::input(std::string& incoming)
{
pin.assign(incoming);
}
#endif
文件:repre_calor.cpp
#ifndef REPRE_CALOR
#define REPRE_CALOR
#include <cstdlib>
#include<iostream>
#include <math.h>
#include <conio.h>
#include "repre_calor.h"
double repre_calor::change(std::string &s,std::string::size_type &st)
//从字符串s中读取一个数,st是在s上的游标
//即从st开始读出一个数,如果读不出来则返回0
{
bool q(false);
std::string::size_type temp;
if ((s[st]=='-')&&(importance[s[(st)-1]]>(-3)))
{
q=true;
++st;
}
std::string tm(s,st,temp=s.find_first_not_of("1234567890.",st));
st=temp-1;
if (q) return (-atof(tm.c_str()));
else return(atof(tm.c_str()));
}
void repre_calor::calit(std::stack<double,std::vector<double> > &s1,std::stack<char,std::vector<char> > &s2,char tem)/*解析表达式*/
{
for (; importance[s2.top()]>importance[tem]; s2.pop())
{
if (s2.top()=='(')
{
return;
}
if (s1.empty())
{
if (detail_error) std::cout<<"what you have input was wrong,input again"<<std::endl;
input_error=true;
state=true;
return;
}
switch (s2.top())
{
double temp_double;
case '+':
temp_double=s1.top();
s1.pop();
s1.top()+=temp_double;
break;
case '-':
temp_double=s1.top();
s1.pop();
s1.top()-=temp_double;
break;
case '*':
temp_double=s1.top();
s1.pop();
s1.top()*=temp_double;
break;
case '/':
if (s1.top()==0.0)
{
if (detail_error)std::cout<<"0 is not a divisor,you must input again."<<std::endl;
calculation_error=true;
state=true;
calculation_error_infor.assign("0 is not a divisor,you must input again.");
return;
}
else
{
temp_double=s1.top();
s1.pop();
s1.top()/=temp_double;
break;
}
case '^':
temp_double=s1.top();
s1.pop();
if ((temp_double==0)&&(s1.top()==0))
{
if (detail_error)std::cout<<"0^0 is not legal,input again"<<std::endl;
calculation_error=true;
state=true;
calculation_error_infor.assign("0^0 is not legal,input again");
return;
}
s1.top()=pow(s1.top(),temp_double);
break;
}
}
}
void repre_calor::nospace(std::string& s)/*去掉字符串中的空格*/
{
std::string temp_s(s);
std::string::size_type end_s(temp_s.size());
s.clear();
for (std::string::size_type si(0); si!=end_s; ++si)
{
if (temp_s[si]!=' ')
{
s.push_back(temp_s[si]);
}
}
}
bool repre_calor::kuohao(std::string& s)/*判断括号是否匹配,匹配返回0,不匹配返回1*/
{
std::string::size_type len(s.size()),count(0),tem(0);
if (s[count]=='(') ++tem;
if (s[count]==')') --tem;
if (tem<0)
{
brackets_error=true;
state=true;
return true;
}
++count;
for (; count!=len; ++count)
{
if (s[count]=='(') ++tem;
if (s[count]==')')
{
if(s[count-1]=='(')
{
state=true;
wrong_brackets=true;
return true;
}
--tem;
}
if (tem<0) return true;
}
if (tem>0) return true;
return false;
}
bool repre_calor::shuzi(std::string& ab)/*判断ab中存储的字符是否都是合法字符,合法返回0,否则返回1*/
{
std::string::size_type temp_end(ab.size());
for (std::string::size_type i=0; i!=temp_end; ++i)
{
if (!importance[ab[i]])
{
state=true;
input_error=true;
return true;
}
}
return false;
}
bool repre_calor::work()
{
if (pin.empty())
{
if (detail_error) std::cout<<"The class is empty,please give a string to .pin!!"<<std::endl;
state=true;
return true;
}
initialize();
stack2.push('#');
nospace(pin);/*先对pin中的表达式去除空格*/
lenth=pin.size()-1;
if (shuzi(pin))/*shuzi(pin)判断pin中的表达式是否合法*/
{
if (detail_error)std::cout<<std::endl<<"Not a right input,you must input again."<<std::endl;
return true;
}
if (kuohao(pin))/*kuohao(pin)判断pin中的表达式中的括号是否能匹配*/
{
if (detail_error)std::cout<<std::endl<<"you may lost a'(' or a ')',please input again"<<std::endl;
return true;
}
if (pin[0]=='-')
{
if (pin[1]=='(')
{
stack2.push('-');
stack1.push(0);
string_cursor=1;
}
else
{
++string_cursor;
stack1.push(-change(pin,string_cursor));
++string_cursor;
}
}
while (string_cursor<=lenth)
{
temp=pin[string_cursor];
if (((temp<='9')&&(temp>='0'))||(temp=='.')||((temp=='-')&&(importance[pin[string_cursor-1]]!=(-3))))
{
stack1.push(change(pin,string_cursor));
}
else
{
if ((temp=='a')||(temp=='A'))
{
stack1.push(ans);
}
else
{
if (importance[temp]>=importance[stack2.top()])/*判断运算符的优先级*/
/*如果当前操作的优先级高于之前操作的优先级,压栈*/
{
stack2.push(temp);
}
else
{
calit(stack1,stack2,temp);
if (state) return true;
stack2.push(temp);
if (temp==')')
{
stack2.pop();
stack2.pop();
}
}
}
}
++string_cursor;
}
calit(stack1,stack2,'#');
if (state) return true;
ans=stack1.top();
return false;
}
void repre_calor::initialize()//显式初始化
{
inim(importance);
while (!stack1.empty()) stack1.pop();
while (!stack2.empty()) stack2.pop();
string_cursor=0;
lenth=0;
state=false;
input_error=false;
brackets_error=false;
calculation_error=false;
wrong_brackets=false;
}
void repre_calor::error_output()
{
if (pin.empty())
{
std::cout<<"No input!"<<std::endl;
return;
}
if (!state) std::cout<<"No error was found!"<<std::endl;
else
{
if (input_error) std::cout<<"Not a right input,you must input again."<<std::endl;
if (wrong_brackets) std::cout<<"That '()' is not allowed!"<<std::endl;
if (brackets_error) std::cout<<"You may lost a'(' or a ')',please input again"<<std::endl;
if (calculation_error) std::cout<<calculation_error_infor<<std::endl;
}
}
#endif
文件:main.cpp
#include <iostream>
#include <conio.h>
#include "repre_calor.h"
int judgement('y');
void main_operation();//主界面
repre_calor calor;//定义calor为一个表达式的类
int main()
{
main_operation();
while ((judgement=='y')||(judgement=='Y'))
{
std::cout<<std::endl<<std::endl<<"Please input a representation"<<std::endl;
calor.input(std::cin);
calor.detail_error=false;
if (calor.work()) calor.error_output();//原先计算全部过程精简为这一句
else std::cout<<"The answer is "<<calor.ans;
std::cout<<"\nContinue(y/n)?";
judgement=_getch();
while ((judgement!='y')&&(judgement!='Y')
&&(judgement!='n')&&(judgement!='N'))
{
std::cout<<std::endl<<"You need to input again."<<std::endl;
judgement=_getch();
}
}
std::cout<<std::endl<<"***********************************"<<std::endl
<<"May you have a good time!!\nBye bye!!"<<std::endl
<<"***********************************"<<std::endl;
system("pause");
return 0;
}

浙公网安备 33010602011771号