Problem with getting programs to run again

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 4276 Views - Last Post: 20 January 2011 - 10:03 AM Rate Topic: -----

#1 DivideByZero  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 238
  • View blog
  • Posts: 551
  • Joined: 02-December 10

Problem with getting programs to run again

Posted 19 January 2011 - 08:40 AM

I've been having issues (particularly in C++ for some odd reason) with getting my programs to run again should the user desire.
I had this problem with an assignment I had before the christmas holidays, which resorted to me removing the option to run again. But now I just want to know what is wrong with my logic as even my tutor can't seem to work it out.

So I've been reading through "Accelerated C++" again in preparation for the inevitable bunch of assignments that will be thrown at me soon. And in chapter 3, one of the exercises is to get the program to run for every student the user wants.

The program calculates each student's final grade using the requirements documented in the book.
The intended output is, after asking the user "Do you want to compute another student\'s grade? (Y/N)", the program should loop to the beginning and run the program again (storing the new name and final grade into a new vector element).
What actually happens is that the program runs all the code once and doesn't even allow the user to decide whether to run the program again.

#include <iomanip>	// For setprecision.
#include <ios>	// For streamsize.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>	// For sort().

using namespace std;

int main()
{
	vector<string> studentNames;
	vector<double> studentGrades;
	bool runProgramAgain = true;

	while (runProgramAgain)
	{
		// Ask for student name and add name into studentNames vector.
		cout << "Please enter your first name: ";
		string name;		
		cin >> name;
		cout << "Hello, " << name << "!" << endl;
		studentNames.push_back(name);

		// Ask for midterm and final exam grades.
		cout << "Please enter your midterm and final exam grades: ";
		double midterm = 0, final = 0;
		cin >> midterm >> final;

		// Ask for homework grades.
		cout << "Enter all your homework, followed by end of file: ";
		
		vector<double> homeworkGrades;
		double readHomeworkGrades = 0;	

		while (cin >> readHomeworkGrades)
		{
			homeworkGrades.push_back(readHomeworkGrades);
		}
		
		typedef vector<double>::size_type HG_VectorSize;
		HG_VectorSize HGsize = homeworkGrades.size(); 

		if (HGsize == 0)	// Check that user entered atleast one grade.
		{
			cout << endl << "You must enter your grades. Please try again." << 
				endl;
			return 1;
		}

		// Sort grades out in ascending order.
		sort(homeworkGrades.begin(), homeworkGrades.end());	

		// Compute median homework grade.
		HG_VectorSize midElement = HGsize / 2;
		double median = 0;
		median = HGsize % 2 == 0 ?
			(homeworkGrades[midElement] + homeworkGrades[midElement - 1]) / 2 :
			homeworkGrades[midElement];

		// Compute lower quartile.
		HG_VectorSize lowerQuartile = midElement / 2;
		double lowerQuartileTotal = 0;

		for (unsigned int i = 0; i < lowerQuartile; i++)
		{
			lowerQuartileTotal += homeworkGrades[i];
		}

		// Compute upper quartile.
		HG_VectorSize upperQuartile = midElement + lowerQuartile;
		double upperQuartileTotal = 0;

		for (unsigned int i = midElement; i < upperQuartile; i++)
		{
			upperQuartileTotal += homeworkGrades[i];
		}

		// Show quartile with the largest value.
		lowerQuartileTotal > upperQuartileTotal ? 
			cout << "\n The lower quartile has the largest value (" << 
			lowerQuartileTotal << ")." :
			cout << "\n The upper quartile has the largest value (" <<
			upperQuartileTotal << ").";

		// Compute and write final grade.
		streamsize precision = cout.precision();
		cout << "\nYour final grade is " << setprecision(3) <<
			(0.2 * midterm) + (0.4 + final) + (0.4 * median) <<
			setprecision(precision) << endl;

		// Add final grade into the studentGrades vector.
		double finalGrade = (0.2 * midterm) + (0.4 + final) + (0.4 * median);
		studentGrades.push_back(finalGrade);

		// Ask whether to run program again for a different student.
		cout << "\n Do you want to compute another student\'s grade? (Y/N)" <<
			endl;
		cout << "Option: ";
		char runAgain;
		cin >> runAgain;

		if (!(runAgain == 'Y' || runAgain == 'y'))
		{
			runProgramAgain = false;
		}
	}

	// Show all students final grades.
	int vectorsSize = studentGrades.size();

	for (int i = 0; i < vectorsSize; i++)
	{
		cout << studentNames[i] << "\'s final grade is: " << studentGrades[i];
	}

	return 0;
}



