2

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());
Paul R.
  • 23
  • 1
  • 3

5 Answers5

8

You might want to use std::stod:

[live]

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.

Community
  • 1
  • 1
marcinj
  • 48,511
  • 9
  • 79
  • 100
3

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
2

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.

Community
  • 1
  • 1
goeddek
  • 109
  • 1
  • 7
  • How do you tell if the text "0.0" is converted correctly? – Thomas Matthews Nov 28 '16 at 16:44
  • @ThomasMatthews: you cant, thats why atof is not the best fct. and most of the answers did recommend different functions with better return values... – goeddek Nov 28 '16 at 17:10
  • I believe you check if `result == 0.0 && str_end == str` and then that will tell you that it failed. Only, of course, if `str != str_end` before calling the function. – Merlyn Morgan-Graham Mar 19 '21 at 21:14
0

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!
Christoph2
  • 143
  • 1
  • 6
-1

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.

  • 1
    This is wrong. It can also start with a whitespace, have a plus or a minus sign, have a binary prefix, have a decimal or a binary exponent, be one of inf, nan, nan(...) etc... – Yakov Galka Nov 28 '16 at 14:08
  • You're right, better using std::stod or similar for generic inputs instead. – Nicola Pellicanò Nov 28 '16 at 14:12