Problem with infinite-loop

Hi there,

I'm new to C++ and having some trouble with an infinite-loop i have to set up.

The Program has to read in an integer value and has to "break;" out of the loop when i enter something different. I googled how to determine an input as an integer but everything fails.

input is declared as an integer.

here the loop:

1
2
3
4
5
6
7
8
9
10
while(1){
		cout << "Enter a integer:";
		cin >> input;
		if (cin.fail() == 0){
			cout << "Yes an integer" << endl;
		}else{
			cerr << "Whoops not an integer!";
			break;
		}
	}


i also added the console output and I am confused why the "break;" quits the loop ( I can't enter a number after this) but keeps printing the "Enter a integer:" after the else statement.

Enter an integer:1
Yes an integer
Enter an integer:2
Yes an integer
Enter an integer:3
Yes an integer
Enter an integer:4.4
Yes an integer
WhoooEnter an integer:ps not an integer


Can somebody help my I really have no clue.

Greetings Almi
Last edited on
I assume the problem you are having is that it is still saying it is an integer even when you enter a floating point value? Also I assume that the input value is an int type? If so then the problem lies in that floating point values when assigned to and integer automatically get cast to type int (Essential it will just chop off the decimal and anything after it).

So your stream does not fail because the stream interprets everything before the decimal as an integer and assigns that to the variable, it then just leaves everything after the decimal in the stream if I recall correctly. So you are going to need to go about testing whether the value is an integer a bit differently, or at least add on another extra test to deal with the floating point case.

I am actually not to sure about this but one sort of messy solution off the top of my head would be to instead change the input variables type to double and then, if cin fails cast it to an interger and compare the values. If they are equal then it is indeed an integer, if not it is a floating point value.

Here is an example, though please note that you will need to perform a better comparison which takes into account float precision inaccuracies.

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
#include <iostream>
using namespace std;

int main() 
{
	float input = 0.0;
	while(true)
	{
		cout << "Enter a integer:" << endl;
		cin >> input;
		if (cin.fail() == 0)
		{
			int testValue = input;
			
			// You are going to need to do a more in depth comparision since float
			// comparision is messy because of precision issues.
			if(testValue == input)
			{
				cout << "Yes an integer" << endl;
			}
		}
		else
		{
                        // Edit: You should probably also clear the steam
                        cin.ignore(100, '\n');
			cin.clear();
			cerr << "Whoops not an integer!";
			break;
		}

                // Edit: Might need to flush the stream
                cin.ignore(100, '\n');
	}
	
	return 0;
}
Last edited on
Hello Zereo,

Yes it is an integer i mentioned it above. The problem is, that the input has to be an integer... so I can't declare it as a double.

Maybe the solution wit cin.fail() isn't suitable for this, but I couldn't find something similar.
Hmm if you do need to keep the type as an integer you could instead use std::cin::peek() to check and see if there is leftover characters in the stream (Remember that if it was a floating point value it would just take the numbers before the decimal and leave everything after in the stream).

So something like this instead 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
33
34
35
36
#include <iostream>
using namespace std;
 
int main() 
{
    int input = 0;
    while(true)
    {
        cout << "Enter a integer: ";
        if (cin >> input)
        {
            // EDIT: Forgot to check for the newline. This will be in there
            // When the stream passes with a real integer and has't been flushed yet
            if (cin.peek() == EOF || cin.peek() == '\n')
            {
                cout << "Yes an integer" <<  endl;
            }
            else
            {
                cout << "Not an integer" << endl;
                cin.ignore(100, '\n');
                break;
            }
        }
        else
        {
            // Edit: You should probably also clear the steam
            cin.ignore(100, '\n');
            cin.clear();
            cout << "Whoops not an integer!";
            break;
        }
    }
 
    return 0;
}
Enter a integer: 5
Yes an integer
Enter a integer: 4
Yes an integer
Enter a integer: 3
Yes an integer
Enter a integer: 4.4
Not an integer
Last edited on
@Almi

Your first attempt wasn't bad at all, it does what's asked for.

The confusing behaviour is actually simple:

If you enter ".4" it you will end up in the cin.fail() branch, because .4 is not an integer. Actually you could use a more compact notaion, I'll give an example later.

If you had entered "4 4" (that is 4 space 4) at the input, your loop would have run twice, each time retrieving the integer 4 from cin.

When you entered "4.4" it also goes through the loop twice. The first time it retrieves 4 from cin, and the second time it tries ".4" and fails

You may not have realised this, maybe you were thinking it's waiting for you type another number and hit enter before continuing, but in actual fact, it doesn't (since you're dealing with int, it cannot), get "4.4" as a single input.

So for the first "4" you get the "Yes an integer" and for the "." you get the "Whoops not an integer!"

You sent your prompt to cout (which is buffered) and the error to cerr (which is not buffered) so you have 2 different iostreams being multiplexed onto your screen, that's why the text is mixed.

You would have seen the same behaviour if you entered something like "4y"

I promised an example alternative to the 2 stage cin >> and cin.fail():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <limits>

using namespace std;

int main()
{
	int input = 0;
	cout << "Enter an integer" << endl;
	while(cin >> input)
	{
		cout << "Yes an integer" << endl;
		cout << "Enter an integer" << endl;
	}

	cout << "Whoops not an integer!" << endl;
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

@tipaye

Your example is still producing incorrect results though. At least if I am understanding the assignment correctly. Here is the output from the program when ran with 4.4 as input.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <limits>

using namespace std;

int main()
{
	int input = 0;
	cout << "Enter an integer" << endl;
	while(cin >> input)
	{
		cout << "Yes an integer" << endl;
		cout << "Enter an integer" << endl;
	}

	cout << "Whoops not an integer!" << endl;
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
Enter an integer
4.4
Yes an integer
Enter an integer
Whoops not an integer!


As we can see when we enter 4.4 the first time it still says that what the user entered is an integer when in fact that isn't true and it is a floating point number. We also then continue to get an empty "Enter an integer" line which is the cause of the buffer still being full.

Both these can be solved by either converting from a float/double to integer and comparing, or by using std::cin::peek() to see if anything is left in the buffer after the stream assigned to the int variable (Which indicates it is a floating point number) and to check for the newline when it is an integer.
Last edited on
Thank you guys for all the feedback! Amazing Community :-)

Well the whole things is an exercise. The task is to build a infinite-loop which requests the user to enter a integer value and has to keep this on until there is another input than an integer. Therefor I insert the:

cout << "Enter integer" and cin >> input into the while(true)-loop.

So I am strictly bond to the task that there has to be an input as integer, otherwise the loop has to be cancelled with the brake; command.

My solution for now is:

1
2
3
4
5
6
7
8
9
10
11
12
13
while(true){
		cout << "Enter integer:";
		cin >> input;
		cout << endl;
		if (cin.fail()){
			cin.clear();
			cin.ignore();
			cout << "Loop-Cancelled";
			break;
		}else{
		        cout << "Continue-The-Loop";
		}
	}


The whole thing works to enter integer values. I also can quit the loop if I enter a character. The further problem is that I can't cancel the loop with an input of:

a double value like "1.1"
a mixed input like "2a"

And i am still clueless after reading several topics on stackoverflow and other resources google shows up.
As I tried to explain, it's trying to read an int and it's not seeing "4.4", it's seeing "4" and then "." - separate tokens. It's like entering "4zilla"...

I'm not trying to give a "correct" result here, OP original code is correct in that sense, and this is how it should behave. I'm just trying to explain the behaviour.

My code example was just to illustrate an alternative style, by using
while(cin >> input)
instead of
1
2
3
   while(true)
    {
        if (cin >> input)


Don't let my answer reflect on yours, I honestly wasn't commenting on your post, I was merely seeking to clear up some confusion.

However, now that I've read your post, permit a few comments:

"cin >>" will generally read input until whitespace, so several integers seperated by spaces or tabs would be valid acceptable input. Your program would choke on such input, you'll need to see if your peek() is some other kind whitespace before determining that input has ended.

The "ignore(100, '\n') is too easily defeated (especially if your input stream is a file for instance), dangers of magic numbers really.

Also prefer to use the more natural "double" rather than "float"
@tipaye

I would rather avoid going into a critiquing competition which would take over this thread. Specially since the point is to help beginners learn. I am sorry if you somehow took offense to my above post, my intent was just to point out to the OP that what your solution did not meet the criteria for his assignment question and to clear up confusing which generally arises when there is two posts that contradict each other.


The whole thing works to enter integer values. I also can quit the loop if I enter a character. The further problem is that I can't cancel the loop with an input of:

a double value like "1.1"
a mixed input like "2a"

And i am still clueless after reading several topics on stackoverflow and other resources google shows up.


Take a look at the examples above and research into the concepts used. They should handle both of those cases mentioned. Also if you don't understand any concepts feel free to ask I am sure one of the members or myself here would be glad to explain and walk through it.

Thank you guys I will try to understand those procedures, :-)

@tipaye

Yes, I understand your post. Can I image the cin does the following:

@tipaye, Zereo

cin >> input; and I type: Some String

the input will be handled character by character? So my program handles an input of "4.4" like:

Ok get the "4" -> it is an integer so no cin.fail() -> do the thing I am supposed to do.

Now there is the "." -> No thats no integer so cin.fail() will be true -> do what I am supposed to do when this happens. -> break; -> exit the while(true)-loop

So the cin.peek() has to take care of making sure the next value what will be checked of cin.fail() has to be an integer? Otherwise it shall break the while(true)-loop?

and still thank you both!
Topic archived. No new replies allowed.