So can anyone help me understand why this doesn't run the program again? The logic makes sense to me and others I've showed this code to, so I'm just really confused as to why this doesn't work.

Thank you for your time :)

This post has been edited by DivideByZero: 19 January 2011 - 08:41 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Problem with getting programs to run again

#2 simeesta  Icon User is offline

  • Deadly Ninja


Reputation: 218
  • View blog
  • Posts: 590
  • Joined: 04-August 09

Re: Problem with getting programs to run again

Posted 19 January 2011 - 08:46 AM

I think newline is being read after the input, so it doesn't loop again.

This post has been edited by simeesta: 19 January 2011 - 08:47 AM

Was This Post Helpful? 0
  • +
  • -

#3 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Problem with getting programs to run again

Posted 19 January 2011 - 08:50 AM

The problem is here.

Sorry, that was wrong.

This post has been edited by r.stiltskin: 19 January 2011 - 09:02 AM

Was This Post Helpful? 0
  • +
  • -

#4 DivideByZero  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 238
  • View blog
  • Posts: 551
  • Joined: 02-December 10

Re: Problem with getting programs to run again

Posted 19 January 2011 - 08:55 AM

I altered the code to the below, but the program still doesn't run again. It just shows the only student's grade again.

if (!(runAgain == 'Y'))
{
	runProgramAgain = false;
}
else if (!(runAgain == 'y'))
{
	runProgramAgain = false;
}


This post has been edited by DivideByZero: 19 January 2011 - 08:56 AM

Was This Post Helpful? 0
  • +
  • -

#5 r.stiltskin  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1833
  • View blog
  • Posts: 4,927
  • Joined: 27-December 05

Re: Problem with getting programs to run again

Posted 19 January 2011 - 09:17 AM

There was nothing wrong with your original logic. The problem is that after you use EOF to terminate the loop reading in homework grades, the EOF flag is set for cin so it doesn't wait for your Y/N answer to re-run.

You have to clear the stream after that input loop:
        while (cin >> readHomeworkGrades)
        {
            homeworkGrades.push_back(readHomeworkGrades);
        }
        cin.clear();


This post has been edited by r.stiltskin: 19 January 2011 - 09:19 AM

Was This Post Helpful? 1
  • +
  • -

#6 I_cant_C  Icon User is offline

  • D.I.C Head

Reputation: 19
  • View blog
  • Posts: 67
  • Joined: 02-December 09

Re: Problem with getting programs to run again

Posted 19 January 2011 - 09:45 AM

I thought it was that too r.stiltskin and tried it to no avail, so if that is the solution my IDE must be set up wrongly or something (code::blocks)... I'll continue to see if I can get that code to work - as this is the best way for me to learn c++ ;)
Was This Post Helpful? 0
  • +
  • -

#7 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 972
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Problem with getting programs to run again

Posted 19 January 2011 - 10:23 AM

r.stiltskin correctly pointed out you need to reset the error flag set by the EOF character entered to end the numeric input. But the EOF character is still pending in the input buffer. So when you check the user's input to see if the user wants to loop, the EOF character is extracted and the test fails:

...
while (cin >> readHomeworkGrades)
{
	homeworkGrades.push_back(readHomeworkGrades);
}

cin.clear(); // reset error flag cuased by EOF
cin.sync();  // remove the character ^Z from input buffer

