代码分为两段
一段为将输入分解为TOKEN : 0-9 ( ) + _ * /
一段为根据输入进行计算
第一段
#include <iostream> #include <string> #include <vector> #include <deque> #include <tuple> #include <assert.h> using namespace std; enum CALC_STATUS{ InitStatus = 0, InNumberStatus, InIdentStatus, EndLineStatus, BadStatus }; enum Token_Type{ NumberTokenType, LparamTokenType, RparamTokenType, AddTokenType, SubTokenType, MulTokenType, DivTokenType, BadTokenType }; typedef struct TOKEN_TUPLE{ TOKEN_TUPLE(const std::string& token,const Token_Type& type){ s = token; t = type; } TOKEN_TUPLE(){}; TOKEN_TUPLE(const TOKEN_TUPLE& tt){ s = tt.s; t = tt.t; } std::string s; Token_Type t; }; std::deque<TOKEN_TUPLE> tokenDeque; void InsertToken(const std::string& token,const Token_Type& type){ tokenDeque.push_front(TOKEN_TUPLE(token,type)); } bool IsIdent(const char cc){ return ( cc == ‘+‘ || cc == ‘-‘ || cc == ‘*‘ || cc == ‘/‘ || cc == ‘(‘ || cc == ‘)‘ ); } void InsertIdentToken(const std::string& token) { Token_Type tokenType = BadTokenType; if(token.size() != 1 || !IsIdent(token[0])) return; if(token[0] == ‘+‘){ tokenType = AddTokenType; }else if(token[0] == ‘-‘){ tokenType = SubTokenType; }else if(token[0] == ‘*‘){ tokenType = MulTokenType; }else if(token[0] == ‘/‘){ tokenType = DivTokenType; }else if(token[0] == ‘(‘){ tokenType = LparamTokenType; }else if(token[0] == ‘)‘){ tokenType = RparamTokenType; } InsertToken(token,tokenType); } bool ParseInput(const std::string& input) { bool bRet = false; CALC_STATUS status = InitStatus; size_t begPos , endPos ; bool foundPoint = false; tokenDeque.clear(); for(size_t index= 0;index < input.size();++index){ switch(status){ case InitStatus: if(isspace(input[index])){ continue; }else if(isdigit(input[index])){ status = InNumberStatus; begPos = index; continue; }else if( IsIdent(input[index]) ){ status = InIdentStatus; begPos = index; continue; }else{ status = BadStatus; //std::cout << "parse bad input,index is " << index << std::endl; break; } break; case InNumberStatus: if(isdigit(input[index])){ status = InNumberStatus; continue; }else if(input[index]==‘.‘){ if(foundPoint){ status = BadStatus; //std::cout << "parse bad input,index is " << index << std::endl; break; } status = InNumberStatus; foundPoint = true; continue; }else if( IsIdent(input[index])){ endPos = index; InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType); begPos = index; status = InIdentStatus; foundPoint = false; continue; }else if(isspace(input[index])){ endPos = index; InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType); status = InitStatus; foundPoint = false; continue; } else{ status = BadStatus; break; } case InIdentStatus: endPos = index; InsertIdentToken(input.substr(begPos,endPos-begPos)); status = InitStatus; --index; continue; default: status = BadStatus; break; }//switch(status) }//for(size_t index= 0;index < input.size();++index) if(status != BadStatus && status != InitStatus){ endPos = std::string::npos; if(status == InNumberStatus) { InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType); }else if(status == InIdentStatus){ InsertIdentToken(input.substr(begPos,endPos-begPos)); } bRet = true; }else if(status == InitStatus){ bRet = true; } if(!bRet) tokenDeque.clear(); return bRet; } void PrintErrorMsg(const string& input){ std::cout << std::endl << "test error!!" << std::endl; std::cout << "input is " << input << "."<< std::endl; } void TestInput(const string& input,bool result,size_t tokenCount){ static int i = 1; if( ParseInput(input) != result) { PrintErrorMsg(input); std::cout << "result is not " << result << std::endl<< std::endl; }else if( tokenDeque.size() != tokenCount ){ PrintErrorMsg(input); std::cout <<"tokenCount is " <<tokenDeque.size() << " not " << tokenCount << std::endl <<std::endl; }else{ std::cout << i << "\ttimes test pass!" << std::endl; } i++; } bool GetNextToken(TOKEN_TUPLE& tokenTuple) { if(tokenDeque.empty()){ tokenTuple.t = BadTokenType; return false; } tokenTuple = tokenDeque.back(); tokenDeque.pop_back(); return true; } void UngetToken(const TOKEN_TUPLE& tokenTuple){ tokenDeque.push_back(tokenTuple); } bool ParsePression(double& value); bool ParsePrimaryExpression(double& value) { bool ret = false; bool minusFlag = false; TOKEN_TUPLE tt; GetNextToken(tt); if (tt.t == SubTokenType) { minusFlag = true; } else { UngetToken(tt); } GetNextToken(tt); if(tt.t == NumberTokenType){ value = std::stod(tt.s); }else if(tt.t == LparamTokenType){ if(!ParsePression(value)) return false; GetNextToken(tt); if(tt.t != RparamTokenType){ return false; } }else{ UngetToken(tt);//?? } if(minusFlag) value = -value; ret =true; return ret; } bool ParseTerm(double& value){ bool ret = false; double v1; double v2; TOKEN_TUPLE tt; if(!ParsePrimaryExpression(v1) ) return ret; for(;;){ GetNextToken(tt); if(tt.t != MulTokenType && tt.t != DivTokenType&&ret){ UngetToken(tt); break; } ParsePrimaryExpression(v2); if(tt.t == MulTokenType){ v1 = v1*v2; }else if(tt.t == DivTokenType){ if(v2 ==0.0) return ret; v1 = v1/v2; } } value = v1; ret = true; return ret; } bool ParsePression(double& value){ bool ret = false; double v1; double v2; TOKEN_TUPLE tt; if(tokenDeque.empty()) return ret; if(!ParseTerm(v1)) return ret; for(;;){ GetNextToken(tt); if(tt.t != AddTokenType && tt.t != SubTokenType){ UngetToken(tt); break; } ParseTerm(v2); if(tt.t == AddTokenType){ v1 = v1+v2; }else if(tt.t == SubTokenType){ v1 = v1-v2; }else{ UngetToken(tt); } } value = v1; ret = true; return ret; } int main(int argc, char *argv[]) { // std::string input; // cin >> input; // cout << input << endl; // TestInput("2",true,1); // TestInput("0.2",true,1); // TestInput("2 3",true,2); TestInput("2.467 + 3",true,3); double d; bool ret = ParsePression(d); // TestInput("()2.467 + 3",true,5); // TestInput("3.14 + ( 2.43-1) /3 *(2*6)",true,15); // TestInput(".()2.467 + 3",false,0); // TestInput("aas+2()2.467 + 3",false,0); // TestInput("2.46.7 + 3",false,0); // TestInput("2.4(6.7 + 3",true,5); return 0; }
显示结果
第二段
1 // 11111.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <string> 6 #include <iostream> 7 8 9 using namespace std; 10 11 std::string s1 = "2+3-2"; 12 std::string s2 = "2+3*3"; 13 std::string s3 = "2+(3*3)"; 14 std::string s4 = "()2+(3*3)"; 15 16 int gStringIndex = 0; 17 18 bool ParseExPression(const std::string& s, int& v); 19 20 #define ERROR_MSG 21 std::cerr << "Error. Func : " << __FUNCTION__ << ".\tLine : " << __LINE__ << std::endl; 22 std::cerr << "expression is " << s << ". error index is " << gStringIndex << std::endl; 23 exit(0); 24 25 26 bool ParsePrimaryExpression(const std::string& s, int& v) 27 { 28 bool minusFlag = false; 29 30 if (s[gStringIndex] == ‘-‘) { 31 minusFlag = true; 32 ++gStringIndex; 33 } 34 35 if (isdigit(s[gStringIndex])) { 36 std::string token = s.substr(gStringIndex, 1); 37 v = stoi(token); 38 gStringIndex++; 39 if (minusFlag) 40 v = -v; 41 return true; 42 } 43 else if (s[gStringIndex] == ‘(‘) 44 { 45 gStringIndex++; 46 if (!ParseExPression(s, v)) { 47 ERROR_MSG; 48 } 49 if (s[gStringIndex] == ‘)‘) { 50 gStringIndex++; 51 if (minusFlag) 52 v = -v; 53 return true; 54 } 55 } 56 else { 57 ERROR_MSG; 58 } 59 60 61 62 63 return false; 64 } 65 66 67 bool ParseTerm(const std::string& s, int& v) 68 { 69 int v1; 70 int v2; 71 char ident = 0; 72 73 if (!ParsePrimaryExpression(s, v1)) { 74 ERROR_MSG; 75 } 76 while (1) { 77 if (s[gStringIndex] != ‘*‘ && 78 s[gStringIndex] != ‘/‘) 79 { 80 break; 81 } 82 else { 83 ident = s[gStringIndex]; 84 ++gStringIndex; 85 } 86 87 if (!ParsePrimaryExpression(s, v2)) { 88 ERROR_MSG; 89 } 90 91 if (ident == ‘*‘) 92 { 93 v1 = v1*v2; 94 } 95 else if (ident == ‘/‘ && v2 != 0) { 96 v1 = v1 / v2; 97 } 98 else { 99 ERROR_MSG; 100 } 101 } 102 103 v = v1; 104 return true; 105 } 106 107 bool ParseExPression(const std::string& s, int& v) 108 { 109 int v1; 110 int v2; 111 char ident = 0; 112 113 114 if (!ParseTerm(s, v1)) { 115 ERROR_MSG; 116 } 117 118 while (1) { 119 if (s[gStringIndex] != ‘+‘ && 120 s[gStringIndex] != ‘-‘) 121 { 122 break; 123 } 124 else { 125 ident = s[gStringIndex]; 126 ++gStringIndex; 127 } 128 129 if (!ParseTerm(s, v2)) { 130 ERROR_MSG; 131 } 132 133 if (ident == ‘+‘) 134 { 135 v1 = v1+v2; 136 } 137 else if (ident == ‘-‘) { 138 v1 = v1 - v2; 139 } 140 else { 141 ERROR_MSG; 142 } 143 144 } 145 146 v = v1; 147 return true; 148 } 149 150 151 bool ParseInput(const std::string& s) 152 { 153 gStringIndex = 0; 154 int v; 155 if (!ParseExPression(s, v)) { 156 ERROR_MSG; 157 } 158 159 std::cout << s << " = " << v << endl; 160 161 162 return true; 163 } 164 165 int main() 166 { 167 ParseInput(s1); 168 std::cout << std::endl << std::endl; 169 170 ParseInput(s2); 171 std::cout << std::endl << std::endl; 172 173 ParseInput(s3); 174 std::cout << std::endl << std::endl; 175 176 ParseInput(s4); 177 std::cout << std::endl << std::endl; 178 179 return 0; 180 }
显示结果
2+3-2 = 3
2+3*3 = 11
2+(3*3) = 11
Error. Func : ParsePrimaryExpression. Line : 57
expression is ()2+(3*3). error index is 1
时间: 2024-10-27 19:37:40