Jump to content
  • Advertisement
Sign in to follow this  
ed209

Probably simple C++ question

This topic is 3920 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I an trying to input a variable with type double but don't know how to check to make sure the input is double and not something else. Could someone tell me how to do this?

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by PCosmin89
What about if(variable%1!=0)


Umm, no. Modular arithmetic only works on integral types (int, short, long, etc) in C++, and even if that was allowed, what if the value was 10.0?

Share this post


Link to post
Share on other sites
Quote:

What about if(variable%1!=0)

% is only valid for integers. This doesn't answer the question.

Quote:

Could someone tell me how to do this?

Presuming you are using std::cin for input, then just:

double d = 0.0;
std::cin >> d;

Now, if you want to make sure the user enters something that is, in fact, a double (in the above code if they enter somebody bogus you will get unexpected results), you must first read the input as a string, then parse it. boost::lexical_cast is great for this. If you don't have Boost, get it. Or use something like

bool is_double(const std::string &input)
{
std::istringstream marshaller(input);
double dummy;
marshaller >> dummy;
return !marshaller.fail();
}

Share this post


Link to post
Share on other sites
Quote:
Original post by jpetrie
Or use something like

bool is_double(const std::string &input)
{
std::istringstream marshaller(input);
double dummy;
marshaller >> dummy;
return !marshaller.fail();
}


This is actually no different from
double x;
if (cin >> x) {
// ok
}
else {
// bad
}


In that both will seem ok if the user enters something like "42asdf" -- x = 42, but "asdf" will still be left in the buffer. If you really need to verify that what the user entered is a real number and absolutely nothing else, that's kinda difficult. You can use atof, but that returns 0.0 in case of an error. So you'd have to compare it to the stringstream conversion result, to make sure that the user didn't actually enter 0.

Share this post


Link to post
Share on other sites
How about...


// Evaluates whether a "C" string is a real.
bool isReal(const char ch[])
{
unsigned i = 0;
bool has_point = false, has_sign = false;
while ( ch != '\0' )
{
// Look for a digit.
if ( !std::isdigit(ch) )
{
switch (ch)
{
case '.':
if ( has_point == true )
{
// Oops, allowed one occurrence.
return false;
}
else
{
// Found the first point.
has_point = true;
}
break;
case '-':
if ( has_sign == true )
{
// Oops, allowed one occurrence.
return false;
}
else
{
// Found the first sign.
has_sign = true;
}
break;
case '+':
if ( has_sign == true )
{
// Oops, allowed one occurrence.
return false;
}
else
{
// Found the first sign.
has_sign = true;
}
break;
default:
// Oops, no number, no point, no minus, no plus.
return false;
}
}
++i;
}

// Has point, sign and at least one number.
if ( has_point && has_sign && i > 2 )
return true;

// Has point and at least one number.
if ( has_point && i > 1 )
return true;

// Has number, but nothing else.
return false;
}






Rules:

1. Can have either a + or - sign or none, but not both signs, or it fails.
2. Must have decimal point, or else assumed to be an integer, and it fails.
3. Must have at least one digit, or it fails.
4. If it has anything other than +/-, digits and a point, then it fails.

--random

Share this post


Link to post
Share on other sites
Quote:
Original post by random_thinker
How about...

*** Source Snippet Removed ***

Rules:

1. Can have either a + or - sign or none, but not both signs.
2. Must have decimal point, or else assumed to be an integer.
3. Must have at least one number.
4. If it has anything other than +/-, digits and a point, then it fails.

--random


Consider:
45.+0

Share this post


Link to post
Share on other sites
Quote:
Original post by drakostar
Quote:
Original post by jpetrie
Or use something like

bool is_double(const std::string &input)
{
std::istringstream marshaller(input);
double dummy;
marshaller >> dummy;
return !marshaller.fail();
}


This is actually no different from
*** Source Snippet Removed ***
In that both will seem ok if the user enters something like "42asdf" -- x = 42, but "asdf" will still be left in the buffer. If you really need to verify that what the user entered is a real number and absolutely nothing else, that's kinda difficult. You can use atof, but that returns 0.0 in case of an error. So you'd have to compare it to the stringstream conversion result, to make sure that the user didn't actually enter 0.


It is quite different. Your one tries to interpret a double straight from std::cin, which if it fails you must reset the streams state and possibly ignore characters from the stream. I prefer to read in a string and then do the conversion as a separate step.

@random_thinker

what about "3E-3". Also, why not std::string?

Share this post


Link to post
Share on other sites
If you want to check that there are no additional characters left in the string after reading the double, you can add a check to jpetrie's solution:

bool is_double(const std::string &input) {
std::istringstream marshaller(input);
double dummy;
marshaller >> dummy;
return !marshaller.fail() && (marshaller.rdbuf()->in_avail() == 0);
}

Share this post


Link to post
Share on other sites
Quote:

Consider:
45.+0


Quote:

what about "3E-3". Also, why not std::string?


Good points, could alter the logic to allow signs only at the beginning of the sequence to solve this potential problem. However, it is a lightweight and reliable approach even though it's very C-like. I couldn't be bothered to permit 'E-3' type constructs.

Could use std::string if you wanted, with a few alterations. I have used this primarily with std::getline() and feed the resulting string.c_str() to it.

--random

What about something like:


// Declare a double.
double d=0;

// Reference character set.
const std::string double_chars("0123456789Ee-+.");

// Make a cache.
std::string cache;

// Fill the cache.
std::getline(std::cin,cache);

// Check for any non-double characters.
if (cache.find_first_not_of(double_chars) == std::string::npos)
{
// All characters are in reference set.
d=strtod(cache.c_str(),0);
}
else
{
// Fail.
}





[Edited by - random_thinker on September 28, 2007 5:56:17 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!