typedef vector<double>::size_type HG_VectorSize;
...
// Ask whether to run program again for a different student.
cout << "\n Do you want to compute another student\'s grade? (Y/N)" <<
	endl;
cout << "Option: ";
char runAgain;  <<<<<<<<<<<<<<<<<<<<<<<<<
cin >> runAgain;

if (!(runAgain == 'Y' || runAgain == 'y'))
{
	runProgramAgain = false;
}
...


This post has been edited by n8wxs: 19 January 2011 - 10:24 AM

Was This Post Helpful? 2
  • +
  • -

#8 I_cant_C  Icon User is offline

  • D.I.C Head

Reputation: 19
  • View blog
  • Posts: 67
  • Joined: 02-December 09

Re: Problem with getting programs to run again

Posted 19 January 2011 - 10:33 AM

ooo thanks - that's great to know, I did try cin.sync(); - but on its own. I am still pretty new to c++ overall, but hope to eventually get to a point where I can actually help others on this site (which I think is a great site btw). :)
Was This Post Helpful? 0
  • +
  • -

#9 DivideByZero  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 238
  • View blog
  • Posts: 551
  • Joined: 02-December 10

Re: Problem with getting programs to run again

Posted 19 January 2011 - 11:00 AM

I've made some changes to the code.

#include <iomanip>	// For setprecision.
#include <ios>	// For streamsize.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>	// For sort().

using namespace std;

int main()
{
	vector<string> studentNames;
	vector<double> studentGrades;
	bool runProgramAgain = true;

	do
	{
		// Ask for student name and add name into studentNames vector.
		cout << "Please enter your first name: ";
		string name;		
		cin >> name;
		cout << "Hello, " << name << "!" << endl;
		studentNames.push_back(name);

		// Ask for midterm and final exam grades.
		cout << "Please enter your midterm and final exam grades: ";
		double midterm = 0, final = 0;
		cin >> midterm >> final;

		// Ask for homework grades.
		cout << "Enter all your homework, followed by end of file: ";
		
		vector<double> homeworkGrades;
		double readHomeworkGrades = 0;	

		while (cin >> readHomeworkGrades)
		{
			homeworkGrades.push_back(readHomeworkGrades);
		}
		
		cin.clear();	// Resets error flag caused by EOF.
		cin.sync();	// Removes the character ^Z from input buffer.
		typedef vector<double>::size_type HG_VectorSize;
		HG_VectorSize HGsize = homeworkGrades.size(); 

		if (HGsize == 0)	// Check that user entered atleast one grade.
		{
			cout << endl << "You must enter your grades. Please try again." << 
				endl;
			return 1;
		}

		// Sort grades out in ascending order.
		sort(homeworkGrades.begin(), homeworkGrades.end());	

		// Compute median homework grade.
		HG_VectorSize midElement = HGsize / 2;
		double median = 0;
		median = HGsize % 2 == 0 ?
			(homeworkGrades[midElement] + homeworkGrades[midElement - 1]) / 2 :
			homeworkGrades[midElement];

		// Compute lower quartile.
		HG_VectorSize lowerQuartile = midElement / 2;
		double lowerQuartileTotal = 0;

		for (unsigned int i = 0; i < lowerQuartile; i++)
		{
			lowerQuartileTotal += homeworkGrades[i];
		}

		// Compute upper quartile.
		HG_VectorSize upperQuartile = HGsize - lowerQuartile;
		double upperQuartileTotal = 0;

		for (unsigned int i = upperQuartile; i < HGsize; i++)
		{
			upperQuartileTotal += homeworkGrades[i];
		}

		// Show quartile with the largest value.
		lowerQuartileTotal > upperQuartileTotal ? 
			cout << "\n The lower quartile has the largest value (" << 
			lowerQuartileTotal << ")." :
			cout << "\n The upper quartile has the largest value (" <<
			upperQuartileTotal << ").";

		// Compute and write final grade.
		streamsize precision = cout.precision();
		cout << "\nYour final grade is " << setprecision(3) <<
			(0.2 * midterm) + (0.4 + final) + (0.4 * median) <<
			setprecision(precision) << endl;

		// Add final grade into the studentGrades vector.
		double finalGrade = (0.2 * midterm) + (0.4 + final) + (0.4 * median);
		studentGrades.push_back(finalGrade);

		// Ask whether to run program again for a different student.
		cout << "\n Do you want to compute another student\'s grade? (Y/N)" <<
			endl;
		cout << "Option: ";
		char runAgain;
		cin >> runAgain;

		if (!(runAgain == 'Y'))
		{
			runProgramAgain = true;
		}
		if (!(runAgain == 'y'))
		{
			runProgramAgain = true;
		}
	} while (runProgramAgain);

	// Show all students final grades.
	int vectorsSize = studentGrades.size();

	for (int i = 0; i < vectorsSize; i++)
	{
		cout << studentNames[i] << "\'s final grade is: " << studentGrades[i];
	}

	return 0;
}



