Hello all, I have been working on a homework assignment that has to build a program for a user to enter student's grades and see the student's average as well as a class avaerage. Besides some cleaning up, organizing, and labeling I am pretty happy with it and it is working. Just one issue not working and I am not sure why. Here is the code:

while (!anotherStudent)
	{
		cout << "Please enter the Student's Name: ";
		getline(cin, studentName);
		cout << endl;
		
		studentAverage = studentGrades();
		sumOfStudentAverages = sumOfStudentAverages + studentAverage;

		cout << "Do you have another Student's grades to record(Yes or No): ";
		cin >> answer;
		cout << endl;

		switch (answer)
		{
		case 'Y':
		case 'y':
			cout << studentName << " has ";
				if (studentAverage >= 90)
					cout << "an \"A\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 80)
					cout << "a \"B\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 70)
					cout << "a \"C\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 60)
					cout << "a \"D\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage < 60)
					cout << "a \"F\" Average with a score of " << studentAverage << "." << endl;
			anotherStudent = false;
			count++;
			break;
		case 'N':
		case 'n':
			cout << studentName << " has ";
				if (studentAverage >= 90)
					cout << "an \"A\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 80)
					cout << "a \"B\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 70)
					cout << "a \"C\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 60)
					cout << "a \"D\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage < 60)
					cout << "a \"F\" Average with a score of " << studentAverage << "." << endl;
			anotherStudent = true;
			break;			
		default:
			cout << "Please type Y or N: " << endl;
		}
	}

When you are entering the first student or entering the while loop for the first time, it prompts you to enter the student name. However, when you are prompted to enter another student, if you type y, it prints the prompt for student name but then it immediatley goes to the studentGrades function, and prompts you to enter score 1. It stores a " " in the string for studentName. Let me know if you need to see more code, but I think this is enough. Now I know I have read something about a pause function on the internet but I have not learned that yet in class and I am pretty sure I need to keep it to what I have learned in my last few chapters. Any ideas? Thanks in advance.

Recommended Answers

All 13 Replies

If you look on the main C++ page in Daniweb you will see a posting "How do I flush the input stream".
This should help

commented: Thank you for pointing me to that thread. +1

Between lines 11 and 12 put cin.ignore( numeric_limits<streamsize>::max(), '\n' ); The stream >> operator only reads what you ask it to, and leaves everything else behind in the input buffer. However, whenever dealing with user input you must expect that the user will press the ENTER key after everything you ask him to enter.

getline() reads everything except the ENTER key, stores it in a string, then reads and throws away the ENTER key.

cin >> anything, in contrast, only reads anything, and leaves everything else (including that pesky ENTER key) in the input stream. So the next time you call getline(), it does what it did before, reading '' and sticking it in to a string, then reads the ENTER key and throws it away.

So, after using >> you must explicitly read and throw away that ENTER key so that it isn't still there the next time you try to get input from the user.

Hope this helps.

commented: Thank you for explaining it so clearly! +1

Thank you both for your reply. I am just trying to make sure I understand this......so the problem is not the loop but the last input that is taken. When it asks, Do you have another student to enter? The user hits "y" then "enter"; "y" is stored in "answer" and the enter key is carried over to the string. Getline then throws away the enter key and causes the string to be filled with a null value then goes to the next prompt?

I read the other thread and saw what I need to add to the code, and just making sure I understand what it is doing, it is throwing away the enter key after the "y" or once the input for "answer" is given. Correct?

yes that's right and to correct the problem use

std::cin.ignore(1);

When you read in the character into answer, you are actually reading in two characters. The first character is 'y', the second character is '\n'. The 'y' is grabbed and stuck into the variable answer. That leaves the '\n' still in that buffer. Next comes the getline command. Let's pretend nothing was in the buffer. You have this command:

getline (cin, studentName);

If there was nothing in the buffer and the user just hit the return key, that's a perfectly legal entry. The empty string ("") would be placed in the studentName.

Now with the newline character ('\n') already in the buffer, when the computer hits that command, it treats the newline character the same as if it was typed in AFTER the getline command was issued. It makes no distinction between whether that Enter key was typed before or after the user is prompted by the getline command. Hence an empty string is placed into studentName and the computer doesn't pause for user input since it thinks it already HAS enough input to do its job and so doesn't wait for any more. That's why the input stream needs to be flushed out before the getline command.

So yes, I think you have a correct understanding.

