[C++] Numeric data validation

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
tipo test
Posts: 66
Joined: Sun May 23, 2010 12:15 pm UTC

[C++] Numeric data validation

Postby tipo test » Thu Jan 06, 2011 8:03 pm UTC

Hi there I'm new on C++, I have some previous experience with other languages, all of them interpreted. If I wanted to read a number from keyboard for example, I'd declare a string, then check if it has numeric format and then convert that string to an int/double/whatever. 'Numeric' format includes of course negative numbers and decimal points... I'd have no problem on writing my own function for this (apparently there's no such thing on the standard C/C++ libraries?) but apparently converting strings etc is VB-like thinking, how do you read your stuff then?

edit - thanks in advance!

Sagekilla
Posts: 382
Joined: Fri Aug 21, 2009 1:02 am UTC
Location: Long Island, NY

Re: [C++] Numeric data validation

Postby Sagekilla » Thu Jan 06, 2011 8:26 pm UTC

I don't know who told you that "converting strings into numbers" is VB-like thinking, since that's a pretty standard thing.

I would create a getNumeric() function, that's what I did when I took my C++ class at my uni. I wrote something along these lines:

Code: Select all

bool getNumeric(double &num)
{
    string data;
    cin >> data;
   
    bool isValid = do_check_here(data);
   
    if (isValid)
    {
        num = atof(data);
        return true;
    }
   
    else
        return false;
}


You can use exceptions too, it's up to you.

Then you can just create different signatures for if you want a float, int, long, etc.
http://en.wikipedia.org/wiki/DSV_Alvin#Sinking wrote:Researchers found a cheese sandwich which exhibited no visible signs of decomposition, and was in fact eaten.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: [C++] Numeric data validation

Postby Yakk » Thu Jan 06, 2011 8:45 pm UTC

Code: Select all

 #include <sstream>
 double string_to_double( const std::string& s )
 {
   std::istringstream i(s);
   double x;
   if (!(i >> x))
     return 0;
   return x;
 }

From here:
http://stackoverflow.com/questions/3929 ... ouble-in-c

Here we pull off a cute trick. We take our string (a std::string, because raw char*s are a bad habit in most cases), stuff it into a stringstream (which is both a string and a stream! Together at last!), use the output operator of the string stream to take the data and shove it into a double, check for success, return 0 if it failed.

Here is a rewritten version:

Code: Select all

template<typename output>
bool convert_from_string( const std::string& input, output& out )
{
   std::istringstream i(s);
   if (!(i >> out ))
     return false;
   return true;
}

template<typename output>
bool convert_from_string( const std::string& input )
{
  output tmp;
  return convert_from_string( input, tmp );
}

This uses a less basic C++ feature called "templates" to get the compiler to generate type-specific code based on the type we pass into the function, has a return value for success/failure. If you don't pass in an output type, you can call convert_from_string<output>( "foo" ) which will tell you if it works, where output is the type of the value you want to convert to.

Now, all of these convert to a specific numerical format. There are no "standard" arbitrary precision numerical formats in C++. Doubles, for example, are 64 bit floating point values (called doubles because they are double the precision of the "standard" 32-bit floating point value at the time C was created).

There are many non-standard arbitrary precision numerical formats. I cannot recommend something with confidence to you.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: [C++] Numeric data validation

Postby sourmìlk » Thu Jan 06, 2011 9:07 pm UTC

This is what I do. It is almost certainly a non-optimal solution. It's similar to sagekilla's.

Code: Select all


bool getNumber
(double &num)
{
    string input;
    cin >> input;

    try
    
{
        num = atof(input.c_str()); //sometimes the compiler makes me convert the string to a c string to use the atof function
    }
    catch (...) //you could specify the kind of exception, but there's really only going to be one kind. And you want to return false if it fails any way.
    {
        return false;
    }

    return true;
}
 


Do that. It sets the num address to contain the input value, and returns false if it fails and true if it succeeds.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
tipo test
Posts: 66
Joined: Sun May 23, 2010 12:15 pm UTC

Re: [C++] Numeric data validation

Postby tipo test » Thu Jan 06, 2011 9:20 pm UTC

Hey cheers for the replies! I'd want to research and try some things before answering properly haha.

See you

User avatar
Sc4Freak
Posts: 673
Joined: Thu Jul 12, 2007 4:50 am UTC
Location: Redmond, Washington

