So I'm curious as to why this happens.
int main()
{
bool answer = true;
while(answer)
{
cout << "\nInput?\n";
cin >> answer;
}
return 0;
}
Expected behavior:
0 - Exits program,
1 - Prompts again,
Any non-zero integer other than 1 - Prompts again
Actual behavior:
0 - As expected,
1 - As expected,
Any non-zero integer other than 1 - Infinite loop
From http://www.learncpp.com/cpp-tutorial/26-boolean-values/
One additional note: when converting integers to booleans,
the integer zero resolves to boolean false,
whereas non-zero integers all resolve to true.
Why does the program go into an infinite loop?
In effect, the operator>> overload used for reading a bool only allows a value of 0 or 1 as valid input. The operator overload defers to the num_get class template, which reads the next number from the input stream and then behaves as follows (C++11 §22.4.2.1/6):
If the value to be stored is 0 then false is stored.
If the value is 1 then true is stored.
Otherwise true is stored and ios_base::failbit is assigned to err.
(err here is the error state of the stream from which you are reading; cin in this case. Note that there is additional language specifying the behavior when the boolalpha manipulator is used, which allows booleans to be inserted and extracted using their names, true and false; I have omitted these other details for brevity.)
When you input a value other than zero or one, the fail state gets set on the stream, which causes further extractions to fail. answer is set to true and remains true forever, causing the infinite loop.
You must test the state of the stream after every extraction, to see whether the extraction succeeded and whether the stream is still in a good state. For example, you might rewrite your loop as:
bool answer = true;
while (std::cin && answer)
{
std::cout << "\nInput?\n";
std::cin >> answer;
}
Because operator>> fails if the input is not 0 or 1, and when it fails, it does not consume input. So the loop consists of reading the digit and then un-reading it, repeatedly.
Try changing the code like this to see it:
if (cin >> answer) {
cout << answer << endl;
} else {
cerr << "oops" << endl;
break;
}
Related
I'm currently learning how while (cin >> num) work and I found out that there are two steps.
First one is the operator>> function return a istream object with error state, and the second is bool converter that convert istream object into bool depend on its state.
But I find it confusing that in the bool convert function, it will return 0 only if failbit or badbit is set. And the operator>> function will set eofbit if it read EOF.
bool convert function: https://www.cplusplus.com/reference/ios/ios/operator_bool/
operator>> function: https://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
In this case, After I enter EOF the bool converter should return 1 because the failbit and badbit aren't set.
Therefore, I use the below program to check what actually happened to the error bit after I enter EOF. And I find out that the failbit will be set after entering EOF!!
So I'm wondering if anyone can help me understand why is failbit set?
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num;
cout << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
return 0;
}
Input: ^Z(on windows using qt creator, non qt c++ project)
Output: 1 1 0
Input: ^D(on windows using qt creator, non qt c++ project)
Output: 0 1 0
eofbit is set when a read operation encounters EOF while reading data into the stream's buffer. The data hasn't been processed yet.
failbit is set when the requested data fails to be extracted from the buffer, such as when reading an integer with operator>>. While waiting for digits to arrive, EOF could occur. eofbit alone is not enough to enter an error state, as there may be usable data in the buffer.
So, for example, imagine a while (cin >> num) loop is used and the user enters 123<Ctrl-Z>.
on the 1st iteration, operator>> reads 1, 2, 3 into the buffer, then encounters Ctrl-Z, so it sets eofbit and stops reading. 123 is then extracted from the buffer into num and the operator exits. At this point, the stream is not yet in an error state. When the stream's bool conversion is evaluated by while, it returns true, allowing the while body to be entered so it can process num.
on the next iteration, operator>> sees eofbit is set, preventing further reading. There is nothing left in the buffer to extract into num, so the operator sets failbit and exits. The stream is now in an error state. When the stream's bool conversion is evaluated by while, it returns false, breaking the while loop.
If the EOF is the first input, the operator>> fails to read an integer, so the stream enters the fail() state.
If you type at least one digit before the Ctrl-Z, that digit is read and the input succeeds.
I am new to c++ and was making a program in c++11 that sorts a list of integers using the bubble sort algorithm. While I was doing this I noticed something weird. This is my code:
#include <iostream>
void bubbleSort(int x) {
bool done;
int list[x] {0};
std::cout << "List:\n";
for (int i=0;i<x;i++) {
std::cout<<i<<':';
std::cin>>list[i];
}
do {
done = true;
for (int i=0;i<x-1;i++) {
if (list[i]>list[i+1]) {
list[i] = list[i]+list[i+1];
list[i+1] = list[i]-list[i+1];
list[i] = list[i]-list[i+1];
done = false;
}
}
} while (not done);
for (int i:list) {
std::cout<<i<<' ';
}
std::cout<<std::endl;
}
int main() {
int n;
std::cout<<"Length of list: ";
std::cin>>n;
bubbleSort(n);
}
If I input a char instead of an int the program outputs numbers leading up to the length of the list then a string of zeros equal to length of the list.
ex: if I input 5 then type 'k' at the input:
1:2:3:4:0 0 0 0 0
My question is, why is it producing this specific output? I would expect an error if it gets the wrong data type. Sorry if my question is confusing. Thanks in advance.
If you enter k when the input is expecting a number. Then the stream will go into an error state.
The problem is that you did not check the state:
std::cin>>n;
// There could be an error in the line above.
// But you did not check for the error.
Also here:
std::cin>>list[i];
// There could be an error in the line above.
// But you did not check for the error.
Try this:
if (std::cin >> n) {
std::cout << "It worked I got the number: " << n << "\n";
}
else
{
std::cout << "Failed to read a number.\n";
}
How does the above work.
Well the result of the operator>> is a reference to a stream. So it reads a value from the stream into n but returns a reference to the stream. This allows you to things like this:
std::cin >> n >> x >> y;
After each operator>> you get a reference to the stream to apply to the next operator>> so you can chain reads together.
When you use a stream in a boolean context (a test like an if or while) it will convert itself to boolean value depending on its internal state. If the internal state is good std::cin.good() then it will return true otherwise it returns false.
So after it completes the operator>> in then converts itself to bool for the if statement. If it is in a good state you know the read worked. If the read failed it would set an internal fail state and good() returns false.
So what happened in your code.
Well the read failed and the state of the stream was set to failed. When a read fails the preferred behavior is that object being read into remain unchanged (this is what happens for POD (standard) types, user defined types this can be a bit more haphazard).
So the value of n remains unchanged.
When you declared n
int n;
You did not define an initial value so it has an indeterminate value. Which means trying to read that value is UB. UB is bad. it means the code can do anything (which it has done). In practical terms (for most systems) it means the variable has an unknowable value and is whatever was left at that memory location from the last variable that used it.
For your specific case:
So you have typed 5 first then k.
So your first read std::cin >> n; worked.
The next read std::cin>>list[i]; failed.
This set the state of the stream to bad. Any subsequent reads do nothing (until you reset the stream state to good). So you are supposed to detect and fix the stream state.
Each subsequent time around the loop the std::cin >> list[i] will do nothing as the stream is in an error state. Which means it will keep its original value (which for this case is defined as zero 0).
Again the correct action here is to read and check the state of the stream. If it fails take corrective action:
if (std::cin >> list[i]) {
// Worked
}
else {
std::cerr << "Bad input. Try again\n";
// reset the state of the stream
// before trying to read again.
std::cin.clear();
if (std::cin >> list[i]) {
std::cerr << "You got it correct this time\n";
}
else {
std::cerr << "User not bright enough to use the app aborting\n";
throw std::runtime_error("Failed Bad User");
}
}
Additional Note
This behavior of streams is good for reading user input. As it allows a natural flow for detecting and writing code for the user to fix the issue. This design is practically the same for all modern languages that have the same pattern.
But this is not a good flow when you have machine input (ie. there are not expected to be any errors in the input and if there was an error there is no way to correct it).
For reading machine input you can set the stream to throw on an error. This allows you to write nice clean easy to read code that when things go wrong (when they should not) then an exception is throw causing the application to correctly terminate (or the exception could be caught).
std::cin.exceptions(std::ios::badbit); // Fail and Bad
In C++ primer I found this code:
if (cin.fail())
{ // bad input
cerr<< "bad data, try again"; // warn the user
cin.clear(istream::failbit); // reset the stream
continue; // get next input
}
I am confused that why the istream::failbit is used to set the error state flag, I mean that since the error has occurred (hence the flow is right now in if block then the failbit must be set, they why use it to set the error flag with that again. Where am I wrong in understanding this?
EDIT:
The book says "We print a warning and clear the failbit state", but IMO clear(istream::failbit) is setting the current state of stream with the value contained in failbit. So why the book is setting the stream's state with that of failbit as it will stop cin from functioning as it will be in error state. ++++ By state of a stream, what bit actually is being talked about, is it eofbit, badbit, goodbit, failbit or a combination of them? How can I know the value of these individual bit as well?
std::basic_ios::clear
void clear( std::ios_base::iostate state = std::ios_base::goodbit );
Sets the stream error state flags by assigning them the value of state. By default, assigns std::ios_base::goodbit which has the effect of clearing all error state flags.
If rdbuf() is a null pointer (i.e. there is no associated stream buffer), then state | badbit is assigned. May throw an exception.
Essentially in this case to set bit means that it sets bit to clear state.
If you call clear without parameters, it sets all bits to clear state, by setting "goodbit", which is exclusive with other states. If you mark only certain bit, only that bit will will be set, clearing other bits ( and good bit as well). Anyway, as said above, if during call of this method input buffer of stream is not valid, then clear() also sets badbit to true, so method good() and operator bool will return false and fail() will still return true.
To wit, why one need to clear those bits but keep a error state is depends on further code, often it is to be able to detect that error happened , but being able to request more data from stream (ask for correct input?)
#include <iostream>
#include <limits>
#include <string>
int main() {
using std::cout;
using std::cin;
int a;
do
{
cout << " Please enter an integer number:";
cin.clear();
cin >> a;
if(cin.fail())
{
cout << "Error occured while parsing input.\n";
cin.clear(std::istream::failbit);
}
// do something
if(cin.fail())
{
std::string str;
//now clear everything, to unlock the input.
cin.clear();
cin >> str;
cout << "Wrong input was: " << str << "\n";
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// setting fail bit again, so loop will go on
cin.clear(std::istream::failbit);
}
} while(cin.fail());
cout << "Thank you!";
}
Without calling ::clear(std::istream::failbit) and ::ignore the loop would be working forever, because state of the flags and buffer would force an attempt to parse same buffer content over and over. Actually, a that point you may try to reparse it , e.g. read the string and print it. It would be ok to call just clear() but then we need to create own flag that would allow us to react correctly.
The "state" of stream is a private field of type std::ios_base::iostate, which value is equal to a binary combination of it eofbit, badbit, and failbit constants. goodbit constant is equal to zero and represents no-error state. Two accessors that provide read and write operations to this field:
void setstate( iostate state );
iostate rdstate() const;
Note, setstate(state) got effect of clear(rdstate() | state), which means that if clear can set exact value of iostate, setstate can only set new bits to true, but can't clear bits that already set.
int main()
{
std::ostringstream stream;
if (stream.rdstate() == std::ios_base::goodbit) {
std::cout << "stream state is goodbit\n";
}
stream.setstate(std::ios_base::eofbit);
// check state is exactly eofbit (no failbit and no badbit)
if (stream.rdstate() == std::ios_base::eofbit) {
std::cout << "stream state is eofbit\n";
}
}
for each bit there are accessors: fail(), bad(), eof(), good().
Essentially, fail() returns true if (rdstate()|std::ios_base::failbit) != 0, and so on (See 30.5.5.4 basic_ios flags functions, ISO/IEC 14882:2017, Programming
Languages — C++)
operator bool is defined and returns good()
operator! is defined and returns !good()
The line
if (stream.rdstate() == std::ios_base::goodbit)
can be replaced by
if (stream)
because the latter results in contextual conversion to bool.
Effects, associated with iostate's bits (according to ISO C++):
badbit indicates a loss of integrity in an input or output sequence (such as an irrecoverable read error from a file);
eofbit indicates that an input operation reached the end of an input sequence;
failbit indicates that an input operation failed to read the expected characters, or that an output operation failed to generate
the desired characters.
In Bjarne Stroustrup's Programming Principles and Practice Using C++ (Sixth Printing, November 2012), if (cin) and if (!cin) are introduced on p.148 and used in earnest on p.178. while (cin) is introduced on p.183 and used in earnest on p.201.
However, I feel I don't fully understand how these constructs work, so I'm exploring them.
If I compile and run this:
int main()
{
int i = 0 ;
while (cin) {
cout << "> ";
cin >> i ;
cout << i << '\n';
}
}
I get something like:
$ ./spike_001
> 42
42
> foo
0
$
Why is it that entering "foo" apparently causes i to be set to 0?
Why is it that entering "foo" causes cin to be set to false?
Alternatively, if I run and compile this:
int main()
{
int i = 0 ;
while (true) {
cout << "> ";
cin >> i ;
cout << i << '\n';
}
}
I get something like:
$ ./spike_001
> 42
42
> foo
> 0
> 0
...
The last part of user input here is foo. After that is entered, the line > 0 is printed to stdout repeatedly by the program, until it is stopped with Ctrl+C.
Again, why is it that entering "foo" apparently causes i to be set to 0?
Why is it that the user is not prompted for a new value for i on the next iteration of the while loop after foo was entered?
This is using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3.
I'm sorry for such a long question, but I think it all boils down to, "How is cin evaluated?"
Well, std::cin (or more precisely std::basic_ios) has an operator bool to implicitly convert the std::cin object to a bool when requested (for example in your if evaluation).
The semantic is as follows:
Checks whether the stream has no errors. Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().
Why is it that entering "foo" apparently causes i to be set to 0?
Again, why is it that entering "foo" apparently causes i to be set to 0?
Because operator>> on an int expects an integer in the string.
From cppreference:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
Why is it that entering "foo" causes cin to be set to false?
Because the fail bit is set, therefore leading fail() to return true.
Why is it that the user is not prompted for a new value for i on the next iteration of the while loop after foo was entered?
That is because std::cin has the fail bit set, therefore it fails to get the input and just prints the old value of i which is 0.
When you use the >> operator on a stream, it attempts to extract a value of that type from the string. In other words, when you do cin >> i where i is an int, the stream attempts to pull an int from the stream. If this succeeds, i is set to the extracted value, and all is well. If it fails, the stream's badbit is set. This is important because treating a stream as a bool is equivalent to checking if it's badbit is set (if (cin) is like if (cin.good())).
So anyway... what's happening is that foo is setting the badbit since the extraction fails. Really, you should be checking if the extraction succeeds directly:
if (cin >> i) { /* success */ }
On a code quality note, I suspect you're using using namespace std;. Please be aware that this can be harmful.
int value(0);
while (!(std::cin >> value)) { //THIS LINE RIGHT HERE IS BUGGING ME(am really a noob)
cout << "you entered a non-digit character\n";
cin.clear();
cin.ignore();
}
this just stops people from entering letters instead of a number but i wanna know HOW it does it
Treating cin as a Boolean value tells you whether it's in a failure state. if ( cin ) is shorthand for if ( cin.ok() ). So the loop continues as long as the input stream is not OK, after taking some input.
Getting bad input is one way to get to a failure state. To get out of the state, call clear(), and to ignore the offending input, call ignore(). Then you can try again, as in this loop.
If what cin received's data type isn't compatible with value, then basically it returns as false.
cin >> value returns the cin object as a result. And it evaluates as false if the user-entered type doesn't match the specific overload (in your code, it's int), or cannot be implicitly converted to it.
cin is an object of class istream that represents the standard input stream. It corresponds to the cstdio stream stdin.
operator >> overload for streams returns a reference to the same stream and this can be evaluated in a boolean condition to true or false based on internal state of stream through a conversion operator. cin provides formatted stream extraction.
The operation
int value;
!(std::cin >> value)
will fail if numeric value is
entered and will return true if non-numeric value is entered.
cin.clear(); // will reset the state of stream
cin.ignore(); // ignore one or more characters