This doesn't logically make sense, but it works :S
*Edit* Actually it does the opposite of what the original problem was and keeps looping the program regardless of what the user chooses. :(
if (!(runAgain == 'Y'))
{
	runProgramAgain = true;
}
if (!(runAgain == 'y'))
{
	runProgramAgain = true;
}


This post has been edited by DivideByZero: 19 January 2011 - 11:04 AM

Was This Post Helpful? 0
  • +
  • -

#10 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: Problem with getting programs to run again

Posted 19 January 2011 - 11:02 AM

!(runAgain == 'Y')


why not use the following?

runAgain!='Y'

Was This Post Helpful? 0
  • +
  • -

#11 DivideByZero  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 238
  • View blog
  • Posts: 551
  • Joined: 02-December 10

Re: Problem with getting programs to run again

Posted 19 January 2011 - 11:06 AM

View Postishkabible, on 19 January 2011 - 11:02 AM, said:

!(runAgain == 'Y')


why not use the following?

runAgain!='Y'

It's the same if I do that, that was originally what I did before I changed it to what it is now :)
Was This Post Helpful? 0
  • +
  • -

#12 I_cant_C  Icon User is offline

  • D.I.C Head

Reputation: 19
  • View blog
  • Posts: 67
  • Joined: 02-December 09

Re: Problem with getting programs to run again

Posted 19 January 2011 - 11:07 AM

There's no way out of your do-while loop now :\


EDIT: After adding what n8wxs said, it worked fine as it was - only changed:

cout << studentNames[i] << "\'s final grade is: " << studentGrades[i];


to:
cout << studentNames[i] << "\'s final grade is: " << studentGrades[i] <<endl;

This post has been edited by I_cant_C: 19 January 2011 - 11:12 AM

Was This Post Helpful? 1
  • +
  • -

#13 DivideByZero  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 238
  • View blog
  • Posts: 551
  • Joined: 02-December 10

Re: Problem with getting programs to run again

Posted 19 January 2011 - 11:12 AM

View PostI_cant_C, on 19 January 2011 - 11:07 AM, said:

There's no way out of your do-while loop now :\

Yeah I just realised that :)

Here's the current version.
   if (runAgain != 'Y')
   {
   	runProgramAgain = false;
   }
   if (runAgain != 'y')
   {
	runProgramAgain = false;
   }
} while (runProgramAgain);



And here's the whole modified code.
#include <iomanip>	// For setprecision.
#include <ios>	// For streamsize.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>	// For sort().

using namespace std;

