Input validation

I need my program to use one of four user inputs (28, 29, 30 or 31) and only that, no characters, no decimals, no higher or lower number.

I've tried so many different loops and forums I'm going insane... it should be pretty simple, only four possible inputs.
28, 29, 30 and 31 are the possible amount of days there can be in a month and I'm gonna use that info for a loop right after this one.

There is three different loop in the code now that sort of work, but not really. If anyone want to use one of those to correct they're there.

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>

using namespace std;

int main()
{
	int month;
	int minTemp;
	int maxTemp; 
	int mmRainfall;
	int totalMmRainfall;

	cout << "Write the number of days in the month (28-31) ";
	cin >> month;
	
	while (!(month == 28, 29, 30, 31) || (cin >> month))
	{

		cout << "Write the number of days in the month (28, 29, 30 or 31) ";
		cin.clear();
		cin.ignore(100, '\n');
		cin >> month;

	}
	/*
	
	cout << "Write the number of days in the month (28-31) ";

	while (!(cin >> month))
	{
		cout << "Write the number of days in the month (28, 29, 30 or 31)  ";
		cin.clear();
		cin.ignore(100, '\n');
	}
	*/

	/*
	while (true)
	{
		cin >> month;
		if ((month > 31) || (month < 28))
			cout << "Write the number of days in the month (28, 29, 30 or 31)  ";

		else
			break;
	}
	*/

	for (int i = 0; i < month; ++i)
	{
		cout << "Day " << i+1 << ": " << endl;

		cout << "Write the lowest temperature: ";
		cin >> minTemp;

		cout << "Write the highest temperature: ";
		cin >> maxTemp;

		cout << "Write the amount of rainfall in mm: ";
		cin >> mmRainfall;
	}
	

	
	system("pause");

	return 0;

}
Last edited on
Try

1
2
while ((month != 28) && (month != 29) && (month != 30)&& (month != 31))
{getmonth}
{getmonth} comes up as unidentified, do i need to include something?
Sorry for confusion: getmonth is where you add your cin command.
Oh, yeah that works really well, but it still breaks when i type in 30.5 for example. Is there a way to fix that?
Int's use whole numbers if you want to use fractions use double.
Oh, sorry. what i mean is: I only want my program to accept whole number, and not break when someone types in a float. right now the only problem I've encountered is that it breaks when i type in one of the accepted number with a decimal point, for example 30.5, 29.9, 28.3 etc. is there a way to make it go into the loop if the user types one of the for-mentioned numbers?

Here is how it is now:

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

using namespace std;

int main()
{
	int month;

	int minTemp;
	int maxTemp; 
	int mmRainfall;

	int totalMinTemp;
	int totalMaxTemp;
	int totalMmRainfall;


	cout << "Write the number of days in the month (28-31) ";
	cin >> month;
	
	while ((month != 28) && (month != 29) && (month != 30) && (month != 31))
	{
		cout << "Write the number of days in the month (28, 29, 30 or 31) ";
		cin.clear();	
		cin.ignore(100, '\n');
		cin >> month;
	}
Last edited on
That is a problem with how cin works.
Cin will ignore periods and spaces.

If you type "28 30" it takes 28 and ignores everything after the space
Same when you type 28.5, it ignores the .5

So I think your code will work even if you type .5 it will be ignored.

Add cout after your cin to see what value cin actually took.
Ok, i guess i could make that work, but the way it is now it breaks the loops i have set up after this one.

Isn't there a way to put the ".5" inputs into the same loop that handles all the other invalid inputs? That way the only input that gets past the "input validation loop" is 28, 29, 30 or 31 and only that, any- and every-thing that isn't those numbers exactly gets thrown in the loop.
The only way I know how to do that is read the intput as a string, verify the string is "28" then convert to a int.

I'm sure there are ways but my knowledge with cin is limited.
Input validation:
-1- User will always press ENTER after every input → get a string from the user
-2- Try to convert that string to the data type you desire.

Notes:
- Code like this assumes that you are dealing with a human.
- Rather than force that to be the case, your program should actually fail on error.

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <ciso646>
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

//----------------------------------------------------------------------------
template <typename T>
bool string_to( const std::string& s, T& result )
{
  // Convert string argument to T
  std::istringstream ss( s );
  ss >> result >> std::ws;
 
  // Stream should be in good standing with nothing left over
  return ss.eof();
}

template <typename T>
T string_to( const std::string& s )
{
  T result;
  if (!string_to( s, result ))
    throw std::invalid_argument( "T string_to <T> ()" );
  return result;
}

//----------------------------------------------------------------------------
int input_integer( const char* prompt, const char* reprompt, int min, int max )
{
  int x;
  cout << prompt;
  while (true)
  {
    // Get user input as a string (user presses ENTER when done)
    string s;
    getline( cin, s );
    
    // Convert string to int and validate
    if (string_to( s, x ) and (x >= min) and (x <= max)) break;
    
    // If validation failed, prompt for try again
    cout << reprompt;
  }
  return x;
}

int input_days_in_month()
{
  return input_integer(
    "Enter the number of days in the month (28-31): ",
    "Invalid number of days. Try again: ",
    28, 31 );
}

int input_temperature( const char* prompt )
{
  return input_integer(
    prompt,
    "Invalid temperature. Try again: ",
    -200, 200
    );
}

//----------------------------------------------------------------------------
int main()
{
	int month;
	int minTemp;
	int maxTemp; 
	int mmRainfall;
	int totalMmRainfall;

        month = input_days_in_month();

	for (int i = 0; i < month; ++i)
	{
		cout << "Day " << i+1 << ": " << endl;

                minTemp = input_temperature( "Enter the lowest temperature (as a whole number): " );
                maxTemp = input_temperature( "Enter the highest temperature (as a whole number): " );
                mmRainfall = input_integer( 
                  "Enter the amount of rainfall in mm: ",
                  "Invalid. Try again: ",
                  0, 1000 );
	}
	

	
//	system("pause");

	return 0;

}

The string_to<type>() functions are designed to cleanly convert from string to whatever type you desire using the standard serialization method of that type. It will catch errors like "12z" or ".7". Leading and trailing whitespace is ignored.

Hope this helps.
Hope this helps.
Topic archived. No new replies allowed.