Trash output when inputing a char into an int

Really loving how the body is already preset with "write your question here" and the proper flag for our code.
ANYWAY!!

I'm not necessarily having an issue (great way to discourage help). I just want to better understand the use of cin, the keyboard buffer, and the interaction of variables with their input types.

The subject for today is inputting a char into an int variable and the craziness that rapidly ensues at the output. The focus is the "readTestandHwScore" function.

I'm observations:
- nothing gets assigned during the first iteration
- all subsequent iterations skip the "cin" statement
- I am somehow getting two iterations before the system("pause") stops it from overflowing.

So, I would love to know how to prevent this. I've seen a few threads recommend cin.fail (i think that's the call out anyway). But i'm more curious as to why it do what it do when it fails.

My assumptions:
- the first term doesn't accept anything
- The keyboard buffer then doesn't clear
- iteration two gets assigned a random value
- ???
- profit

Contents of Interest:
Line 32 - "readTestandHwScore" function
Line 40 - do-while input loop.

Current Output:
Let's figure out if your passing.

What were your scores for this term:
Test 1: a
Press any key to continue . . . [ENTER]

Test 2:
No way you have a 1.2659e+231
Try that again...
Press any key to continue . . . [NO INPUT]
Test 2:
No way you have a 1.2659e+231
Try that again...
Press any key to continue . . . [ENTER]

Test 2:
No way you have a 1.2659e+231
Try that again...
Press any key to continue . . . [NO INPUT]
Test 2:
No way you have a 1.2659e+231
Try that again...
Press any key to continue . . . [Stopped program through eclipse]


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


// List of Functions:
void 	readTestandHwScore	(double &, double &, double &);
void	printFinalScore		(double);
double	calcFinalScore		(double, double, double);


int main (){

	double	scoreTEST1,
			scoreTEST2,
			scoreHW;

	cout << "Let's figure out if your passing."
			<< endl << endl;

	cout << "What were your scores for this term:"
			<< endl;;

	readTestandHwScore(scoreTEST1, scoreTEST2, scoreHW);

	printFinalScore(calcFinalScore(scoreTEST1, scoreTEST2, scoreHW));

	return 0;
}

void readTestandHwScore (double &test1, double &test2, double &hw)
{
	int check;
	double scoreARRAY[3];
	string	scoreTYPE[]{ "Test 1", "Test 2", "Homework"};

	for (check = 0 ; check < 3 ; check++)
	{
		do {
			cout << scoreTYPE[check]<< ": ";
			cin >> scoreARRAY[check];

			if(scoreARRAY[check] < 0)
				cout	<< endl
						<< "A negative score is not possible\n"
						"Please re-enter..."
						<< endl;
			else if(scoreARRAY[check] > 100)
				cout 	<< endl
						<< "No way you have a "<< scoreARRAY[check]
						<< "\nTry that again..."
						<< endl;
			system("pause");
			} while (scoreARRAY[check] < 0 || scoreARRAY[check] > 100);

	}
	test1 = scoreARRAY[0];
	test2 = scoreARRAY[1];
	hw = scoreARRAY[2];
}

void printFinalScore(double avg)
{
	// Evaluate scoreAVG for it's corresponding letter grade
	//	A: >=90 B: >=80 C: >=70 D: >=60 F: <60

	char	scoreLETTER[]{ 'F', 'D', 'C', 'B', 'A'};
	int		scoreCOMP[]{0, 60, 70, 80, 90},
			set,
			check;

	cout << setprecision(2) << fixed << showpoint << right;
	cout << "Your average is: " << avg
			<< endl;

	for(check = 0 ; check < 5 ; check++)
	{
		if (avg >= scoreCOMP[check])
			set = check;
	}

	cout << "You have a "<< avg << " - " << scoreLETTER[set];
}

double calcFinalScore(double test1, double test2, double hw)
{
	double scoreAVG = 0;

	// Test scores are 40% and Homework is 20%

	scoreAVG = (test1 + test2)*0.4 + (hw*0.2);

	return scoreAVG;
}
Last edited on
If all you want is an int:
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
#include <iostream>
#include <string>

