Why does it look like that cin converts my double

2019-03-05 19:17发布

问题:

I have the following code:

//...
int variable_1, variable_2;
cout << "Please enter the 2 numbers: ";

try
{   
    if ( !(cin >> variable_1) ) throw Invalid_number(); //empty class just for exceptions
    if ( !(cin >> variable_2) ) throw Invalid_number(); //problem is here.
}
catch (Invalid_number) {cerr << "You must enter integers\n"; return -1;}
//...

So if I enter an integer for variable_1 and a double for variable_2, the programme doesn't throw the exception, it just continues executing the rest of the programme. From debugging I saw that when I enter a double variable_2 i.e 2.4 it just converts it to 2 and it doesn't throw an exception. Instead if I enter a double for variable_1, it throws the exception, it is caught and the programme ends (return -1). Does anyone know why this happens and how to make it to throw the exception everytime any of the two numbers entered is not an int?

回答1:

When you read an int using an std::istream it first skips leading space, then tries to read a sign (it assumes positive if there is none), followed by a sequence of digits. It stops reading as soon as there are no more digits. The read succeeds if at least one digit could be read and the sequence of digits combined with the sign yields the value. Otherwise the read fails.

In your first case the first value is read completely followed by a read leaving the decimal point . and anything following it unread. However, the reads are both successful.

In you second case the digits before the decimal point are read leaving the decimal point in the stream. The second read attempts to read an int and fails finding the decimal point.

Making the read fail if there is something else is a bit tricky because it is unclear what inputs should fail! You could check after the read that the next character is an expected character, e.g., a whitespace. ... or you could read the remainder of the line and verify that it only contains whitespaces: that would be one of the rare cases where switch between formatted and unformatted without any reads between is the right thing to do.

By overriding the corresponding do_get() member of the std::num_get<...> facet and installing a std::locale object which fails upon finding one of the expected failure cases the reading of an int could be made to fail. I suspect that is a bit more complex than is being reasonable over here, though.



标签: c++ int double cin