So I use atof to convert my string to double. But I need to know if I get wrong input (like y564 etc.). How can I check it? I need correct number for further actions with it.
double x = atof(s.c_str());
You might want to use std::stod:
bool parse_double(std::string in, double& res) {
try {
size_t read= 0;
res = std::stod(in, &read);
if (in.size() != read)
return false;
} catch (std::invalid_argument) {
return false;
}
return true;
}
int main()
{
double d;
bool b = parse_double("123z", d);
if (b)
std::cout << d;
else
std::cout << "Wrong input";
}
[edit]
You may find here:
Return value
double value corresponding to the contents of str on success. If the converted value falls out of range of the return type, the return value is undefined. If no conversion can be performed, 0.0 is returned.
so that makes it impossible to decide if input is wrong or it contains 0
.
Use std::stod
. It throws exceptions on invalid input. Or, if you insist on C solutions, use strtod
; it gives you more information about the result.
definition of atof(http://en.cppreference.com/w/cpp/string/byte/atof):
Return value
double value corresponding to the contents of str on success. If the converted value falls out of range of the return type, the return value is undefined. If no conversion can be performed, 0.0 is returned.
If you use modern c++ and you have to now the return, better use std::strtod
(http://en.cppreference.com/w/cpp/string/byte/strtof):
double strtod( const char* str, char** str_end );
and its return value is defined:
Return value
Floating point value corresponding to the contents of str on success. If the converted value falls out of range of corresponding return type, range error occurs and HUGE_VAL, HUGE_VALF or HUGE_VALL is returned. If no conversion can be performed, 0 is returned and *str_end is set to str.
Regular expressions (i.e. libpcre) to the rescue:
// checked_atof.cpp
#include <iostream>
#include <cstdlib>
#include <pcrecpp.h>
const char FP_RE[] = "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?";
using namespace std;
int main()
{
std:string s;
double number;
pcrecpp::RE fpre(FP_RE);
cout << "Enter a floating point number: " << endl;
cin >> s;
if (!fpre.FullMatch(s)) {
cout << "Sorry, not a valid floating point number!" << endl;
} else {
number = atof(s.c_str());
cout << "Ok, result: " << number << endl;
}
return 0;
}
For details regarding installation/compilation, please refer to libpcre
documentation -- the following may work on your system:
g++ checked_atof.cpp $(pkg-config --cflags libpcrecpp) $(pkg-config --libs libpcrecpp) -o checked_atof
$ ./checked_atof.exe
Enter a floating point number:
23.42
Ok, result: 23.42
$ ./checked_atof.exe
Enter a floating point number:
3.14159e-4
Ok, result: 0.000314159
$ ./checked_atof.exe
Enter a floating point number:
x9
Sorry, not a valid floating point number!
You could simply check if each character of your string is either a '.' or std::isdigit(int ch) before passing it to atof (and the '.' has to be unique)
More compact solution is to your string with a regular expression like ^[0-9]+(\.[0-9]+)?$
which should work for generic floating values.