int main()
{
	vector<string> studentNames;
	vector<double> studentGrades;
	bool runProgramAgain = true;

	do
	{
		// Ask for student name and add name into studentNames vector.
		cout << "Please enter your first name: ";
		string name;		
		cin >> name;
		cout << "Hello, " << name << "!" << endl;
		studentNames.push_back(name);

		// Ask for midterm and final exam grades.
		cout << "Please enter your midterm and final exam grades: ";
		double midterm = 0, final = 0;
		cin >> midterm >> final;

		// Ask for homework grades.
		cout << "Enter all your homework, followed by end of file: ";
		
		vector<double> homeworkGrades;
		double readHomeworkGrades = 0;	

		while (cin >> readHomeworkGrades)
		{
			homeworkGrades.push_back(readHomeworkGrades);
		}
		
		cin.clear();	// Resets error flag caused by EOF.
		cin.sync();	// Removes the character ^Z from input buffer.
		typedef vector<double>::size_type HG_VectorSize;
		HG_VectorSize HGsize = homeworkGrades.size(); 

		if (HGsize == 0)	// Check that user entered atleast one grade.
		{
			cout << endl << "You must enter your grades. Please try again." << 
				endl;
			return 1;
		}

		// Sort grades out in ascending order.
		sort(homeworkGrades.begin(), homeworkGrades.end());	

		// Compute median homework grade.
		HG_VectorSize midElement = HGsize / 2;
		double median = 0;
		median = HGsize % 2 == 0 ?
			(homeworkGrades[midElement] + homeworkGrades[midElement - 1]) / 2 :
			homeworkGrades[midElement];

		// Compute lower quartile.
		HG_VectorSize lowerQuartile = midElement / 2;
		double lowerQuartileTotal = 0;

		for (unsigned int i = 0; i < lowerQuartile; i++)
		{
			lowerQuartileTotal += homeworkGrades[i];
		}

		// Compute upper quartile.
		HG_VectorSize upperQuartile = HGsize - lowerQuartile;
		double upperQuartileTotal = 0;

		for (unsigned int i = upperQuartile; i < HGsize; i++)
		{
			upperQuartileTotal += homeworkGrades[i];
		}

		// Show quartile with the largest value.
		lowerQuartileTotal > upperQuartileTotal ? 
			cout << "\n The lower quartile has the largest value (" << 
			lowerQuartileTotal << ")." :
			cout << "\n The upper quartile has the largest value (" <<
			upperQuartileTotal << ").";

		// Compute and write final grade.
		streamsize precision = cout.precision();
		cout << "\nYour final grade is " << setprecision(3) <<
			(0.2 * midterm) + (0.4 + final) + (0.4 * median) <<
			setprecision(precision) << endl;

		// Add final grade into the studentGrades vector.
		double finalGrade = (0.2 * midterm) + (0.4 + final) + (0.4 * median);
		studentGrades.push_back(finalGrade);

		// Ask whether to run program again for a different student.
		cout << "\n Do you want to compute another student\'s grade? (Y/N)" <<
			endl;
		cout << "Option: ";
		char runAgain;
		cin >> runAgain;

		if (runAgain != 'Y')
		{
			runProgramAgain = false;
		}
		if (runAgain != 'y')
		{
			runProgramAgain = false;
		}
	} while (runProgramAgain);

	// Show all students final grades.
	int vectorsSize = studentGrades.size();

	for (int i = 0; i < vectorsSize; i++)
	{
		cout << studentNames[i] << "\'s final grade is: " << 
			studentGrades[i] << endl;
	}

	return 0;
}


This post has been edited by DivideByZero: 19 January 2011 - 11:17 AM

Was This Post Helpful? 0
  • +
  • -

#14 jimblumberg  Icon User is offline

  • member icon


Reputation: 3987
  • View blog
  • Posts: 12,298
  • Joined: 25-December 09

Re: Problem with getting programs to run again

Posted 19 January 2011 - 11:23 AM

There is a problem with your if statements:

if (runAgain != 'Y')
        {
            runProgramAgain = false;
        }
        if (runAgain != 'y')
        {
            runProgramAgain = false;
        }



You loop will not exit when runAgain == 'Y' because if it == 'Y' it will never == 'y' (you need to combine these statements, either with an else or using || )

Jim

This post has been edited by jimblumberg: 19 January 2011 - 11:24 AM

Was This Post Helpful? 0
  • +
  • -

#15 DivideByZero  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 238
  • View blog
  • Posts: 551
  • Joined: 02-December 10