Re: [C++] Numeric data validation

Postby Sc4Freak » Thu Jan 06, 2011 10:10 pm UTC

Okay, first of all, do not use atof. atof is a legacy C function that's unsafe and gives you no way to detect an error, making it completely and utterly useless for data validation. Upon error, atof returns 0.0, which is indistinguishable from a legitimate output of 0.0. In C++ you have absolutely no reason to be using atof, you should be using stringstreams or (better yet) boost::lexical_cast.

sourmìlk wrote:This is what I do. It is almost certainly a non-optimal solution. It's similar to sagekilla's.

Code: Select all


bool getNumber
(double &num)
{
    
string input;
    
cin >> input;

    try
    {
        
num atof(input.c_str()); //sometimes the compiler makes me convert the string to a c string to use the atof function
    
}
    catch (...) 
//you could specify the kind of exception, but there's really only going to be one kind. And you want to return false if it fails any way.
    
{
        return 
false;
    }

    return 
true;
}
  


Do that. It sets the num address to contain the input value, and returns false if it fails and true if it succeeds.

atof does not throw an exception. Your code will never detect an error condition, and due to the way atof works, it never will.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: [C++] Numeric data validation

Postby Yakk » Thu Jan 06, 2011 10:15 pm UTC

I should post the dog-simple version, and fix the bug:

Code: Select all

bool convert_from_string( const std::string& input, double& out )
{
   // create a stream wrapping out value input
   std::istringstream ss(input);
   // use the out-stream operator on the string stream to extract a double
   // store this value in out
   if (!(ss >> out ))
   // detect failure -- if so, return false:
     return false;
   return true;
}
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: [C++] Numeric data validation

Postby sourmìlk » Fri Jan 07, 2011 12:08 am UTC

atof is a legacy C function that's unsafe and gives you no way to detect an error


This is good to know. Do not use my method. I think the reason I once used atof is because 0 wasn't valid input for my program anyways.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
tipo test
Posts: 66
Joined: Sun May 23, 2010 12:15 pm UTC

Re: [C++] Numeric data validation

Postby tipo test » Sat Jan 08, 2011 8:32 pm UTC

1.- About using exceptions, can I do something like this -without using strings-? It's not working.

Code: Select all

int A;
cout << "Enter a number.\n";
try{
   cin >> A;
} catch (...) {
   cout << "The number has to be an integer.";
}

2.-
Sagekilla wrote:

Code: Select all

bool getNumeric(double &num)
{
    string data;
    cin >> data;
   
    bool isValid = do_check_here(data);
   
    if (isValid)
    {
        num = atof(data);
        return true;
    }
   
    else
        return false;
}


I really don't understand in what context would you use this function...? Why is double &num an argument?

3.-
Yakk wrote:

Code: Select all

 #include <sstream>
 double string_to_double( const std::string& s )
 {
   std::istringstream i(s);
   double x;
   if (!(i >> x))
     return 0;
   return x;
 }


I think I understand how does this solution work but what if I need all the double range to be valid, including zero?

greetings

-V

User avatar
sourmìlk
If I can't complain, can I at least express my fear?
Posts: 6393
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong
Contact:

Re: [C++] Numeric data validation

Postby sourmìlk » Sat Jan 08, 2011 8:34 pm UTC

tipo test wrote:I really don't understand in what context would you use this function...? Why is double &num an argument?


It's an argument because the function's return value is a boolean (based on whether the function was successful or not), so it needs another method with which to set a double value.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: [C++] Numeric data validation

Postby Yakk » Sat Jan 08, 2011 8:43 pm UTC

My most recent post has the "returns a bool, takes a string and modifies a double" version that can distinguish between a double that is 0, and invalid input.

---

Do you know what this means:

Code: Select all

void function( double& argument );

and how it differs from this:

Code: Select all

void function( double argument );

?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
tipo test
Posts: 66
Joined: Sun May 23, 2010 12:15 pm UTC

Re: [C++] Numeric data validation

Postby tipo test » Sun Jan 09, 2011 12:39 pm UTC

I think I understand those solutions now. If you want to read a double N, you set 0.0 (or any other number) as a defaut value so you can send it as an argument, by reference. But you only accept the new value for N if the function returns true, otherwise you loop it, for example.