int main()
{
   std::string input    = "";
   int         response = 0;

   while (true)
   {
       std::cout << "Enter an int: ";
       std::getline(std::cin, input);

      try
      {
         response = std::stoi(input);
         break;
      }

      catch (...)
      {
         std::cout << "No, no, no, I want an int, try again.\n\n";
         continue;
      }
   }

   std::cout << "\nOkay, you entered " << response << '\n';
}
Enter an int: t
No, no, no, I want an int, try again.

Enter an int: hello
No, no, no, I want an int, try again.

Enter an int: 5

Okay, you entered 5
Another way to validate input:

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

int main()
{
   int response = 0;

   while (true)
   {
      std::cout << "Enter an int: ";
      
      // the input stream will error if it can't extract an int
      if (!(std::cin >> response))
      {
         std::cout << "No, no, no, I want an int, try again.\n\n"; 
         
         // clear the error bit
         std::cin.clear();
         
         // extract and throw away what's left in the input stream buffer
         // the maximum number of characters the input stream can hold
         std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
         continue;
      }
      break;
   }

   std::cout << "\nOkay, you entered " << response << '\n';
}
Enter an int: t
No, no, no, I want an int, try again.

Enter an int: t5
No, no, no, I want an int, try again.

Enter an int: 5t

Okay, you entered 5
So what you're telling me is I can use !(cin >> variable) to check for a failed input?

for example if, I was determined to use do-whiles to use a sentry I could write something like:

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
double getRadius(){

double userINPUT;

	cout << "Give me the length of your\n"
		"circle's radius."
		<< endl << endl;

	do{
	
	cout << "Radius: ";
	cin << userINPUT;
	cout << endl;
	
	if (userINPUT < 0)
		cout << "That's not a valid entry.\n"
			"Please input a positive number..."
			<< endl << endl;
	else if (!(cin << userINPUT))
	{
		cout << "That's not a valid entry.\n"
			"Please input an integer..."
			<< endl << endl;
		cin.clear();
		cin.ignore(10, '\n');
	}
	
	} while (userINPUT < 0 || !(cin << userINPUT))

	return userINPUT;

}


I'm working with what's been covered by my class so far, but I'd like to get to know a bit more.

Edit:

I'm noticing now that the only place you called cin was in the if statement's argument. You can call an object from with in the argument or was that a mistake?
Last edited on
Was also wondering about how you set up your while loop.
1
2
3
4
5
6
7
8
9
10
   while (true)
   {

      if (!(std::cin >> response))
      {
         continue;
      }

      break;
   }


I'm assuming it's to dictate the course of the loop through the if statements without rewriting every possible criteria in the while statement's argument.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <limits>

int main()
{
   int response = 0;
   int min      = 1;
   int max      = 7;

   do
   {
      std::cout << "Enter an int between 1 and 7: ";

      if (!(std::cin >> response))
      {
         std::cin.clear();
         std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
         continue;
      }
   } while (response < min || response > max);

   std::cout << "\nOkay, you entered " << response << '\n';
}
Enter an int between 1 and 7: t
Enter an int between 1 and 7: -1
Enter an int between 1 and 7: 8
Enter an int between 1 and 7: 5

Okay, you entered 5

You can also have a menu system:
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 <vector>

unsigned short Menu(const std::vector<std::string>&);

int main()
{
   std::vector<std::string> query = { "What do you want to do: ",
                                       "Fight", "Stand Guard", "Evade", "Flee" };
   
   unsigned short response = Menu(query);

   std::cout << "\nOkay, you chose '" << query[response] << "'.\n";
}

unsigned short Menu(const std::vector<std::string>& stringArray)
{
   unsigned short response = 0;
   size_t         size = stringArray.size() - 1;
   std::string    input = "";

   std::cout << stringArray[0] << '\n';

   while (response < 1 || response > size)
   {
      for (size_t i = 1; i <= size; i++)
      {
         std::cout << " " << i << ") " << stringArray[i] << '\n';
      }
      std::cout << ": ";

      std::getline(std::cin, input);

      try
      {
         response = std::stoi(input);
      }

      catch (...)
      {
         continue;
      }
   }
   return response;
}
What do you want to do:
 1) Fight
 2) Stand Guard
 3) Evade
 4) Flee
: hello
 1) Fight
 2) Stand Guard
 3) Evade
 4) Flee
: 2

Okay, you chose 'Stand Guard'.
Topic archived. No new replies allowed.