//一个简单的计算器代码,主要用来练习C++11新标准的编程技术和stl应用
1 #include<iostream>
#include<stack>
#include<map>
#include<set>
#include<functional>
#include<string>
using namespace std; typedef function<float(float,float)> optionFun;
stack<float> snumber;
stack<string> soption;
map<string,optionFun> optFunMap;
map<string,int> optWeightMap; #define DECLARE_OPT(opts,preority) \
optWeightMap[#opts] = int(preority);\
optFunMap[#opts] = bind([](float a, float b){return a opts b;}, placeholders::_1, placeholders::_2); void init_option()
{
DECLARE_OPT(+,);
DECLARE_OPT(-,);
DECLARE_OPT(*,);
DECLARE_OPT(/,);
} bool isoption(string op)
{
auto it = optWeightMap.find(op);
return it!=optWeightMap.end();
}
float recognize_float(const char* pstr, int& width)
{
char value[]={};
int dotcount = ;
for(int i=;pstr[i]!='\0';i++)
{
int x = pstr[i];
if(isdigit(x)||(x=='.'&&dotcount==))
{
value[i] = x;
dotcount++;
}
else
{
width = i;
break;
}
}
return atof(value);
} //offset from '(' to ')'
int check_match(const char* str)
{
int offset = ;
bool match = false;
while(str[offset]!='\0')
{
if(str[offset++]==')')
{
match = true;
break;
}
}
return match?offset:-;
} void handle_stack()
{
while(!soption.empty())
{
string opt = soption.top();
if(opt=="(")
{
soption.pop();
break;
}
auto it = optFunMap.find(opt);
if(it != optFunMap.end())
{
auto fun = it->second;
float a= snumber.top();
snumber.pop();
float b = snumber.top();
snumber.pop();
snumber.push(fun(b,a));
soption.pop();
}
}
}
float calc(const char* str)
{
if(str==nullptr)
{
cout<<"invalid express"<<endl;
return ;
} if(*str=='+'||*str=='-')
{
snumber.push();
}
while(*str!='\0')
{
if(isdigit(*str))
{
int len;
snumber.push(recognize_float(str,len));
str+=len;
continue;
}
if(*str=='(')
{
int len = check_match(str);
if(len==-)
{
cout<<"sync error : the express less a ')'"<<endl;
return;
}
soption.push("(");
calc(str+);
str += len;
continue;
}
if(*str==')')
{
handle_stack();
return ;
}
string ops(,*str);
if(isoption(ops))
{
if(!soption.empty())
{
if(optWeightMap[ops]<optWeightMap[soption.top()])
{
handle_stack();
}
}
soption.push(ops);
str++;
continue;
}
cout<<"invalid express"<<endl;
return ;
}
handle_stack();
return snumber.top();
}
int main()
{
init_option();
string str;
while(str!="exit")
{
cout<<"> ";
cin>>str;
if("exit"==str)break;
cout<<calc(str.c_str())<<endl;
}
return ;
}
这个计算器去年也写了一个,这次代码少了将近一半,说明还是有进步的……下次再少一点就好了,因为现在看上去还是有一些不和谐的东西,比如float类型的限制、括号处理分在了两个函数里面等。