When does that incorrect formatting infinite looping error occur and how to fix it?

I know there are a bunch of threads on this already, but I'm having a tiny bit of trouble understanding them. Anyways, there's a well-known glitch/error/bug (more of a beginner's mistake) that, when the wrong kind of data's entered into the command line (such as a char when an int was expected), will result in a sort of infinite looping, repeatedly prompting for input and not waiting for a response. I was unable to reproduce this, despite trying.

So when does it occur, and how could one prevent it?
Last edited on
Let's say you have an int input, and stick in some string of characters. It'll happen then. You can prevent it by checking for flags of your input stream, or by doing something like

1
2
3
If(cin >> input)
     something = input;


What this does is checks to see if the input was valid before doing anything with it. There's a little more to it, and you can look it up if your curious, but that'll work
Okay. One more thing. When exactly does it come up, and why? For instance, I tried the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

int main()
{
    while(true)
    {
        int a,b;
        char operation;
        std::cout << "\nEnter a single operation\n" << std::endl;
        std::cin >> a >> operation >> b;
        switch (operation)
        {
            case ('+'):
                std::cout << a+b << std::endl;
                break;
            case ('-'):
                std::cout << a-b << std::endl;
                break;
            case ('*'):
                std::cout << a*b << std::endl;
                break;
            case ('/'):
                std::cout << static_cast<double>(a)/static_cast<double>(b) << std::endl;
                break;
            default:
                std::cout << "You entered an invalid operation." << std::endl;
        }
    }
}


And I'm not sure why exactly it happens. Could you please enlighten me? Oh, and thanks for the help!
Well, what exactly happened and what did you try?
Well, what happened was when I entered a char instead of an int, it would keep looping infinitely. In an attempt to correct it, I did

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

int main()
{
    while(true)
    {
        int a,b;
        char operation;
        std::cout << "\nEnter a single operation\n" << std::endl;
        if (std::cin >> a)
        {
            std::cin >> operation;
            if (std::cin >> b)
            {
                switch (operation)
                {
                    case ('+'):
                        std::cout << a+b << std::endl;
                        break;
                    case ('-'):
                        std::cout << a-b << std::endl;
                        break;
                    case ('*'):
                        std::cout << a*b << std::endl;
                        break;
                    case ('/'):
                        std::cout << static_cast<double>(a)/static_cast<double>(b) << std::endl;
                        break;
                    default:
                        std::cout << "You entered an invalid operation." << std::endl;
                }
            }
            else
            {
                std::cout << "You entered it wrong.  Do it right this time." << std::endl;
            }
        }
        else
        {
            std::cout << "You entered it wrong.  Do it right this time." << std::endl;
        }
    }
}


Which didn't work.
Last edited on
There's a little more to it, and you can look it up if your curious, but that'll work

When you input something cin doesn't like, you break the cin. You have to fix it:
1
2
3
4
5
while (!(cin >> a)) // While the input is breaking the cin
  cin.clear();  // Reset the state of the cin object
  cin.sync();  // clear the buffer, else there could still be something there to break it again
  cout << "You messed up.  Try again: ";
}


This might take some figuring to get it working for your program, but the method is the same. Maybe you don't want the actual extraction in the condition, etc.
Hmmm ... this didn't help.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

int main()
{
    while (true)
    {
        int a,b;
        char operation;
        std::cout << "\nEnter an operation\n" << std::endl;
        if (!(std::cin >> a))
        {
            std::cout << "You entered it wrong. Get it right next time." << std::endl;
            std::cin.clear();
            std::cin.sync();
            continue;
        }
        std::cin >> operation;
        if (!(std::cin >> b))
        {
            std::cout << "You entered it wrong. Get it right next time." << std::endl;
            std::cin.clear();
            std::cin.sync();
            continue;
        }
        switch (operation)
        {
            case ('+'):
                std::cout << a+b << std::endl;
                break;
            case ('-'):
                std::cout << a-b << std::endl;
                break;
            case ('*'):
                std::cout << a*b << std::endl;
                break;
            case ('/'):
                std::cout << static_cast<double>(a)/static_cast<double>(b) << std::endl;
                break;
            default:
                std::cout << "You entered an invalid operation." << std::endl;
        }
    }
}


