题目要求:
Validate if a given string is numeric.
Some examples: "0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
这道题看起来貌似简单,实则要考虑的情况非常多。更可惜的是LeetCode并不支持正则表达式。。。。下文先试着以正则表达式的方法去解决这个问题。
C++现在是提供了对正则表达式的支持的,但貌似用的少,更多的是Boost库提供的正则表达式。
法一和法二的测试用例来自一博文,且这两个方法均测试通过。测试用例可从百度云下载得到。另外,具体的文件读写及函数验证程序如下:
1 #include <fstream> 2 ... ... 3 ifstream in("C:\Users\xiehongfeng100\Desktop\LeetCode_Valid_Number_Test_Cases.txt"); 4 if (in) // if file exists 5 { 6 string line; 7 while (getline(in, line)) // read each line from 'in' 8 { 9 string input; 10 bool expect; 11 12 // extract 'input' 13 line.erase(0, 1); 14 int tmpFind = line.find('"'); 15 input = line.substr(0, tmpFind); 16 while (input.begin() != input.end() && input.front() == ' ') 17 input.erase(input.begin()); 18 while (input.begin() != input.end() && input.back() == ' ') 19 input.pop_back(); 20 21 // extract 'expect' 22 string expectStr = line.substr(tmpFind + 2, line.size() - line.find(' ', tmpFind + 2) - 1); 23 if (expectStr == "TRUE") 24 expect = true; 25 else 26 expect = false; 27 28 // validate 29 bool isValid = isNumber(input); 30 if (isValid != expect) 31 cout << "Something wrong! " << line << endl; 32 } 33 } 34 else 35 { 36 cout << "No such file" << endl; 37 }
1. 法一:基于C++自身正则表达式
用正则表达式写出来的程序非常简洁:
1 #include <regex> 2 ... ... 3 bool isNumber(string buf) 4 { 5 regex pattern("[+-]?(\.[0-9]+|[0-9]+\.?)[0-9]*(e[+-]?[0-9]+)?", regex_constants::extended); 6 match_results<string::const_iterator> result; 7 return regex_match(buf, result, pattern); 8 }
2. 法二:基于Boost库正则表达式
Boost库的正则表达式的语法跟C++自身提供的有点差别。Boost库的跟其他语言更加兼容。
1 #include <boost/regex.hpp> 2 ... ... 3 bool isNumber(string buf) 4 { 5 string Reg = "[+-]?(\.\d+|\d+\.?)\d*(e[+-]?\d+)?"; 6 boost::regex reg(Reg); 7 return boost::regex_match(buf, reg); 8 }
3. 法三:列举所有情况
这种方法很繁杂。。。
1 class Solution { 2 public: 3 bool isValidChar(char c) 4 { 5 string str = "0123456789.e+-"; 6 return str.find(c) != -1; 7 } 8 9 bool isDigit(int in) 10 { 11 char ref[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; 12 for (int i = 0; i < 10; i++) 13 { 14 if (in == ref[i]) 15 return true; 16 } 17 return false; 18 } 19 20 bool isNumber(string s) { 21 // clear spaces 22 while (s.begin() != s.end() && s.front() == ' ') 23 s.erase(0, 1); 24 while (s.begin() != s.end() && s.back() == ' ') 25 s.pop_back(); 26 27 int szS = s.size(); 28 if (szS == 0) 29 return false; 30 // only '.' 31 if (szS == 1 && s[0] == '.') 32 return false; 33 // 'e' at the first or last position of s 34 if (s[0] == 'e' || s[szS - 1] == 'e') 35 return false; 36 // too many signs 37 if (szS > 1 && (s[0] == '-' || s[0] == '+') && (s[1] == '-' || s[1] == '+')) 38 return false; 39 // sign at the last 40 if (s[szS - 1] == '+' || s[szS - 1] == '-') 41 return false; 42 43 szS = s.size(); 44 int countDot = 0; 45 int countE = 0; 46 for (int i = 0; i < szS; i++) 47 { 48 if (!isValidChar(s[i])) 49 return false; 50 51 if (s[i] == '.') //'.e at the begining, ' '.+/-' are not allowed 52 { 53 countDot++; 54 if (i + 1 < szS && ((i == 0 && s[i + 1] == 'e') || s[i + 1] == '+' || s[i + 1] == '-')) // '.e' 55 return false; 56 } 57 if (s[i] == 'e') // 'e.' 'e+/-...+/-' are not allowed 58 { 59 countE++; 60 if (i + 1 < szS) 61 { 62 int pos1 = s.find('.', i + 1); 63 if (pos1 != -1) 64 return false; 65 } 66 if (i + 2 < szS) 67 { 68 int pos2 = s.find('+', i + 2); 69 int pos3 = s.find('-', i + 2); 70 if (pos2 > (i + 1) || pos3 > (i + 1)) 71 return false; 72 } 73 } 74 if (s[i] == '+') // '+e' '+-' 'digit+/' are not allowed 75 { 76 if (i + 1 < szS && (s[i + 1] == 'e' || s[i + 1] == '-')) 77 return false; 78 if (i > 0 && isDigit(s[i - 1])) 79 return false; 80 } 81 if (s[i] == '-') // '. at the last' '-e' '-+' 'digit+/' are not allowed 82 { 83 if (i + 1 < szS && ((i + 1 == szS - 1 && s[i + 1] == '.') || s[i + 1] == 'e' || s[i + 1] == '+')) 84 return false; 85 if (i > 0 && isDigit(s[i - 1])) 86 return false; 87 } 88 89 if (countDot > 1 || countE > 1) // no double dots or double e can exit 90 return false; 91 92 } 93 94 return true; 95 } 96 };