So, I was making hangman for fun, and I had
unsigned short guesses;
std::string word;
std::cin << guesses;
// ...
And I discovered something interesting.
I was just playing around, and I typed 1
, and spammed a bunch of 0
s.
Sort of like the following.
1000000000000000000000
And then it did something really strange, it skipped the next std::cin
command (which was the one for word
).
And then... it kept repeating, printing things over and over (probably because I was in a while(true)
), but it didn't bother to stop when it hit std::cin
, even on the next loop iteration, instead constantly having the number be equal to 65535
, (2^16)-1
; or in other words, the 16 bit integer (unsigned short
) limit.
Even if I enter 65536
, the unsigned short
limit plus one, it still bugs out in this crazy way.
Here's an image of what happens after I do this:
This is what should happen normally:
Strangely, this bug will also happen if I pass any strings that include a space () character in them for
answer
(for some reason).
This is my code:
int main() {
while(true) {
unsigned short guesses;
std::string answer;
std::cout << "Enter the amount of guesses to allow: ";
std::cin >> guesses;
std::cout << "Enter the word for P2 to guess: ";
std::cin >> answer;
std::cout << "[Guesses: " << guesses << ", " << "Word: \""
<< answer << "\"]\n";
}
}
If anyone knows what's causing these bugs, and how I can fix them, let me know!
Thanks!
Cheers!
Cheers!
Top comments (5)
Obviously, 65536 can't fit in an
unsigned short
and the convertion fails. cppreference explains why you get 65535:You should call
fail()
to check whether the conversion has been sucessful. You can also test the stream withoperator!()
.If the conversion has failed, you should
clear()
the error state flags. You should also empty the input buffer, otherwise the next iteration of the loop will run into the same bad convertion [repeat while true].The code may then looks like:
The space is parameter separator so I'm not supprised that it triggers input in the next loop iteration. What I am supprised is that buffer is not getting emptied on next iteration causing it to read stuff over and over again. But I'm used to garbage collected languages so I might be expecting more than I should. Anyways try clearing the input buffer on last line of loop, see what happens. I would assume that a single unput input of 100000000000 would overflow uint couple of times and on next interation it would accept new input. Would also expect that empty input (when you hit space after answer) for uint would be 0 or some garbage numeric value not overflowing the buffer again multiple times.
How do you clear it?
The
ignore method
? (Or is that slightly different than what I want?I think that comment from @pgradot is the way to go. Check for failure, then clear the buffer, then ignore stuff, and finally do the rest - output messages and ask for inputs. Insted of clearing at the end as I suggested it's probably correct to first validate, clear, ignore.
So not just 'ignore' method but combination as described in mentioned comment links.
When I try
std::getline(std::cin, answer)
, it doesn't work, it just acts as if there was no call made togetline
, or tostd::cin
.