Re: Problem with getting programs to run again

Posted 20 January 2011 - 09:47 AM

Has anyone figured out why this program refuses to loop again? I've been picking it apart for the last couple of hours and I'm stumped. It just makes sense yet it doesn't do what it should :S

Here's the code, I haven't modified it.
#include <iomanip>	// For setprecision.
#include <ios>	// For streamsize.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>	// For sort().

using namespace std;

int main()
{
	vector<string> studentNames;
	vector<double> studentGrades;
	bool runProgramAgain = true;

	do
	{
		// Ask for student name and add name into studentNames vector.
		cout << "Please enter your first name: ";
		string name;		
		cin >> name;
		cout << "Hello, " << name << "!" << endl;
		studentNames.push_back(name);

		// Ask for midterm and final exam grades.
		cout << "Please enter your midterm and final exam grades: ";
		double midterm = 0, final = 0;
		cin >> midterm >> final;

		// Ask for homework grades.
		cout << "Enter all your homework, followed by end of file: ";
		
		vector<double> homeworkGrades;
		double readHomeworkGrades = 0;	

		while (cin >> readHomeworkGrades)
		{
			homeworkGrades.push_back(readHomeworkGrades);
		}
		
		cin.clear();	// Resets error flag caused by EOF.
		cin.sync();	// Removes the character ^Z from input buffer.
		typedef vector<double>::size_type HG_VectorSize;
		HG_VectorSize HGsize = homeworkGrades.size(); 

		if (HGsize == 0)	// Check that user entered atleast one grade.
		{
			cout << endl << "You must enter your grades. Please try again." << 
				endl;
			return 1;
		}

		// Sort grades out in ascending order.
		sort(homeworkGrades.begin(), homeworkGrades.end());	

		// Compute median homework grade.
		HG_VectorSize midElement = HGsize / 2;
		double median = 0;
		median = HGsize % 2 == 0 ?
			(homeworkGrades[midElement] + homeworkGrades[midElement - 1]) / 2 :
			homeworkGrades[midElement];

		// Compute lower quartile.
		HG_VectorSize lowerQuartile = midElement / 2;
		double lowerQuartileTotal = 0;

		for (unsigned int i = 0; i < lowerQuartile; i++)
		{
			lowerQuartileTotal += homeworkGrades[i];
		}

		// Compute upper quartile.
		HG_VectorSize upperQuartile = HGsize - lowerQuartile;
		double upperQuartileTotal = 0;

		for (unsigned int i = upperQuartile; i < HGsize; i++)
		{
			upperQuartileTotal += homeworkGrades[i];
		}

		// Show quartile with the largest value.
		lowerQuartileTotal > upperQuartileTotal ? 
			cout << "\n The lower quartile has the largest value (" << 
			lowerQuartileTotal << ")." :
			cout << "\n The upper quartile has the largest value (" <<
			upperQuartileTotal << ").";

		// Compute and write final grade.
		streamsize precision = cout.precision();
		cout << "\nYour final grade is " << setprecision(3) <<
			(0.2 * midterm) + (0.4 + final) + (0.4 * median) <<
			setprecision(precision) << endl;

		// Add final grade into the studentGrades vector.
		double finalGrade = (0.2 * midterm) + (0.4 + final) + (0.4 * median);
		studentGrades.push_back(finalGrade);

		// Ask whether to run program again for a different student.
		cout << "\n Do you want to compute another student\'s grade? (Y/N)" <<
			endl;
		cout << "Option: ";
		char runAgain;
		cin >> runAgain;

		if (runAgain != 'Y')
		{
			runProgramAgain = false;
		}
		if (runAgain != 'y')
		{
			runProgramAgain = false;
		}
	} while (runProgramAgain);

	// Show all students final grades.
	int vectorsSize = studentGrades.size();

	for (int i = 0; i < vectorsSize; i++)
	{
		cout << studentNames[i] << "\'s final grade is: " << 
			studentGrades[i] << endl;
	}

	return 0;
}


Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2