Proper use of cin.ignore() to clear user input.

Hello All,
I've learned a great deal of information over the past few weeks as I've looked around. I was looking at how to handle an error condition when a user provides an incorrect input type. I came across a thread that talked about using a while loop to solve this. The thread was here

http://www.cplusplus.com/forum/beginner/21595/

and the post was by jRaskell.

The code that I'm using from the thread looked like this:

1
2
3
4
5
6
7
8
	while(!(cin >> gross))
	{
		
		cout << "Your entry must be a valid numeric value." << endl; 
		cin.clear();
		cin.ignore(numeric_limits<streamsize>::max(), '\n');
		cout << "What is " << empFirstName << "'s monthly salary? ";
	}


The problem this creates is that if the user typo's characters in the middle or end of the input number, the program only stores the numbers up to the first non-numeric character and does not clear the input stream as I expected.

For example, if the user inputs 123;.45 when prompted, then the program will store 123 to gross and leave the ;.45 on the input stream. The next input in my program is a check for a yes or no response from the user to loop back. That check responds to each character that follows the 123 from the previous input.

If I replace

 
cin.ignore(numeric_limits<streamsize>::max(), '\n');


with just cin.ignore(), the problem is the same. Why does this happen?

Here is my completed code so you can see what happens.
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
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
#include <cmath>
using namespace std;


int myRythm()
{

	string empFirstName, empLastName;
	double gross, fedTax, stateTax, socMed, netPay;


	cout << "What is the employee's first name: ";
	cin >> empFirstName;
	cout << "What is the employee's last name: ";
	cin >> empLastName;
	cout << "What is " << empFirstName << "'s monthly salary? ";

        // This is where I need help

	while(!(cin >> gross))
	{
		
		cout << "Your entry must be a valid numeric value." << endl; 
		cin.clear();
		cin.ignore(numeric_limits<streamsize>::max(), '\n');
		cout << "What is " << empFirstName << "'s monthly salary? ";
	}
	cout << "____________________________________________________" << endl;
	cout << "  " << empFirstName << " " << empLastName << endl;
	cout << setfill('.') << left << setw(40) << "| Gross Salary: ";
	cout << " $";
	cout << setfill(' ') << right << setw(8) << fixed << setprecision(2) << gross << " |" << endl;
}

int main()
{
	start:
	myRythm();


	another:
	cout << endl << "----------------------------------------------------------------------";
	cout << endl << "Would you like to perform another calculation? (y/n)" << endl;
	char choice;
	cin >> choice;
	if (toupper(choice) == 'Y')
	{
		cin.ignore();
		goto start;
	}
	else if (toupper(choice) == 'N')
	{
		goto stop;
	}
	else
	{
		cout << "Please enter the letter Y for \"yes\" or the letter N for \"no\"." << endl;
		goto another;
	}
	
	
	stop:
	return 0;

}
Last edited on
If the user enters "123;.45" the gross variable will be set to 123 and the loop will not run, so ";.45" still remains inside the stream. If you want to remove the rest of the line you need to call ignore after >> has succeeded as well.
Peter87 wrote:
If the user enters "123;.45" the gross variable will be set to 123 and the loop will not run, so ";.45" still remains inside the stream. If you want to remove the rest of the line you need to call ignore after >> has succeeded as well.


In these cases it would probably be best to clear the input and re-prompt the user for the correct input. This why was I tried replacing
1
2
3
4
 cin.ignore(numeric_limits<streamsize>::max(), '\n');
[code]

with just [code]cin.ignore()
.

I'm sorry. I should have made that clearer. So there are currently 3 error conditions I have tested with this code.

Condition 1: The user inputs only non-numeric characters. (eg. "a" or "abc")
Condition 2: The user inputs non-numeric characters first followed by the correct numeric value. (eg. "a123.45" or "abc123.45")
Condition 3: The user starts to enter a numeric value but typos non-numeric characters after entering at least 1 numeric value. (eg. "123a.45" or "123.45a")

Condition 1 results in prompting the user to input a correct value.
Condition 2 results in storing the value that proceeds the non-numeric character
Condition 3 results in storing only the numeric value that precedes the first non-numeric character and leaves the remaining input on the cin buffer.

For this situation, it would be best if all three conditions responded the way that Condition 1 responds.

Adding cin.ignore(); after the while loop also does not clear the remaining items in the input buffer.
fiberglasscivic wrote:
Adding cin.ignore(); after the while loop also does not clear the remaining items in the input buffer.

cin.ignore() removes a single character. If you want to remove the whole rest of the line you have to call it the way you do inside the loop.

For this situation, it would be best if all three conditions responded the way that Condition 1 responds.

One way I can think of is to add getline to the loop condition and check if the rest of the line is an empty string (or contains only whitespace characters).
Last edited on
I think I have found a workable solution while doing some research on the forums. So far, the layout detailed in the following thread is working for what I need.

http://www.cplusplus.com/forum/articles/6046/
Topic archived. No new replies allowed.