个人的小程序需要匹配一些简单的通配符,如*?之类。抽时间写了一个
1 #pragma once 2 #ifndef CHECKER 3 #define CHECKER 4 5 #include <iostream> 6 #include <string> 7 #include <sstream> 8 using namespace std; 9 10 class Checker 11 { 12 public: 13 Checker(void){} 14 ~Checker(void){} 15 16 // 匹配模式 17 enum MatchMode 18 { 19 // 全部匹配 20 ALL, 21 // 任意匹配 22 ANY, 23 // 都不匹配 24 NONE 25 }; 26 27 // 是否匹配 28 int isMatch(string input, string* patterns, int pLen, MatchMode mode){ 29 istringstream ss = istringstream(input); 30 int matchOne = 0; 31 istringstream ssPattern; 32 switch (mode) 33 { 34 case Checker::ALL: 35 for (int i = 0; i < pLen; i++) 36 { 37 matchOne = isMatch(ss, ssPattern); 38 if(!matchOne) 39 return false; 40 } 41 return true; 42 case Checker::ANY: 43 for (int i = 0; i < pLen; i++) 44 { 45 matchOne = isMatch(ss, ssPattern); 46 if(matchOne) 47 return true; 48 } 49 return false; 50 case Checker::NONE: 51 for (int i = 0; i < pLen; i++) 52 { 53 matchOne = isMatch(ss, ssPattern); 54 if(matchOne) 55 return false; 56 } 57 return true; 58 default: 59 return false; 60 } 61 } 62 63 // 是否匹配 64 int isMatch(string input, string pattern){ 65 istringstream ss = istringstream(input); 66 istringstream ssPattern = istringstream(pattern); 67 return isMatch(ss, ssPattern); 68 } 69 70 // 是否匹配 71 int isMatch(istream &input, istream &pattern) 72 { 73 char left,right; 74 while (Token t = getToken(pattern, false)) 75 { 76 switch (t) 77 { 78 case END: 79 return true; 80 case CONT: 81 if(!pattern.get(right)) 82 return true; 83 input.get(left); 84 if(left != right) 85 return false; 86 break; 87 case STAR: 88 { 89 t = getToken(pattern, true); 90 if(t != CONT){ 91 if(!isMatch(input, pattern)) 92 return false; 93 break; 94 }else{ 95 if(!pattern.get(right)) 96 return true; 97 int flag = 0; 98 while (input.get(left)) 99 { 100 if(flag = (left == right)) 101 break; 102 } 103 // cant't find match till end of file 104 // i.e "abcd" didn't match "*e" 105 if(input.eof() && !flag) 106 return false; 107 else 108 break; 109 } 110 } 111 case QUS: 112 { 113 t = getToken(pattern, true); 114 if(t != CONT){ 115 if(!isMatch(input, pattern)) 116 return false; 117 break; 118 }else{ 119 if(!pattern.get(right)) 120 return true; 121 // skip one char 122 input.get(left).get(left); 123 if(left != right) 124 return false; 125 break; 126 } 127 } 128 case SPEC: 129 { 130 SymbolToken simbol = getSimbol(pattern); 131 switch (simbol) 132 { 133 case SBL_POS_INT: 134 { 135 int num = getInt(input); 136 if(num < 0){ 137 cerr << "Error : only positive int is supported."; 138 return false; 139 } 140 break; 141 } 142 case SBL_REAL: 143 { 144 double num; 145 if(!(input >> num)) 146 cerr << "Error : failed in parsing input into double."; 147 break; 148 } 149 case SBL_WRD: 150 { 151 if(!input.get(left)) 152 return false; 153 if(!isalpha(left)) 154 return false; 155 break; 156 } 157 case SBL_SLASH: 158 { 159 if(!input.get(left)) 160 return false; 161 if(left != '\') 162 return false; 163 break; 164 } 165 default: 166 cerr << "Error : simbol expected."; 167 return false; 168 } 169 } 170 default: 171 break; 172 } 173 } 174 return true; 175 } 176 177 private: 178 // 令牌 179 enum Token 180 { 181 // 结束 182 END, 183 // 内容 184 CONT, 185 // 通配符* 186 STAR = '*', 187 //通配符? 188 QUS = '?', 189 //转义符 190 SPEC = '\', 191 }; 192 193 enum SymbolToken 194 { 195 // 结束 196 UNKNOWN, 197 // 正整数 198 SBL_POS_INT = 'd', 199 // 字符 200 SBL_WRD = 'w', 201 // 实数 202 SBL_REAL = 'r', 203 // 转义符 204 SBL_SLASH = '\' 205 }; 206 207 // 获取符号令牌 208 SymbolToken getSimbol(istream& stream){ 209 char c = 0; 210 if(!stream.get(c)) 211 return UNKNOWN; 212 return SymbolToken(c); 213 } 214 215 // 获取正整数 216 int getInt(istream& stream){ 217 char c; 218 int result = 0; 219 while (stream.get(c) && c >= '0' && c <='9') 220 { 221 result = result*10 + c - '0'; 222 } 223 stream.putback(c); 224 return result; 225 } 226 227 // 获取令牌 228 Token getToken(istream& stream, bool putback){ 229 char c = 0; 230 if(!stream.get(c)) 231 return END; 232 Token result; 233 switch (c) 234 { 235 case '*':case '?':case '\': 236 result = Token(c); 237 if(putback) 238 stream.putback(c); 239 break; 240 default: 241 stream.putback(c); 242 result = CONT; 243 } 244 return result; 245 }; 246 247 int isMatch(istream &input, istream &pattern){ 248 char left; 249 SymbolToken simbol = getSimbol(pattern); 250 switch (simbol) 251 { 252 case SBL_POS_INT: 253 { 254 int num = getInt(input); 255 if(num < 0){ 256 cerr << "Error : only positive int is supported."; 257 return false; 258 } 259 break; 260 } 261 case SBL_REAL: 262 { 263 double num; 264 if(!(input >> num)) 265 cerr << "Error : failed in parsing input into double."; 266 break; 267 } 268 case SBL_WRD: 269 { 270 if(!input.get(left)) 271 return false; 272 if(!isalpha(left)) 273 return false; 274 break; 275 } 276 case SBL_SLASH: 277 { 278 if(!input.get(left)) 279 return false; 280 if(left != '\') 281 return false; 282 break; 283 } 284 default: 285 cerr << "Error : simbol expected."; 286 return false; 287 } 288 } 289 }; 290 #endif
测试代码段:
Checker c; string input,pattern; while (cin) { cout << endl; cin >> input; cin >> pattern; cout << c.isMatch(input , pattern); }