Clarification on a basic behavior of cin in C++ - c++

I am curious why cin behaves in the following way. I think I might have
some misunderstanding about its behavior.
Consider this simple code. This code is asks for some input to be entered, all of which is printed out in the last statement.
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char** argv) {
cout << "Please enter your input: " ;
int a=3, b=87; // initialized to some random integers
string s = "Mary" ; // initialized to a random string
cin >> a ;
cin >> b ;
getline(cin,s);
cout << "You entered the following " << a << " " << b << " " << s << endl;
return 0;
}
Now if the input is 12 34 cat the output is 12 34 cat
This is expected.
However if the input is cat 23 dog the output is 0 87 Mary.
Here is why I think this is unexpected:
cin >> a should fail since catcannot be converted into an integer. However, a gets replaced with what I presume is a garbage value.
Now since the second number of the input is an integer 23, cin >> b must succeed. Yet this operation seems to fail, and b continues to retain its original value unlike what happened to a.
Similarly getline fails to place the string <space>dog into the string s
which continues to retain its original value of Mary.
My questions are the following.
Does the failure of some cin operation mandate the failure of all
subsequent cin operations using the >> operator or the getline function.
Why did the failure of the first cin operation change the value of a
whereas the initial values of b and s were unchanged?

Does the failure of some cin operation mandate the failure of all
subsequent cin operations using the >> operator or the getline
function.
Yes. Until you clear the error with cin.clear(). Also, when an extraction fails, the characters are left in the buffer, so if you try to read the same type again, it will fail again.
Why did the failure of the first cin operation change the value of a
whereas the initial values of b and s were unchanged?
Because (since C++11), it is defined to change the value to 0 in case of failed extraction from a (previously) valid stream. Before C++11, it would have been left unchanged. For a stream in an error state, the operation does nothing, which is why b and s are unchanged.

Does the failure of some cin operation mandate the failure of all subsequent cin operations using the >> operator or the getline function.
Yes. Your code expects to read the input value in exactly that order
cin >> a ; // 1st integer value
cin >> b ; // 2nd integer value
getline(cin,s); // string value
Giving it a input like
cat 23 dog
leads to setting fail() state on cin when trying to read the 1st int value, and none of the following operator>>() calls will succeed.
cin >> a should fail since catcannot be converted into an integer. However, a gets replaced with what I presume is a garbage value.
It's no garbage value but well defined, see the reference citation below.
Now since the second number of the input is an integer 23, cin >> b must succeed. Yet this operation seems to fail, and b continues to retain its original value unlike what happened to a.
No this assumption is wrong, as mentioned cin is in fail() state at this point, and parsing further input is skipped at all.
You have to call clear() after each operator>>() call, to be sure the input will by parsed:
cin >> a ; // 1st integer value
cin.clear();
cin >> b ; // 2nd integer value
cin.clear();
getline(cin,s); // string value
Why did the failure of the first cin operation change the value of a whereas the initial values of b and s were unchanged?
Because the reference of std::basic_istream::operator>>() says
"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<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set. (since C++11)"

You should use cin.good() function or shorthand notation if(cin) as said by #AndyG to check the state of cin object. variable a is of type int then how can you & why are you inputting string? So, it gives unexpected output for variable a.

Related

Confusion in cin functionality with int dataype

{
int n;
cin>>n;
cout<< n;
}
The output is 0 when any alphabet or special character is given as input.
In C its not the case when I used scanf(); and printf(). It prints the corresponding ASCII value.
Please explain why is this happening?
Please explain why is this happening?
In the documentation of the std::istream& operator>>(std::istream&, int) it's stated (emphasis mine):
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
For c++11 code it seems initialization is guaranteed:
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<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set.
Assumed you run a debug build of your code, n is probably initialized with 0 automatically, but technically accessing it is undefined behavior, since it wasn't initalized in that case you describe.
You have to check cin's state after input to detect if a failure occured during the number extraction, or if you can safely use the now-initialized value:
int n;
std::cin >> n;
if(std::cin) {
std::cout << n << std::endl;
}
else {
std::cin.clear(); // Clear the streams fail state
std::string dummy;
std::cin >> dummy; // Consume the non numeric input
std::cout << "Wrong input, '" << dummy << "' is not a number."
}
In both C and C++, when inputting an integer, the driver input function will read numeric characters until a character that is not a number is read.
For example, the sequence "123GHI" should return the value 123.

Why happens to variable when cin breaks? C++

I have the following code snippet:
int a = 1;
double b = 3.14;
string c = "hi";
cin >> a >> b >> c;
cout << a << " " << b << " " << c << endl;
If I enter apple 11 tammy, why does it cout: 0 3.14 hi instead of: 1 3.14 hi?
Why does the value of a change when cin is broken?
Why does the value of a change when cin is broken?
This is the expected behavior of std::basic_istream::operator>> since C++11; If extraction fails the value will be set to 0.
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<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set.
Note that after failbit being set, the following input won't be performed; that means b and c will remain their original values.
BTW: Before C++11 the value will be left unmodified when extraction fails.
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
Try stringstream instead. here is a link explaining the same issue in detail:
http://www.cplusplus.com/doc/tutorial/basic_io/

Effects on Input Variable after Failed Input Stream