Ok so....If I added std::cin.ignore(1); That just ignores 1 char right? Or does that make it ignore everything after the first char that it stores? Sorry to sound like such a rookie, this is my first C++ class and I really want to make sure I understand it all correctly.

I will go home, make the changes to my code and post it here, if it works, I will mark as solved, if not, I will annoy you more ;) Thanks guys.

I think you should ignore more than 1 character. That'd be enough if the person actually does only enter one character, which is what they are supposed to. But what if they get ahead of themselves, like we all do, and forget that they have to just type in one character, and they type in "Jonathon" or something? In other words, go straight for the name entry by accident. The buffer takes in "Jonathon", plus the '\n', stores 'J' in the character variable answer, throws away 1 character, which is the first 'o' in "Jonathon", then you write an error message to type 'y' or 'n', "nathon" is left in the buffer, the variable answer grabs the first letter 'n', the computer thinks that means the user is done, and exits, when it was just a mistake. I say think of some number like 256 that's bigger than any possible name, and throw that many characters away, which'll clear the entire input stream.

http://www.cplusplus.com/reference/iostream/istream/ignore.html

commented: Thanks for the help, I understand it now. +1

Edited: Ok I spoke to soon if you saw my post before I edited. It worked for one part but it is still not letting me type in the next student name. Here is the new code:

while (!anotherStudent)
	{
		cout << "Please enter the Student's Name: ";
		getline(cin, studentName);
		std::cin.ignore(500);
		cout << endl;
		
		studentAverage = studentGrades();
		sumOfStudentAverages = sumOfStudentAverages + studentAverage;

		cout << "Do you have another Student's grades to record(Yes or No): ";
		cin >> anotherStudent;
		std::cin.ignore(500);
		cout << endl;

		cout << studentName << " has ";
				if (studentAverage >= 90)
					cout << "an \"A\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 80)
					cout << "a \"B\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 70)
					cout << "a \"C\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage >= 60)
					cout << "a \"D\" Average with a score of " << studentAverage << "." << endl;
				else if (studentAverage < 60)
					cout << "a \"F\" Average with a score of " << studentAverage << "." << endl;
	}

I changed the way I was handling the bollean expression, thats why it looks different. However, it still will not let me tyoe in the next student's name. I tride placing std::cin.ignore(500); in a couple of places and it still skips. Also for my other function I did this:

double studentGrades()
{
	double score;
	double average;
	double sum = 0;
	int count = 1;

	bool moreGrades = false;

	while (!moreGrades)
	{
		cout << "Please enter score " << count << ":";
		cin >> score;
		cout << endl;

		sum = sum + score;
		
		cout << "Do you have more grades to record(Yes or No): ";
		cin >> moreGrades;
		std::cin.ignore(100);
		cout << endl;
		}


	average = sum / count;

	return average;
}

I tried implementing the same thing here thinking when they replied yes or no to another score, it would take the "y" or "n" and change the boolean as needed. However if I type "yes" it constantly adds its own score, which I am sure is representing ascii some how, and answers the question again never ending. So I am sorry, a little more explanation please.

It is not working because you failed to obey my advice.

Read up on istream::ignore() to find out why it fails.

First off, I am not a dog, I don't obey! I took everyone's advice and ran it by my prof, he had a different way of doing it all together that is working. Thank you everyone for your help I did learn quite a bit through the proccess.

Keep in mind that we have run across many professors who teach quite the opposite of good practice.

And secondly, if you are going to ask for advice you can't ignore the advice given you and complain things still don't work. I didn't walk into your house and tell you to sit. I answered your question.

I am sure you do. I know every programmer has their own style and I was not in any way insulting the advice given, unfortunatley for an online forum there is not the advantage of sitting down and talking it out as everything has to be posted and wait for a reply. Also, another disadvantage to everyone here is you have to expect I know what I am talking about when I have a question and in this case I misunderstood what I was trying to do and I am sure that caused confusion.

The only thing that I was responding negativley too was the language Duoas was using when he thought I did not take his advice. I did take his advice and it did not work. I am sure he and everyone else would have had the correct advice if I had explained what I was trying to do properly.

Lastly, I always try every advice given to me. I did not ignore your advice Duoas, I simply did not respond to you because other there were other people were responding that were online.

Again, thank you for all your help and I mean that. I learned quite a bit through this proccess. I think we can all agree that experience is the best teacher and that is all I am trying to gain now. Most of you will notice I added to your rep, including you Duoas.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.