How to accept only the input i want?

Hello all;

I am new both to programming and to this forum.

C++ seemed like a good language to get to grips with and here seemed like a good place to try and solve my first problem.

I set myself an exercise to get to grips with 'while' and 'bool'

Here is the code:

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
#include <iostream>
#include <string>

using namespace std;

int main ()

{
int x;
bool finished = false;
bool correct_no = false;

cout << "your number please:-" << endl;
cin >> x;

while (!correct_no)
	{
		if (x <= 100000 && x > 0)
		{
		correct_no = true;
		}
			else
			{
			cout << "Pick a 'whole' positive number please between zero and 100000:" << endl;
			cin >> x;	
			}
	}
	 
			
while (!finished)
	{
	cout << x << " ";
	x--;
	
	if (x==0)
	finished = true;
	}
	
	cout << endl << "All done! Nice!!" << endl;
	
return 0;
}


It pretty much works the way I intended apart from one problem:-

I want it so that any entry at the console not within the number range eg. letters, decimal numbers, negative numbers, too large numbers etc. is met with the "pick a 'whole' positive number...." output.

If i enter a letter character instead of a number, i get stuck in an 'output loop.

Sorry i'm not explaining it very well, not got used to the lingo yet!

Could someone please give me some pointers, it's been driving me round the bend.

Many thanks,

Dan.
When cin encounters an input it can't properly read in to the variable specified (such as inputing a character into an integer variable), it goes into an error state and leaves the input in it's buffer.

You have to do several things to properly handle this scenario.

1. You have to test for this error state.
2. You have to clear the error state.
3. You have to either alternatively handle the input data that generated the error state, or flush it out and reprompt the user.

The following code provides one of numerous methods of doing these three things.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
#include<limits>
using namespace std;
int main()
{
	
	cout << "Enter an int: ";
	int x = 0;
	while(!(cin >> x)){
		cin.clear();
		cin.ignore(numeric_limits<streamsize>::max(), '\n');
		cout << "Invalid input.  Try again: ";
	}
	cout << "You enterd: " << x << endl;		
}


You could just pass in some large value to cin.ignore like 1000 and it's likely to behave exactly the same for all practical purposes.

You can also test cin after the input attempt and handle it that way, something like
if(!cin){//clean up the error} .

Check out the istream reference for other member functions to handle stream state: http://cplusplus.com/reference/iostream/istream/
Many thanks for the help,

That seems to have sorted out the inappropriate entering of letters at cin.
I am still not clear on how to limit the input to numbers > 0, <something, or to whole numbers

This is where i've got to:
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
#include <iostream>
#include <string>
#include <limits>

using namespace std;

int main ()

{
int x = 0;
bool finished = false;


cout << "your number please:-" << endl;


while (!(cin >> x))
	{
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(),'\n');

		cout << "Please input a proper 'whole' number: " << endl;
	}
	 
			
while (!finished)
	{
	cout << x << " ";
	x--;
	
	if (x==0)
	finished = true;
	}
	
	cout << endl << "All done! Nice!!" << endl;
	
return 0;
}


Should i put back the 'bool' that i removed or is there a clearer way?
Bounding the value to a subset of the legal values would be a separate check. You will still need the if() statement in your original sample code to do that check.

On another note, an example of a way to simplify the latter portion of your code...

1
2
3
while(x)
  cout << x-- << " ";
cout << endl << "All done! Nice!!" << endl;
Thanks for the simplification!

By putting just (x) after the while statement, am I right in thinking that the loop continues as long as x has a positive value then?

I am now 98% close to being there - played with different variations of my code until the wee hours - but am definitely still missing a little something.


Input of letters are excluded from the beginning with correct loop function - great, then wrong number input functions also - great.

The 'wrong' numbers are excluded from the beginning with correct functioning of the loop - good. However if a 'letter' is subsequently entered, I run into the whole input staying in the buffer problem.

Problem also occurs if I enter letters, followed by an unacceptable number, followed by another letter.

I tried putting one while loop into the other amongst other things but to no avail.

here is the code at present - including your simplification!

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
#include <iostream>
#include <string>
#include <limits>

using namespace std;

int main ()

{
int x=0;
bool right_integer = false;

cout << "your number please:-" << endl;

while (!(cin >> x)) 
	{
	cin.clear();
	cin.ignore(numeric_limits<streamsize>::max(),'\n');
	
	cout << "Please input a proper 'whole' number between 0 and 100000, thank you!: " << endl;
		
	}
	
while (!right_integer)
	{
		if (x <= 100000 && x > 0)
		{
		right_integer = true;
		}
			else
			{
			cout << "Pick a 'whole' positive number please between zero and 100000:" << endl;
			cin >> x;	
			}
	}
	

while (x)
	{
	cout << x-- << " ";
	}
	
	cout << endl << "All done! Nice!!" << endl;
	
return 0;
}

Line 33 is still a problem. Any use of cin is subject to errors that need to be handled to prevent the infinite output loop.

You could put your input code into a function call, then use that function to get input.

1
2
3
4
5
6
7
8
9
10
11
12
int getInt(){
	int x = 0;
	
	while(!(cin >> x)){
		cin.clear();
		cin.ignore(numeric_limits<streamsize>::max(),'\n');
		cout << "Invalid input.  Try again: ";
	}
	
	return x;
}


Then just make a call to getInt() every time you want to prompt the user to input an int, like this: x = getInt();
Otherwise, you have to duplicate your error checking code in every location you use cin.
Last edited on
Hi, thanks for the patience,

Am liking the idea of the functions, have been reading today and 'fiddling'

Still not perfect, however looking more robust. Still finding a few infinite loop outputs when different inputs are tried in different orders.

Could you please point me in the direction of my errors - my god this is a steep learning curve - only started learning last week! Wife not too pleased as you can imagine (a good 6hrs a day being consumed). Having fun though!!

Here are things as they stand:

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
57
58
59
#include <iostream>
#include <string>
#include <limits>

using namespace std;


int getInt()
	{
	int x=0;
	while (!(cin >> x))
		{
		cin.clear();
		cin.ignore(numeric_limits<streamsize>::max(),'\n');
		cout << "Please input a proper 'whole' number: " << endl;
		}
	return (x);
	}

int toobig()
{
cout << "Your number is too large, please enter something smaller: " << endl;
int x = getInt();
return (x);
}

int toosmall()
{
cout << "your number is negative, please enter a positive number: " << endl;
int x = getInt();
return (x);
}

	
int main ()
	{

	cout << "your number please:-" << endl;
	int x = getInt();

		if (x>100000)
		{
		toobig();
		}
		else if (x<0)
		{
		toosmall();
		}
		
		
		while (x)
		{
		cout << x-- << " ";
		}
	
	cout << endl << "All done! Nice!!" << endl;
	
	return 0;
	}


Many thanks,

Dan,

P.S. must get some sleep tonight, signing off.
Read these FAQs for some more ideas.
http://www.parashift.com/c++-faq-lite/input-output.html
Very nice thanks - although has caused me to have a major rewrite - no bad thing as the code is now certainly improved.

Topic archived. No new replies allowed.