算术表达式解析(第二版) C++11版

//一个简单的计算器代码,主要用来练习C++11新标准的编程技术和stl应用
1
#include<iostream> 2 #include<stack> 3 #include<map> 4 #include<set> 5 #include<functional> 6 #include<string> 7 using namespace std; 8 9 10 typedef function<float(float,float)> optionFun; 11 stack<float> snumber; 12 stack<string> soption; 13 map<string,optionFun> optFunMap; 14 map<string,int> optWeightMap; 15 16 #define DECLARE_OPT(opts,preority) \ 17 optWeightMap[#opts] = int(preority);\ 18 optFunMap[#opts] = bind([](float a, float b){return a opts b;}, placeholders::_1, placeholders::_2); 19 20 21 void init_option() 22 { 23 DECLARE_OPT(+,1); 24 DECLARE_OPT(-,1); 25 DECLARE_OPT(*,2); 26 DECLARE_OPT(/,2); 27 } 28 29 bool isoption(string op) 30 { 31 auto it = optWeightMap.find(op); 32 return it!=optWeightMap.end(); 33 } 34 float recognize_float(const char* pstr, int& width) 35 { 36 char value[24]={0}; 37 int dotcount = 0; 38 for(int i=0;pstr[i]!='\0';i++) 39 { 40 int x = pstr[i]; 41 if(isdigit(x)||(x=='.'&&dotcount==0)) 42 { 43 value[i] = x; 44 dotcount++; 45 } 46 else 47 { 48 width = i; 49 break; 50 } 51 } 52 return atof(value); 53 } 54 55 //offset from '(' to ')' 56 int check_match(const char* str) 57 { 58 int offset = 1; 59 bool match = false; 60 while(str[offset]!='\0') 61 { 62 if(str[offset++]==')') 63 { 64 match = true; 65 break; 66 } 67 } 68 return match?offset:-1; 69 } 70 71 void handle_stack() 72 { 73 while(!soption.empty()) 74 { 75 string opt = soption.top(); 76 if(opt=="(") 77 { 78 soption.pop(); 79 break; 80 } 81 auto it = optFunMap.find(opt); 82 if(it != optFunMap.end()) 83 { 84 auto fun = it->second; 85 float a= snumber.top(); 86 snumber.pop(); 87 float b = snumber.top(); 88 snumber.pop(); 89 snumber.push(fun(b,a)); 90 soption.pop(); 91 } 92 } 93 } 94 float calc(const char* str) 95 { 96 if(str==nullptr) 97 { 98 cout<<"invalid express"<<endl; 99 return 0; 100 } 101 102 if(*str=='+'||*str=='-') 103 { 104 snumber.push(0); 105 } 106 while(*str!='\0') 107 { 108 if(isdigit(*str)) 109 { 110 int len; 111 snumber.push(recognize_float(str,len)); 112 str+=len; 113 continue; 114 } 115 if(*str=='(') 116 { 117 int len = check_match(str); 118 if(len==-1) 119 { 120 cout<<"sync error : the express less a ')'"<<endl; 121 return; 122 } 123 soption.push("("); 124 calc(str+1); 125 str += len; 126 continue; 127 } 128 if(*str==')') 129 { 130 handle_stack(); 131 return 0; 132 } 133 string ops(1,*str); 134 if(isoption(ops)) 135 { 136 if(!soption.empty()) 137 { 138 if(optWeightMap[ops]<optWeightMap[soption.top()]) 139 { 140 handle_stack(); 141 } 142 } 143 soption.push(ops); 144 str++; 145 continue; 146 } 147 cout<<"invalid express"<<endl; 148 return 0; 149 } 150 handle_stack(); 151 return snumber.top(); 152 } 153 int main() 154 { 155 init_option(); 156 string str; 157 while(str!="exit") 158 { 159 cout<<"> "; 160 cin>>str; 161 if("exit"==str)break; 162 cout<<calc(str.c_str())<<endl; 163 } 164 return 0; 165 }

   这个计算器去年也写了一个,这次代码少了将近一半,说明还是有进步的……下次再少一点就好了,因为现在看上去还是有一些不和谐的东西,比如float类型的限制、括号处理分在了两个函数里面等。

posted @ 2014-03-09 18:26  mjwk  阅读(1331)  评论(0编辑  收藏  举报