LeetCode之“字符串”:Valid Number(由此引发的对正则表达式的学习)

  题目链接

  题目要求: 

  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('\t', 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 }
View Code

  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 };
View Code

 

posted @ 2015-06-05 22:09  峰子_仰望阳光  阅读(421)  评论(0编辑  收藏  举报