Okay, so I have my program almost complete. I can get it to do everything except use the computeAverage. I know it works because if I hard code the arrays, I can utilize that and it will work. However, I am having to utilize what I pull from a .txt file and I can't figure out quite yet how to compute those numbers.

Here is what I have:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

const int MAX_SIZE = 21;     // Declared by professor

void readStudentData(ifstream &rss, int scores[], int id[], int &count, bool &tooMany)
{
	void printTable(int score[], int id[], int count);

	rss.open("studentScoreData.txt",ios::in,ios::binary);

	int amountRead = 0;
	count = 0;
	int oneScore = 0;
	float average = 0;
	string grade;

	if(!rss)
	{
		cout << "Cannot Open File. If test file has been created rename it studentScoreData." << endl;
	}
	else
	{
		printTable(scores, id, count);

		while((rss >> id[amountRead] && amountRead < MAX_SIZE) && (rss >> scores[amountRead] && amountRead < MAX_SIZE))
		{
			amountRead++;
		}
	
		for(int i = 0; i < MAX_SIZE; i++)
		{
			cout << left << setw(9) << id[i] << setw(9) << scores[i] << setw(9) << grade << endl;
		}
	}
}

float computeAverage(int scores[], int count[])
{
	float average = 0;
	int sum = 0;
	for(int i = 0; i < MAX_SIZE; i++)
	sum += scores[i];
	average = sum / MAX_SIZE;

	return 0;
}

void printTable(int scores[], int id[], int count)
{
	void printGrade(int oneScore, float average);

	int oneScore = 0;
	float average = 0;
	string grade;

	cout << left << setw(9) << "ID#s" << setw(9) << "Scores" << setw(9) << "Grades" << endl << endl;
	printGrade(oneScore, average);


}

void printGrade(int oneScore, float average)
{
	int scores[MAX_SIZE];
	oneScore = 0;
	average = 0;
	int count[MAX_SIZE];
	string grade;

	computeAverage(scores,count);

	for(int i = 0; i < MAX_SIZE; i++)
	{
		if(scores[i] > average + 10)
		{
			grade = "outstanding";
		}
		else if(scores[i] < average - 10)
		{
			grade = "unsatisfactory";
		}
		else
		{
			grade = "satisfactory";
		}

		//cout << left << setw(9) << grade << endl;
	}
	
}

int main()
{
	ifstream rss;
	string line;
	int scores[MAX_SIZE];
	int id[MAX_SIZE];
	int count;
	bool tooMany;

	readStudentData(rss, scores, id, count, tooMany);

	

	return 0;
}

Recommended Answers

All 10 Replies

float computeAverage(int scores[], int count[])
{
    float average = 0;
    int sum = 0;
    for(int i = 0; i < MAX_SIZE; i++)
    sum += scores[i];
    average = sum / MAX_SIZE;

    return 0;
}

Your compute average function is still incomplete. 1st thing I don't see any usage of count[] that you pass to this function. 2nd You are computing the average but not even returning it ???
You have coded the initial read function well (I haven't checked the errors in it though if there are any ;)) Now just use the same concept and feed in the values to this array of yours and then compute the average thats it !!! :)

tooMany is never used in this function:

void readStudentData(ifstream &rss, int scores[], int id[], int &count, bool &tooMany)

You should find out what you are supposed to do with tooMany.

readStudentData should do just that: read the student data. It shouldn't display anything except possibly error messages. You have printTable and printGrade. Let them do the displaying. Just call readStudentData from main, then display the info by calling printTable from main. You can display things from readStudentData temporarily for debugging purposes (remember to delete it later), but other than that, there shouldn't be any output from that function.

In printTable, this isn't a valid function call (red):

void printTable(int scores[], int id[], int count)
{
	void printGrade(int oneScore, float average);

	int oneScore = 0;
	float average = 0;
	string grade;

	cout << left << setw(9) << "ID#s" << setw(9) << "Scores" << setw(9) << "Grades" << endl << endl;
	printGrade(oneScore, average);


}

The thing is that I can't have the arrays hardcoded because I have to pull the values from a .txt file. I can set it up to where it calls and utilizes the computeAverage function and it will work. I guess my thing is, is that when I do that it gives me a large negative number for both the id[] and the score[] and just reads out 'unsatisfactory' since it is obviously far more than -10 from the average. The average that the program is computing is 50 from the numbers that I have entered. So, I need computeAverage to utilize the numbers being pulled from the .txt file and then I need to print the result. My thing is how do I do that.

The thing is that I can't have the arrays hardcoded because I have to pull the values from a .txt file. I can set it up to where it calls and utilizes the computeAverage function and it will work. I guess my thing is, is that when I do that it gives me a large negative number for both the id[] and the score[] and just reads out 'unsatisfactory' since it is obviously far more than -10 from the average. The average that the program is computing is 50 from the numbers that I have entered. So, I need computeAverage to utilize the numbers being pulled from the .txt file and then I need to print the result. My thing is how do I do that.

You mean this is actually compiling? I can't imagine how it could with the line in red that I posted in my last post.

void printTable(int scores[], int id[], int count)
{
	void printGrade(int oneScore, float average);

	int oneScore = 0;
	float average = 0;
	string grade;

	cout << left << setw(9) << "ID#s" << setw(9) << "Scores" << setw(9) << "Grades" << endl << endl;
	printGrade(oneScore, average);


}

This shouldn't compile and you should get no results, good or bad, till you delete it.


That aside, you should get complete nonsense values if you call printTable. After all, look when you are calling it:

void readStudentData(ifstream &rss, int scores[], int id[], int &count, bool &tooMany)
{
	void printTable(int score[], int id[], int count);

	rss.open("studentScoreData.txt",ios::in,ios::binary);

	int amountRead = 0;
	count = 0;
	int oneScore = 0;
	float average = 0;
	string grade;

	if(!rss)
	{
		cout << "Cannot Open File. If test file has been created rename it studentScoreData." << endl;
	}
	else
	{
		printTable(scores, id, count);

		while((rss >> id[amountRead] && amountRead < MAX_SIZE) && (rss >> scores[amountRead] && amountRead < MAX_SIZE))
		{
			amountRead++;
		}
	
		for(int i = 0; i < MAX_SIZE; i++)
		{
			cout << left << setw(9) << id[i] << setw(9) << scores[i] << setw(9) << grade << endl;
		}
	}
}

You call it in line 19. You don't read any data till line 21. How can you calculate when you haven't read in the data yet? And line 3 needs to be deleted. Again, this shouldn't compile with this there.

Read my last post again. There should be no calls to any other functions in readStudentData. readStudentData reads the student data. That's it. You calculate and you display from other functions.

It actually does compile. I removed that one line you said to and placed as a global declaration otherwise the code won't compile. As for 'printTable', all it really contains is the heading displays:
ID#s Score Grade

Those are my headings of each column.
I am trying to use printGrade to display the ID#s, scores and grades. I am trying to get the whole thing to work before I break it down into it's respective sectors. I'm just trying to get done what I can by Monday night.

I have included the code file and the .txt file that I am using.

Yeah, I guess it does compile (except for this line, at least in Dev C++).

rss.open("studentScoreData.txt",ios::in, ios::binary);

Dev C++ requires the comma to be replaced by a |.

rss.open("studentScoreData.txt",ios::in | ios::binary);

Regarding the function declarations, you're right. I didn't look closely at the error message and assumed they were from those lines and not the ifstream.open line. You know what they say about people who assume. My bad. Normally you put your function declarations above all your functions rather than inside them, but you CAN put them inside the function. I just had never seen it before. Still, you're saying that the ifstream.open line above compiled? It didn't for me till I changed the comma to a '|'.

I stand by everything I suggested in my last post other than deleting those lines, though. count and tooMany were passed by reference for a reason and that reason was that the function is supposed to assign those variables values that will be used AFTER readStudentData is completed. Your program just ends then, so there's no point at all passing those parameters by reference.
You should put the following line right before return 0 in main:

cout << count << endl;

That needs to display 21. If it doesn't (and it won't), that means you have problems reading the data in. Which means that that function needs to be fixed first before you work on any calculation functions or any display functions. You need to assign count to equal the number of records in the input file in your readStudentData function. You don't do that anywhere. And again, I don't know what you're supposed to do with tooMany . I can guess, but you should ask your professor.

The tooMany thing that is in the book looks like this:

bool &tooMany);      //OUT: A flag to indicate that more
                     //than MAX_SIZE scores items are in
                     //input file.

That is how the book shows it, so I'm assuming that I need to use it somewhere in the code as:

if(MAX_SIZE >= tooMany)
{
//    myFile.close() or myFile.eof()   //////something to that effect
      cout << "End of file" << endl;
}

Quick question, with bool &tooMany, should I make that into a seperate function, or should i set it to (MAX_SIZE + 1)? I don't really have much experience with bools. I know that bools are true/false items. I will google it, but what would be your opinion to do with it?

The tooMany thing that is in the book looks like this:

bool &tooMany);      //OUT: A flag to indicate that more
                     //than MAX_SIZE scores items are in
                     //input file.

That is how the book shows it, so I'm assuming that I need to use it somewhere in the code as:

if(MAX_SIZE >= tooMany)
{
//    myFile.close() or myFile.eof()   //////something to that effect
      cout << "End of file" << endl;
}

Quick question, with bool &tooMany, should I make that into a seperate function, or should i set it to (MAX_SIZE + 1)? I don't really have much experience with bools. I know that bools are true/false items. I will google it, but what would be your opinion to do with it?

The important thing is to not overflow your array. Say you have 22 records and MAX_SIZE is 21.

while((rss >> id[amountRead] && amountRead < MAX_SIZE) && (rss >> scores[amountRead] && amountRead < MAX_SIZE))
		{
			amountRead++;
		}

So let's say amountRead is 21. We have one record left in the file, but our array is full. We hit this line:

while((rss >> id[amountRead] && amountRead < MAX_SIZE) && (rss >> scores[amountRead] && amountRead < MAX_SIZE))

We hit the first term:

rss >> id[amountRead]

which is this, since amountRead is 21:

rss >> id[21]

This is a potential array overflow/segmentation fault since the array only holds 21 elements. So you you need to test whether amountRead < 21 BEFORE trying to read in anything, because you check it too late:

while(amountRead < MAX_SIZE && (rss >> id[amountRead] >> scores[amountRead]))

The while loop ends when the file is either completely read or amountRead >= MAX_SIZE, or both. Potentially you could have EXACTLY MAX_SIZE records in the file, so you wouldn't know which one it was. Try reading in a new dummy record and see if you can do it:

int dummyInt;
rss >> dummyInt;

// now test whether the file has been completely exhausted and the above test failed:

if (rss.good ())
     tooMany = true; // file has more than MAX_SIZE records
else
     tooMany = false; // file has MAX_SIZE or fewer records

http://www.cplusplus.com/reference/iostream/ios/good/

or similarly:

int dummyInt;

if (rss >> dummyInt)
     tooMany = true; // file has more than MAX_SIZE records
else
     tooMany = false; // file has MAX_SIZE or fewer records

So your function ends up being something like this:

void readStudentData(ifstream &rss, int scores[], int id[], int &count, bool &tooMany)
{
	rss.open("studentScoreData.txt",ios::in,ios::binary);

	int amountRead = 0;
	count = 0;
	int oneScore = 0;
	float average = 0;
	string grade;

	if(!rss)
	{
		cout << "Cannot Open File. If test file has been created rename it studentScoreData." << endl;
	}
	else
	{
		printTable(scores, id, count);

		while(amountRead < MAX_SIZE && (rss >> id[amountRead] >> scores[amountRead]))
		{
			amountRead++;
		}

                int dummyInt;
                rss >> dummyInt;

                // now test whether the file has been completely exhausted and the above test failed:

                if (rss.good ())
                     tooMany = true; // file has more than MAX_SIZE records
                else
                     tooMany = false; // file has MAX_SIZE or fewer records
	
		for(int i = 0; i < MAX_SIZE; i++)
		{
			cout << left << setw(9) << id[i] << setw(9) << scores[i] << setw(9) << grade << endl;
		}
	}
}

That's ONE way of doing it. It's not the ONLY way and I was trying to keep most of your code intact. I'll reiterate my earlier point that you should get rid of the display code and that you need to do something to the count variable before the function is over, in order to send it back with the actual number of records. You should also exit the program if your file doesn't open. Right now you just display an error message. And you should close your file once you are done reading from it.

The "not-quite-so-much-masterpiece" is almost done.

I put

cout << count << endl;

into my program. I had to do it like

if (tooMany = true)
	{
		printTable(scores,id,count);
		cout << count << endl;
		exit(1);
	}
	else
	{
		printTable(scores,id,count);
	}

for it to be able to work. I removed any display calls or programming from inside of the readStudentData(.....) function. It only displays the error and does the counting (which I also adjusted). The only issue I have left is getting it to do the grade display. Inside of "void printGrade(.....)" where I have the 'cout' line commented out, it will display a list of long negative numbers and all say 'unsatisfied' next to it. I know the code inside of that function is right, except for calling the numbers from the .txt file into it. If I can get that then it will be finished I believe. At least in working order.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

void printGrade(int oneScore, float average);

const int MAX_SIZE = 21;

void readStudentData(ifstream &rss, int scores[], int id[], int &count, bool &tooMany)
{

	rss.open("studentScoreData.txt",ios::in,ios::binary);

	count = 0;
	int oneScore = 0;
	float average = 0;
	string grade;

	if(rss.fail())
	{
		cout << "Cannot Open File. If test file has been \n"
			<< "created rename it studentScoreData." << endl << endl;
		exit(1);
	}
	else
	{
		while((rss >> id[count] && count < MAX_SIZE) && (rss >> scores[count] && count < MAX_SIZE))
		{
			count++;
		}
	}
}

float computeAverage(int scores[], int count[])
{
	float average = 0;
	int sum = 0;
	for(int i = 0; i < MAX_SIZE; i++)
	sum += scores[i];
	average = sum / MAX_SIZE;

	return 0;
}

void printTable(int scores[], int id[], int count)
{

	int oneScore = 0;
	float average = 0;
	string grade;

	printGrade(oneScore, average);

	cout << left << setw(9) << "ID#s" << setw(9) << "Scores" << setw(9) << "Grades" << endl << endl;

	for(int i = 0; i < MAX_SIZE; i++)
	{
		cout << left << setw(9) << id[i] << setw(9) << scores[i] << setw(9) << grade << endl;
	}
}

void printGrade(int oneScore, float average)
{
	int scores[MAX_SIZE];
	oneScore = 0;
	average = 0;
	int count[MAX_SIZE];
	int id[MAX_SIZE];
	string grade;

	computeAverage(scores,count);

	for(int i = 0; i < MAX_SIZE; i++)
	{
		if(scores[i] > average + 10)
		{
			grade = "outstanding";
		}
		else if(scores[i] < average - 10)
		{
			grade = "unsatisfactory";
		}
		else
		{
			grade = "satisfactory";
		}

//		cout << left << setw(9) << id[i] << setw(9) << scores[i] << setw(9) << grade << endl;
	}
	
}

int main()
{
	ifstream rss;
	string line;
	int scores[MAX_SIZE];
	int id[MAX_SIZE];
	int count;
	bool tooMany;

	readStudentData(rss, scores, id, count, tooMany);

	if (tooMany = true)
	{
		printTable(scores,id,count);
//		cout << count << endl;    just a test
		exit(1);
	}
	else
	{
		printTable(scores,id,count);
	}

	return 0;
}

That is the almost finished coding. Just need help calling the numbers into the function 'printGrade(.....)'.

Read my post describing why this is a problem when count >= MAX_SIZE. It wont make any difference when you have a file with fewer than MAX_SIZE records, but you'll run into problems otherwise. Even if you sometimes get away with it, it's still an array-out-of-bounds problem that should be fixed.

while((rss >> id[count] && count < MAX_SIZE) && (rss >> scores[count] && count < MAX_SIZE))

The printGrade function has a lot of problems.

void printGrade(int oneScore, float average)
{
	int scores[MAX_SIZE];
	oneScore = 0;
	average = 0;
	int count[MAX_SIZE];
	int id[MAX_SIZE];
	string grade;

	computeAverage(scores,count);

	for(int i = 0; i < MAX_SIZE; i++)
	{
		if(scores[i] > average + 10)
		{
			grade = "outstanding";
		}
		else if(scores[i] < average - 10)
		{
			grade = "unsatisfactory";
		}
		else
		{
			grade = "satisfactory";
		}

//		cout << left << setw(9) << id[i] << setw(9) << scores[i] << setw(9) << grade << endl;
	}
	
}

You should have no arrays in it. It should print a single grade (not grades plural. Let printTable do that.). Also, the function is passed average , so don't call computeAverage in it since you were supposed to have computed that BEFORE calling this function.

In addition, MAX_SIZE should not be used in any of your functions except main and readStudentData. A major tipoff that something is wrong is that you aren't using count[] in this function. If you didn't need it, you wouldn't have been asked to pass it:

float computeAverage(int scores[], int count[])
{
	float average = 0;
	int sum = 0;
	for(int i = 0; i < MAX_SIZE; i++)
	sum += scores[i];
	average = sum / MAX_SIZE;

	return 0;
}

I'm guessing that the specification is supposed to be this:

float computeAverage(int scores[], int count)

not this:

float computeAverage(int scores[], int count[])

If it's truly supposed to be the latter, I don't understand the goal of the function. Regardless, you don't use the count that you filled in in readStudentData anywhere. You are using MAX_SIZE instead. I doubt you are supposed to do that and I doubt that MAX_SIZE is supposed to be 21. It's usually some big round number, far bigger than any data file you'll run into.

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.