The loop happens because the first extraction for a char datatype takes the first digit of the multiple digits as input, and the second recognizes that there is data remaining in the stdin buffer, so it doesn't wait for the user to input anything and takes it automatically.
Ex: Input a char > '12'
The extraction takes '1', and when the next extraction from stdin takes place, the '2' is still left in the stream's buffer, therefore, there's no need to wait for the user to input any data because it can just take it from stdin. And because of the way scanf() and std::cin's operator>> work, it will only take data out of the stdin buffer if it can be properly represented in the datatype associated with the pointer passed to the function. If we enter a string when the function expects an int, the variable is never assigned a meaningful value, the function returns an indication of this, and the string is left in stdin.
A way to deal with that, along with a similar solution is as follows:
#include <stdio.h>
#include <stdlib.h>
#pragma GCC diagnostic ignored "-Wunused-parameter"
int main(int argc, const char *argv[])
{
int num;
int tries = 0;
do
{
printf("Please enter a number other than %d: ", tries);
while (scanf(" %d", &num) != 1)
{
while ((num = getchar()) != EOF && num != '\n');
fputs("Invalid input, please try again: ", stderr);
}
/* after 10 iterations -- from a 0-based 'tries' count, the 11th
* iteration will be 10, thus we should exit after our message */
if (tries == 10)
{
fputs("Wow, you're more patient than I am, you win.", stdout);
exit(0);
}
}
while (num != tries++);
printf("Hey! you weren't supposed to enter %d!\n", num);
exit(0);
}
Same reason why you need a std::cin.get() after std::cin >> int_variable, or something else to get rid of the '\n' from the buffer because it's what gets appended when you confirm input with the enter key. With a string like "1234\n" as input, only the "1234" part can be represented as an int (1234), and the '\n' which remains is left in the input buffer. To avoid future conflict you should remove it somehow as soon as you can.
The way stream objects like std::cin work in C++ -- they maintain state flags that you should be checking for indication of success or failure whenever you deal with read/extraction operations like with the overloaded >> operator.