thanks!

btw, what about my first question? :)

tipo test wrote:1.- About using exceptions, can I do something like this -without using strings-? It's not working.

Code: Select all

int A;
cout << "Enter a number.\n";
try{
   cin >> A;
} catch (...) {
   cout << "The number has to be an integer.";
}

User avatar
Yakk
Poster with most posts but no title.
Posts: 11128
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: [C++] Numeric data validation

Postby Yakk » Sun Jan 09, 2011 2:34 pm UTC

What do you mean "without using strings"? Without a prompt or anything?
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Token
Posts: 1481
Joined: Fri Dec 01, 2006 5:07 pm UTC
Location: London

Re: [C++] Numeric data validation

Postby Token » Sun Jan 09, 2011 2:52 pm UTC

tipo test wrote:1.- About using exceptions, can I do something like this -without using strings-? It's not working.

Code: Select all

int A;
cout << "Enter a number.\n";
try{
   cin >> A;
} catch (...) {
   cout << "The number has to be an integer.";
}

That won't work because by default, exception throwing for istream objects (like std::cin) is turned off. What will happen is that imstead cin's failbit flag will be set (which you can check by calling cin.fail()). If you want to turn exceptions on, you'll need to call cin.exceptions(istream::failbit). This will throw an exception every time the failbit flag is set.
All posts are works in progress. If I posted something within the last hour, chances are I'm still editing it.

User avatar
tipo test
Posts: 66
Joined: Sun May 23, 2010 12:15 pm UTC

Re: [C++] Numeric data validation

Postby tipo test » Sun Jan 09, 2011 5:01 pm UTC

Yakk wrote:What do you mean "without using strings"? Without a prompt or anything?

I meant not converting strings to numeric types but reading directly ints, doubles, etc with cin*... Following Token's advice I added cin.exceptions(istream::failbit) to main (if that's right?), this almost works:

Code: Select all

int _tmain(int argc, _TCHAR* argv[])
{
   cin.exceptions(istream::failbit);
   int A;
   cout << "Enter a number.\n";
   try{
      cin >> A;
   } catch (...) {
   cout << "The number has to be an integer.";
   }
   fflush(stdin);
   cin.get();
   return 0;
}


Right after I can read "The number has to be an integer." Visual C++ interrupts the program due to an uncontrolled exception.

*I like how your dog-simple solution works, I'm just being curious hehe.

User avatar
sparkyb
Posts: 1091
Joined: Thu Sep 06, 2007 7:30 pm UTC
Location: Camberville proper!
Contact:

Re: [C++] Numeric data validation

Postby sparkyb » Wed Jan 26, 2011 1:45 pm UTC

I agree that atof is bad, but I've also never liked the C++ stream/io classes that overload the shift operator so badly (so badly I almost see why Java doesn't allow operator overloading). I use strtod (or strtol if I want to do integers) do this:

Code: Select all

bool parseFloat(const char* val, double& ret) {
   char* end;
   if (!val || val[0]=='\0')
      return false;
   ret = strtod(val,&end);
   return (*end=='\0' && end!=val);
}


Basically what's happening is that strtod works a bit like atof except that if it finds characters it doesn't understand it just returns what it has so far instead of zero. But the important thing is that it also returns (via an out parameter) the place in the string where it stopped parsing. So my conversion fails (returns false) if the string is null, empty, or doesn't parse up to the null character at the end of the string.

sigmaman
Posts: 12
Joined: Thu Dec 04, 2008 12:05 am UTC

Re: [C++] Numeric data validation

Postby sigmaman » Wed Jan 26, 2011 3:10 pm UTC

sparkyb wrote:I agree that atof is bad, but I've also never liked the C++ stream/io classes that overload the shift operator so badly (so badly I almost see why Java doesn't allow operator overloading). I use strtod (or strtol if I want to do integers) do this:


Bad is so relative. Why do you think its bad? Because it doesn't implement a "shift?"

I propose that my that same logic, you should never use a + to concatenate strings (addition is not concatenation!), or even be allowed to use the * for multiplication and pointer dereferencing (just because one is an unary operator and the other isn't doesn't mean they should be allowed to do different things with the same symbol!) I personally don't mind the streams using the >> and << operators because while it doesn't make a whole lot of sense, it seems to work pretty well.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 10 guests