Reputation: 3887
I am using std::regex r("-?[0-9]*(.[0-9]+)?(e-?[0-9]+)?")
to validate numbers (ints/fixed point/floating point). The MWE is below:
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <algorithm>
using namespace std;
bool isNumber(string s) {
// can ignore all whitespace
s.erase(remove(s.begin(), s.end(), ' '), s.end());
std::regex r("-?[0-9]*(.[0-9]+)?(e-?[0-9]+)?");
return regex_match(s, r);
}
int main() {
std::vector<string> test{
"3", "-3", // ints
"1 3", " 13", " 1 3 ", // weird spacing
"0.1", "-100.123123", "1000.12312", // fixed point
"1e5", "1e-5", "1.5e-10", "1a.512e4", // floating point
"a", "1a", "baaa", "1a", // invalid
"1e--5", "1e-", //invalid
};
for (auto t : test) {
cout.width(20); cout << t << " " << isNumber(t) << endl;
}
return 0;
}
I notice the compile time is quite large compared to what I was expecting:
gcc 5.4 -O0 -std=c++11
, 2.3 secondsgcc 5.4 -O2 -std=c++11
, 3.4 secondsclang++ 3.8 -O0 -std=c++11
, 1.8 secondsclang++ 3.8 -O2 -std=c++11
, 3.7 secondsI use this for an online judge submission, which has a time limit on the compilation stage.
So, the obivous questions:
Upvotes: 4
Views: 1148
Reputation: 38949
You can certainly lighten the computational load of your regex by appropriately escaping the decimal point: -?[0-9]*(\.[0-9]+)?(e-?[0-9]+)?
This will of course prevent you from returning a false positive on numbers like: "1 3" (don't worry that's a good thing those were 2 numbers.) But in this case and many others when you stoop to using regexes "Now you have 2 problems".
Using a istringstream
would provide a more specialized, robust solution to this problem:
bool isNumber(const string& s) {
long double t;
istringstream r(s);
return r >> t >> ws && r.eof();
}
Upvotes: 1