Replacing those if's with while's just resulted in that while being an infinite loop. I'm obviously getting the whole idea of this wrong somehow, but what am I doing wrong?
Works for me, remove those continues. It would also be good to put your cout after fixing the cin, you want to fix it asap.
Hmmm ... I know how much of a pain I am, but I tried

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>

int main()
{
    while (true)
    {
        int a,b;
        char operation;
        bool caught = false;;
        std::cout << "\nEnter an operation\n" << std::endl;
        if (!(std::cin >> a))
        {
            while (!(std::cin))
            {
                std::cin.clear();
                std::cin.sync();
            }
            std::cout << "You entered it wrong. Get it right next time." << std::endl;
            caught = true;
        }
        std::cin >> operation;
        if (!(std::cin >> b))
        {
            while (!(std::cin))
            {
                std::cin.clear();
                std::cin.sync();
            }
            if (!caught)
            {
                std::cout << "You entered it wrong. Get it right next time." << std::endl;
            }
            caught = true;
        }
        switch (operation)
        {
            case ('+'):
                std::cout << a+b << std::endl;
                break;
            case ('-'):
                std::cout << a-b << std::endl;
                break;
            case ('*'):
                std::cout << a*b << std::endl;
                break;
            case ('/'):
                std::cout << static_cast<double>(a)/static_cast<double>(b) << std::endl;
                break;
            default:
                if (!caught)
                {
                    std::cout << "You entered an invalid operation." << std::endl;
                }
        }
    }
}


It at least manages to stop, but it doesn't seem to want to output any operations afterwards, and it takes a lot of iterations to stop. Here was the input/output from one of the times I ran this.



Enter an operation

www
You entered it wrong. Get it right next time.

Enter an operation

You entered it wrong. Get it right next time.

Enter an operation

You entered it wrong. Get it right next time.
2+2

Enter an operation
//And here I gave up
Try 2 + 2 (note the spaces)
Unfortunately, that didn't work. And I do know the really basic basics about cin, so I'm pretty sure entering 2+2 (without spaces) should work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using namespace std;

int main(){
	double x, y;
	char c;

	while (true){
		cout << "Please enter a function: ";
		if (!(cin >> x >> c >> y)){
			cin.clear();
			cin.sync();
			cout << "Nope";
		}
		else {
			switch (c)
			{
			case '+': cout << x <<  " + " << y << " = " << x+y; break;
			case '-': cout << x <<  " - " << y << " = " << x-y; break;
			case '*': cout << x <<  " * " << y << " = " << x*y; break;
			case '/':
				if (y != 0) cout << x << " / " << y << " = " << x/y;
				else cout << "Can't divide by zero";
				break;
			default: cout << "I have no idea";
			}

		}
		cout << endl;
	}
	return 0;
}
Last edited on
You might try it using the canonical solution, since cin.sync() isn't guaranteed to do anything (and isn't a general portable solution.)

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <limits>
#include <iostream>

int main()
{
	while(true)
	{
		int a,b;
		char operation;
		std::cout << "\nEnter a single operation\n" << std::endl;

		if ( !(std::cin >> a >> operation >> b ) )
		{
			std::cin.clear() ;
			std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ;
			continue ;
		}

		switch (operation)
		{
		case ('+'):
			std::cout << a+b << std::endl;
			break;
		case ('-'):
			std::cout << a-b << std::endl;
			break;
		case ('*'):
			std::cout << a*b << std::endl;
			break;
		case ('/'):
			std::cout << static_cast<double>(a)/static_cast<double>(b) << std::endl;
			break;
		default:
			std::cout << "You entered an invalid operation." << std::endl;
		}
	}
}
Last edited on
Topic archived. No new replies allowed.