Confusion in cin functionality with int dataype - c++

{
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.

Related

Is there some input condition for which `cin >> someStringValue` can evaulate to `false'?

In C++, standard input stream i.e. cin could evaluate to false (via. implicit boolean conversion) if it finds an input value that is not matching with type of variable where input is going to be stored.
For example,
#include <iostream>
using namespace std;
int main() {
int x;
while (cin >> x)
{
cout << "valid integer input\n";
}
cout << "invalid integer input !!\n";
return 0;
}
Input/Output to above code,
Input,
12
13
15
ABC
Output,
valid integer input
valid integer input
valid integer input
invalid integer input !!
Here is my question,
As expected, If we give a non-numeric input in above scenario then cin evaluates to false and program ends there. But what if I use a string variable in-place of integer variable in above code then what could be possible input value which I can provide so that cin evaluates to false? Because when I try above piece of code with a string variable instead of int then while-loop never seems to end ...
The expression cin >> x returns cin, so you check the boolean value of cin.
An iostream has operator bool define as:
Checks whether the stream has no errors.
…
2. Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().
This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or while(getline(stream, string)){...}. Such loops execute the loop's body only if the input operation succeeded.
In the case of an int it fails for ABC because ABC cannot be converted to int. Another situation when cin would evaluate to false is when the input stream closes.
I have realized that sometimes with the string input loop (like the while loop), "end-of-file" would still be recognized as a string input rather than a command to signal the end of your data input. Therefore I usually use if-else to manually set the string "end-of-file" (or basically anything) as the end of my data input. For example I would re-write your code like this for the string case (the int case would be similar):
#include <iostream>
using namespace std;
int main() {
string s;
string eof("end-of-file");
while (cin >> s) {
if (s != eof) { // the "!=" operator means "different from"
cout << "valid-string-input" << endl;
} else {
return 0;
}
}
cout << "invalid string input" << endl;
return 0;
}
Note: you should be aware that while an int cannot be a string, a string can be almost anything, even a number says "10" or "1" could still be considered a valid string input, it's just that these "10" or "1" cannot perform arithmetic operations since they are not ints. So the "invalid string input" here might be a little bit harder to trigger compared to the int case.
Short explanation for return 0, which basically means the program will be recognized as successful and will end right there. So the else {return 0;} means if the string is "end-of-file" then the program would just stop right there and recognized as successfully operated/ran.

Trying to understand cin behavior

I am writing software that takes a (huge) input stream from stdin and reads it into a vector of floats. I want to capture the case that the stream contains characters like commas, and either fail to accept it, or simply ignore everything that cannot be parsed as float (whichever is easier to implement, I have no preference). I have noticed the following behavior: when I call
echo "1.4, -0.7 890 23e-3" | ./cintest
this version
#include <iostream>
using std::endl;
using std::cin;
using std::cout;
int main ( int argc, const char* argv[] ){
float val;
while (cin >> val) {
cout << val << endl;
}
return 0;
}
prints
1.4
while this version
#include <iostream>
using std::endl;
using std::cin;
using std::cout;
int main ( int argc, const char* argv[] ){
float val;
while (cin) {
cin >> val;
cout << val << endl;
}
return 0;
}
prints
1.4
0
Without the comma, the first one prints
1.4
-0.7
890
0.023
while the second one prints
1.4
-0.7
890
0.023
0.023
Could somebody please explain what is going on here?
The first version of your code
while (cin >> val) {
tries to parse a float, and then checks whether the stream state is good. (Specifically, it calls operator>> to do the extraction, which will set failbit on error, and then uses the bool conversion to test failbit).
So, if the stream state is bad (because it couldn't convert , to a float), the loop body is not entered. Hence it terminates on the first failed conversion.
The second version
while (cin) {
cin >> val;
checks if the stream state is good (which just tells you the previous conversion succeeded), then tries parsing a float, and then assumes this succeeded without checking. It ought to check the stream state after conversion before using the float value, which in this case is left over from the previous iteration.
In a correct implementation, when conversion fails, you should check whether fail() is true but eof() is false (ie, the conversion failed for some reason other than end-of-file). In this case, use ignore() to discard input - you could either require whitespace (and ignore until the next space), or just ignore one character and try again.
Note that the ignore documentation linked above includes sample code with correct error handling. If we choose to skip a single character on failed conversions, your code would become:
for(;;) {
float val;
std::cin >> val;
if (std::cin.eof() || std::cin.bad()) {
break;
} else if (std::cin.fail()) {
std::cin.clear(); // unset failbit
std::cin.ignore(1); // skip next char
} else {
std::cout << val << '\n';
}
}
Your results have to do with when the >> fails.
In both versions, you read your values and reach the comma (or EOF). The read obviously fails, because , and EOF are not valid integers that >> can parse. So >>'s return value (the stream itself) converts to false, and you exit the loop in the first version (this is how it should work).
In the second version (which isn't how you should usually do it), however, you are still printing out whatever value ends up in val. In C++ before C++11, val remains the same; since C++11 >> writes 0 on failure.
TL;DR: Your second version stops the loop to late, and writes one pass of garbage.
It's because in the second one you have a bug.
You should always check to see if the formatted input operator>> actually worked.
So this code:
cin >> val;
cout << val << endl;
Should be written as:
if (cin >> val) {
cout << val << endl;
}
If the operator>> fails. Then it will set one of the fail bits on the stream and not put any value into val. So there is no need to print val because nothing was put into it.
This is why your second version prints garbage when it has no data left to read. The read fails and then you print out a value. Then you try and re-start the loop (which fails).
The first one works correctly.
while (cin >> val) {
cout << val << endl;
}
Because you read a value then check to see if the read works before entering the loop.
std::cin is an instantiation of std::istream
when there is a comma or any invalid data type at any point the operator >> fails. hence your code prints the last known value of 'val'.
Linked here is a reference for 'std::istream >>'
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

Why does a program become broken when a character is input when prompted to input an integer value?

Example:
int i=0;
do {
cin >> i;
if(!isdigit(i)) cout << "Error. Must be an integer\n\n";
}
while(cin.fail());
If a character rather than an integer was input by the user, the program would break and go into some infinite loop for some reason. Why is this? Is there no way to prevent it from happening? the isdigit() function doesn't seem to work well with int variables, only with char variables.
You seem to be confused about how input works. When you write
std::cin >> i;
and i is an int, the input stream will extract the text for
an integral value: it will skip whitespace, then extract
a possible sign, then one or more digits. It will then convert
this text into an int, and store it where requested. If it
doesn't find text in the appropriate format, it will set an
error status (failbit), which will remain set until you clear
it. And it will not modify i; you must always check that
input has succeeded before using the variable input.
isdigit, on the other hand, has undefined behavior unless
the integer it is passed is in the range [0,UCHAR_MAX]. (Note
that range. It means that you cannot simply pass it a char.)
It's not clear what you're trying to do here. If it's just
enter an int:
int i;
while ( !(std::cin >> i) ) {
std::cout << "Error: integer wanted" << std::endl;
std::cin.clear(); // Clear error...
std::cin.ignore( INT_MAX, '\n' ); // And ignore characters which caused it
// (up until next '\n')
}
If you want a single digit:
int i = std::cin.get();
while ( i != EOF && !isdigit( i ) ) {
std::cout << "Error, single digit wanted" << std::endl;
i = std::cin.get();
}
char ch = i; // NOW (and only now) can you convert into int.
std::cin.get() returns an int, in order to handle the out of
band value EOF. The int in guaranteed to be in the range
[0...UCHAR_MAX], or to be EOF, so you can pass it directly
to isdigit. Only once you've finished these tests should you
convert it into a char (since a digit is a character).
You always need to check after reading that your input was successful, e.g.
if (std::cin >> i) {
// process input
}
If the input fails std::ios_failbit is set. While this flag is set the stream won't accept any input and convert to false. To clear the error flags you use
std::cin.clear();
Clearing the error flags won't remove the offending character. You'll need to get rid of them, e.g., using
std:: ignore();
The above code certainly doesn't create an infinite loop. But the loop happens usually when a digit is expected and a non-digit is given, so the characters in the buffer will stay there and the stream is in an bad state. This will happen until the stream is appropriately cleared, so that the stdio can continue to read according to the format specification. Of course the loop has to be done iny our program, as stdio is not looping on it's own.
To clear the input and ingore what is left there you can use this:
std::cin.clear();
std::cin.ignore();

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()