From Stroustrup's TC++PL, 3rd Edition, Section 21.3.3:
If we try to read into a variable v and the operation fails, the value of v should be unchanged (it is unchanged if v is one of the types handled by istream or ostream member functions).
The following example appears to contradict the above quote. Based on the above quote, I was expecting the value of v to remain unchanged -- but it gets zeroed. What's the explanation for this apparent contradictory behaviour?
#include <iostream>
#include <sstream>
int main( )
{
std::stringstream ss;
ss << "The quick brown fox.";
int v = 123;
std::cout << "Before: " << v << "\n";
if( ss >> v )
{
std::cout << "Strange -- was successful at reading a word into an int!\n";
}
std::cout << "After: " << v << "\n";
if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit\n";
if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit\n";
return 1;
}
The output I get using x86_64-w64-mingw32-g++.exe (rubenvb-4.7.2-release) 4.7.2 is:
Before: 123
After: 0
state: failbit
Thanks.
From this reference:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set (until C++11)
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits::max() or std::numeric_limits::min() is written and failbit flag is set. (since C++11)
It seems that your compiler is compiling in C++11 mode, which changes the behavior.
The input operator uses the locale facet std::num_get whose get function invokes do_get. For C++11 it's specified to use std::strtoll et. al. type of functions. Before C++11 it apparently used std::scanf style parsing (going by the reference, I don't have access to the C++03 specification) to extract the numbers. The change in behavior is due to this change in parsing the input.
The operator >> is a formatted input operator.
As such is dependent on the locale for how input is read from the stream:
[istream.formatted.arithmetic]
As in the case of the inserters, these extractors depend on the locale’s num_get<> (22.4.2.1) object to perform parsing the input stream data. These extractors behave as formatted input functions (as described in 27.7.2.2.1). After a sentry object is constructed, the conversion occurs as if performed by the following code fragment:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
As we can see above the value is actually set by the numget facet of the locale imbuded onto the stream.
num_get virtual functions [facet.num.get.virtuals]
Stage 3:
The numeric value to be stored can be one of:
zero, if the conversion function fails to convert the entire field. ios_base::failbit is assigned to err.
the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is assigned to err.
the most negative representable value or zero for an unsigned integer type, if the field repre- sents a value too large negative to be represented in val. ios_base::failbit is assigned to err.
The definition of stage 3 changed drastically between n2723 -> n2798
Where do I find the current C or C++ standard documents?
num_get virtual functions [facet.num.get.virtuals]
Stage 3: The result of stage 2 processing can be one of:
A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of scanf) to a value of the type of val . This value is stored in val and ios_base::goodbit is stored in err .
The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure. ios_base::failbit is assigned to err.
Related
Being following the book "Programming Principles and Practice Using C++" by Bjarne Stroustrup for learning C++ right from the very basics. It all proved good until this happened...
int main()
{
cout << "Please enter your first name and age\n";
string first_name = "???"; // string variable
int age = -1; // integer variable
cin >> first_name >> age; // read a string and then integer
cout << "Hello, " << first_name << " (age " << age << ")\n";
}
Now, as the above code (under the section Input and Types, Chapter 2) suggests, it outputs a string which familiarizes us to the name and age of a person. As I have initialized the integer variable age to -1, the program must return -1 to the monitor if I, in case by mistake, input a string value into age. The issue is that it just won't happen in my computer. I have tried and compiled and run the program 19 times (I do remember it...) but the result is always the same: it outputs 0 instead of -1.
For e.g. if I enter ABCXYZ 16, then the output will be a nice and simple Hello, ABCXYZ (age 16). But if the input was 16 ABCXYZ, then the output comes out to be Hello, ABCXYZ (age 0), which I expected to be Hello, ABCXYZ (age -1) as the string ABCXYZ won't be read into age (it is an integer variable) and thus give out the initialized value because it wasn't overwritten.
Any idea?
P.S.: I'm using Code:Blocks with GCC - 8.1.0
std::istream& operator>>(int &value) calls std::num_get::get() internally. From cppreference std::num_get::get() the behavior changed in c++11.
Having v to denote the variable we read into, until c++11 we had:
If an error occurs, v is left unchanged.
However since c++11:
If the conversion function fails to convert the entire field, the
value 0 is stored in v
If the conversion function results in a
positive or negative value too large to fit in the type of v which is
a signed integer type, the most positive or negative representable
value is stored in v, respectively
If the conversion function results
in a value not to fit in the type of v which is an unsigned integer
type, the most positive representable value is stored in v.
You are compiling using a compiler and C++ standard library configured to be compatible with a standard after c++11, so when std::cin fails to read the field, the value of 0 is stored into age.
The issue is isolated to the >> operator, where it fails to convert your string input into an integer (which is expected, as std::cin >> x handles expected input, from the type you define for x), and hence returns a 0, irrespective of whatever value you initialized the integer variable with.
This was done since C++ 11 as Kamil mentioned, and conforming to previous standards, the value would have been left unchanged and would return a -1 for your case.
You can check if cin fails or passes for the same to draw a conclusion yourself:
int main()
{
int age = -1;
std::cin >> age;
if(cin)
std::cout << age;
}
If you enter an integer (as expected from the type of age) you'd get the output for the value of age you initialized it to, else if you enter a string, cin will fail (and its failbit will be triggered, resulting in false) and nothing will be displayed, in accordance with the if-statement above.
This line of code outputs 0:
std::cout << !+2;
I think it should be 35, since '!' has an ASCII code of 33 and adding 2 to it equals 35.
Why is it like that?
Let's quickly analyze what your code !+2 does. The bare exclamation mark is the logical not operator which negates the truth value of its operand. Integers, such as +2 can be converted to boolean, where 0 means false and every non-zero integer true. That means that !+2 is converted to !true. The negation of true is obviously false, so !+2 is converted to false. When you pipe this boolean into std::cout is is converted to integer again, i.e. true turns into 1 and false turns into 0. That is why you std::cout << !+2; prints 0.
What you wanted to do instead (add 2 to the ASCII code of !) can be achieved as well. Therefore you have to tell the compiler that you want the character ! by enclosing it in single quotes. Then the code std::cout << ('!' + 2); will print 35, as expected. I added some extra parentheses to not rely purely on operator precedence.
#include <iostream>
int main() {
std::cout << ('!' + 2) << '\n';
}
Output:
35
Live on Wandbox
If you want to get the ASCII value of exclamation mark, you need to surround it with single quotes like following.
std::cout << '!' + 0;
What you did is negating a value (this value can be either True or False). Making the value (here integer) positive or negative does not matter (here you explicitly specify 2 as positive), because everything other than zero means True. So, if you do the same thing for zero like following, you would get 1 as output.
std::cout << !+0;
int a, b;
cin >> a >> b;
cout << a << endl << b;
input1: 3.5 5.5
input2: 3 5.5
check this code
The behaviour of your code is undefined up to and including C++03. The stream halts on the .. From C++11 onwards b is set to 0; prior to that it was not modified. Currently you read its value in the fail case, which is careless.
A good fix is to always write something like
if (cin >> a >> b){
// yes, all good
} else {
// a parsing error occurred
}
On the true branch, values are guaranteed to have been written to a and b.
It reads:
spaces/tabs/newlines (just consumes that if any)
digits till something different (the dot in your case) and parse them as the number
So a becomes 3.
Then, when it tries to read the second number it is still at the . , but a 'dot' is different from spaces and digits, so it does not consume any char and assignes 0 to b and set the failbit
Thanks to #tobi303 for the specs link:
(until C++11) If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
(since C++11) If extraction fails, zero is written to value and failbit is set.
The input is not a decimal value; it's a text string, and the code will translate that text string into an integer value. So, what's the integer value that the string "3.5" represents? It's 3, just as if the input had been "3 5": the code that translates the text reads as much of the text as makes sense, then stops. What happens after that depends on what caused the translation to stop. If it hit a whitespace character, all is well. If it hit something else (in this case, a .), you're in trouble.
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
How does this code know when to finish grabbing input values and display sum? Why does it only end when I input a non-integer value?
Your loop ends when std::istream& operator>>(int) evaluates to false. That happens if the stream has hit end of file or has been marked as in error. Entering a floating point number causes the latter to occur.
Details:
Every stream includes a bitmask that indicates the status of the stream. The bits in the mask comprise an eof bit, a fail bit, and a bad bit (std::ios_base::eofbit, std::ios_base::failbit, and std::ios_base::badbit). The first is rather obvious: It's set upon hitting EOF. The next two are a bit trickier. std::ios_base::failbit is set when an input operation failed to read the expected characters, or when an output operation failed to generate the desired characters. std::ios_base::badbit is set when something goes very wrong, e.g., your disk is fried. The conversion from a stream reference to a boolean eventually involves checking that none of these bits is set. The decimal point in a floating point number causes the fail bit to be set, and that in turn causes your loop to end.
Because as long as you are typing intergers, the cin >> value expression evaluates to true. If you type a non-integer, the expression will fail because you would be trying to put a non-integer into your value variable of type int.
while (std::cin >> value) will ends when there is no input (ctrl-D or end of stream) or has something bad occurred. Your input of a non-integer gives an error then it terminate the while
The line while (std::cin >> value) is saying to continue running while std::cin >> value is true. Conveniently, since value is an int, if you enter value which can't be implicitly converted to an int, then that expression will return false. Otherwise, it keeps going.
From Stroustrup's TC++PL, 3rd Edition, Section 21.3.3:
If we try to read into a variable v and the operation fails, the value of v should be unchanged (it is unchanged if v is one of the types handled by istream or ostream member functions).
The following example appears to contradict the above quote. Based on the above quote, I was expecting the value of v to remain unchanged -- but it gets zeroed. What's the explanation for this apparent contradictory behaviour?
#include <iostream>
#include <sstream>
int main( )
{
std::stringstream ss;
ss << "The quick brown fox.";
int v = 123;
std::cout << "Before: " << v << "\n";
if( ss >> v )
{
std::cout << "Strange -- was successful at reading a word into an int!\n";
}
std::cout << "After: " << v << "\n";
if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit\n";
if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit\n";
return 1;
}
The output I get using x86_64-w64-mingw32-g++.exe (rubenvb-4.7.2-release) 4.7.2 is:
Before: 123
After: 0
state: failbit
Thanks.
From this reference:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set (until C++11)
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits::max() or std::numeric_limits::min() is written and failbit flag is set. (since C++11)
It seems that your compiler is compiling in C++11 mode, which changes the behavior.
The input operator uses the locale facet std::num_get whose get function invokes do_get. For C++11 it's specified to use std::strtoll et. al. type of functions. Before C++11 it apparently used std::scanf style parsing (going by the reference, I don't have access to the C++03 specification) to extract the numbers. The change in behavior is due to this change in parsing the input.
The operator >> is a formatted input operator.
As such is dependent on the locale for how input is read from the stream:
[istream.formatted.arithmetic]
As in the case of the inserters, these extractors depend on the locale’s num_get<> (22.4.2.1) object to perform parsing the input stream data. These extractors behave as formatted input functions (as described in 27.7.2.2.1). After a sentry object is constructed, the conversion occurs as if performed by the following code fragment:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
As we can see above the value is actually set by the numget facet of the locale imbuded onto the stream.
num_get virtual functions [facet.num.get.virtuals]
Stage 3:
The numeric value to be stored can be one of:
zero, if the conversion function fails to convert the entire field. ios_base::failbit is assigned to err.
the most positive representable value, if the field represents a value too large positive to be represented in val. ios_base::failbit is assigned to err.
the most negative representable value or zero for an unsigned integer type, if the field repre- sents a value too large negative to be represented in val. ios_base::failbit is assigned to err.
The definition of stage 3 changed drastically between n2723 -> n2798
Where do I find the current C or C++ standard documents?
num_get virtual functions [facet.num.get.virtuals]
Stage 3: The result of stage 2 processing can be one of:
A sequence of chars has been accumulated in stage 2 that is converted (according to the rules of scanf) to a value of the type of val . This value is stored in val and ios_base::goodbit is stored in err .
The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure. ios_base::failbit is assigned to err.