Reputation: 2634
I have three variable declared as doubles:
double Delay1 = 0;
double Delay2 = 0;
double Delay3 = 0;
I Then get their values from the user:
cout << "Please Enter Propogation Delay for Satellite #1:";
cin >> Delay1;
...
But when I check these values to see if they are null (user just hit enter and did not put a number) it doesn't work:
if(Delay1 || Delay2 || Delay3 == NULL)
print errror...
This runs every time.
What is the proper way to check if an input that has been declared a double is blank?
Upvotes: 3
Views: 6646
Reputation: 224079
The way to check if stream input worked is to test the stream:
if(!std::cin) throw "Doh!";
Since operator>>
always returns its left argument, this works, too:
if( std::cin >> Delay1 )
good();
else
bad();
Input streams will not alter the value if inputting fails. In your case, they will thus keep the random values they had before. You should never accept input without having checked the stream.
Upvotes: 3
Reputation: 507005
Something like
cin >> Delay1;
if(cin) { ... }
won't work according to your specification, because cin
will skip leading whitespace. The user can't just hit enter. He first has to enter some text. If he enters the following
3a
Then the input is read into the double, up to a
, where it stops. cin
won't find anything wrong, and leaves a
in the stream. Often, this is enough error handling, i think. But if it's a requirement that you want to actually repeat when the user enters something like above, then you need a bit more code.
If you want to test whether the whole input up to the newline is a number, then you should use getline
, read into a string and then try to convert to a number
string delay;
if(!getline(std::cin, delay) || !isnumber(delay)) {
...
}
The isnumber
function can use a stringstream to test the string
bool isnumber(string const &str) {
std::istringstream ss(str);
double d;
// allow leading and trailing whitespace, but no garbage
return (ss >> d) && (ss >> std::ws).eof();
}
The operator>>
will eat leading whitespace, and std::ws
will consume trailing whitespace. If it hits to the end of the stream, it will signal eof
. This way, you can signal the error to the user immediately, instead of erroring out at the next time you try to read from cin
.
Write a similar function that returns the double or pass the address of a double to `isnumber, so that it can write the result in case of a successful parse.
It's also worth to have a look at the various error flags and how they relate to operator void*
, operator!
, good()
, fail()
, bad()
and eof()
which can be quite confusing:
flag | badbit | failbit | eofbit
function | | |
-----------------+---------+-----------+--------
op void* | x | x |
-----------------+---------+-----------+--------
op ! | x | x |
-----------------+---------+-----------+--------
good() | x | x | x
-----------------+---------+-----------+--------
fail() | x | x |
-----------------+---------+-----------+--------
bad() | x | |
-----------------+---------+-----------+--------
eof() | | | x
-----------------+---------+-----------+--------
There is an x
if the respective bit influences the result. operator void*
is used when converting to bool
(if(cin) ...
) while operator!
is used for code doing !cin
Upvotes: 11
Reputation: 76660
What you need to check is the state of the input stream after you try to read in the double.
For example
cin >> Delay1;
if (!cin.fail()) {
// Input was a double
} else {
// Input was something that could not be interpreted as a double
}
You can write this more tersely as follows
if (cin >> Delay1) {
// Input was a double
} else {
// Input was something that could not be interpreted as a double
}
If the input fails, the value of Delay1 will not change, and so if you have not previously initialized it, it will be some arbitrary value. As has been pointed out, though, it will not become "NULL", since only pointers can be null, not value-types.
Upvotes: 3
Reputation: 73443
Your if condition is wrong. if(Delay1 || Delay2 || Delay3 == NULL)
will be true if Delay is not equal to zero or delay2 is not equal to zero or Delay3 is zero. Surely that is not what you want. Also you should use 0 for primitive data types. Further, comparing the double values to an absolute value is always dangerous. You check whether the value is less than a small epsilon value.
Upvotes: 2
Reputation: 96869
std::cout << "Enter doubles: ";
std::cin >> d1 >> d2 >> d3;
if(std::cin.fail())
{
// error!
}
Upvotes: 4
Reputation: 90442
just use the stream state, it will be in a fail state if it couldn't read a double.
if(!(std::cin >> Delay1 >> Delay2 >> Delay3)) {
// error
}
Upvotes: 1
Reputation: 200806
There's multiple things going wrong here.
First: to check whether parsing failed, use if (cin.fail()) { /* print error */ }
.
Second: Delay1 || Delay2 || Delay3
will convert doubles to boolean values, and then logical-OR them together.
Third: == NULL
will compare your boolean value (in this case false
) to the pointer value NULL
. I believe that this will always be true
.
Upvotes: 2
Reputation: 13908
I think you need to read the variable in as a string, then check to see if it's blank, then convert it to a double (and check if it's a valid double - the user might just have typed "hello").
Upvotes: 0