I can't take credit for this solution, though it's a good one, see this SO post. For those too lazy to skip over, the author recommends using a locale to treat all non-numeric digits as whitespace. It might be overkill for your solution but the idea is easily adaptable. Instead of all non-numeric, you could just use "-" as your whitespace. Here's his code, not mine. Please, if you like this give him the upvote.
struct digits_only: std::ctype<char>
{
digits_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
return &rc[0];
}
};
bool in_range(int lower, int upper, std::string const &input) {
std::istringstream buffer(input);
buffer.imbue(std::locale(std::locale(), new digits_only()));
int n;
while (buffer>>n)
if (n < lower || upper < n)
return false;
return true;
}
Then just remove the whitespace and pass the string to atof
.