I was working on the following code.
#include <iostream>
int main()
{
std::cout << "Enter numbers separated by whitespace (use -1 to quit): ";
int i = 0;
while (i != -1) {
std::cin >> i;
std::cout << "You entered " << i << '\n';
}
}
I know that using while (std::cin >> i) would have been better but I don't understand a specific occurrence.
If I provide an invalid input, the loop becomes infinite because the Input Stream enters a failbit state. My question is that what happens to the input variable i? In my case, it becomes 0 regardless of the previous value entered. Why does it change to 0 after an invalid input? Is this a predefined behaviour?
You get zero because you have a pre-C++11 compiler. Leaving the input value unchanged on failure is new in the latest standard. The old standard required the following:
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.
(source)
For gcc, you need to pass -std=c++11 to the compiler to use the new behavior.

Why is character 'a' not converted to 97 automatically?

char input1;
std::cout << "input1 : ";
std::cin >> input1;
int input2;
std::cout << "input2 : ";
std::cin >> input2;
std::cout << input1 << std::endl;
std::cout << input2 << std::endl;
return 0;
I wrote 'a' at input1 and 'a' at input2.
Ouput is like this.
input1 : a
input2 : a
a
-858993460
I'm curious...'a' charter is 97 in dec. why does it print -858993460?
'a' is not converted to 97 automatically? why?
a, as a string, is not convertible to an int by the rules std::cin follows. Consider this: a is not a valid integer in base 10. std::cin will fail to convert the string "a" to an int.
The reason it prints -858993460 is because the int is not initialized, so it could print anything, or nothing, or do whatever it desires (look up undefined behaviour).
Try something like this instead:
char input2_chr;
std::cin >> input2_chr;
int input2 = input2_chr;
I think the input simply failed, and the value you're seeing is the result of undefined behavior (input2 was never written to).
If you try to read an integer, the character 'a' is not valid so it wouldn't be accepted by the >> operator.
You seem to somehow expect that the input should convert the character to the ASCII code for that character in order to give you the integer-typed result you requested. This reasoning is not supported by the language.
In the first, you asked to input a character, so you got the first
non-whitespace character in the stream. In the second, you asked to
input an integer, so the stream skips whitespace (as it always does with
>>) and attempted to parse an integer. Since "a" cannot be the
start of an integral value, the stream set an error status (the
failbit) and returned, without modifying input2. When you output
the uninitialized variable, you have undefined behavior. (You should
never use a variable you've input without first checking whether the
input succeeded or not.)
From what you describe, it sounds like you are trying to input some
binary format. To do that, you must open the stream in binary mode,
ensure that it is imbued with the "C" locale, and then use
istream::get or istream::read. (Of course, you have to know what
the binary format is that you are reading, in order to be able to
convert the unformatted bytes you read into the actual information you
need.)
As e.g. Aardvard already has answered, you're seeing an arbitrary original value, in the C++ standard called an indeterminate value, because the input operation failed and input2 was not assigned a new value.
To output a decimal representation of the value of a char variable, simply convert it to int in order to direct the output stream to treat as integer.
The easiest way to convert it to int is to encourage an implicit promotion by using the variable in an expression, such as simply adding a + sign in front of it:
#include <iostream>
using namespace std;
int main()
{
char const ch = 'a';
cout << "'" << ch << "' = " << +ch << endl;
}
Output:
'a' = 97
Because you are reading an integer at input2. a isn't an integer. Therefore nothing will be read, and the original value of input2 will be maintained.
In this case, it will be some random value, cause input2 isn't initialized.
You can check whether the read succeeded by checking cin.good()

Input a letter to 'int'

Code:
int a;
cin>>a;
cout<<a<<endl;
Then I use g++ test.cpp, and run it. Then I input a letter 'b' to the variable a. The output is 0.
But, When I test the Other code:
cout<<int('b')<<endl; // output: 98
Why? What is the different?
std::cin is an object, an instance of a std::istream. std::istream has overloaded the >> to support a variety of types. One of those types is &int. When there is a std::istream on the left of >> and an integer reference on the right, the method istream& operator>> (int& val) is called. The conceptual implementation of that method is as follows.
Store 0 in an accumulator
Read a character of the input
If the character is 0-9, add its decimal value to the accumulator
If not, return the value of the accumulator
Return to step 2
When you provide 'b' as input to istream& operator>> (int& val), it immediately stores the "accumulated" 0 in your int variable. Example:
#include <iostream>
int main (const int argc, const char * const argv[]) {
int b = 100;
std::cout << b << std::endl;
std::cin >> b;
std::cout << b << std::endl;
return 0;
}
Execution:
100
b
0
As for the cast, when you cast the value 'b' to an integer, you already have a byte in memory with the value 98, which you then print as an integer. When you use >> the resulting value in memory is 0, which you then print as an integer.
The input operation that you are trying to do is failing. Since a is an int cin expects an int. since it gets a char it fails. You can test this by changing you code to:
int a;
cin>>a;
if(!cin)
cout << "input failed";
else
cout<<a<<endl;
Input:
a
Output:
input failed
See this live example
When you are using 'b' to cin a integer value, your program think you are input a invalid number, so it does't assign value by int('b'). still using initial value of a
not sure if this what you're finding:
char a;
cin >> a;
cout << a << endl;
try to change int to char,
when you enter 3, it'll output 3;
when you enter b, it'll output b;
if you want to output ascii, you can make cout like:
cout << (int) a << endl;
then you'll get 98 when you enter b
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)
from https://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt