Hey lsu420luv,
Sorry for the reply like 8 hours later. You see, I live in Singapore and the reply you gave was at 4am SGT. Was asleep by then.
From what I saw in your previous post, I think you still do not comprehend quite a number of the C++ concepts... Here's what I did together with an explanation:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
// Const Fields
const int MAXMEMBERS = 20;
const int MAXJUDGES = 5;
// Globals
int pianoPlayer[MAXMEMBERS];
double score[MAXMEMBERS][MAXJUDGES];
double weightFactor[MAXMEMBERS];
int profLevel[MAXMEMBERS];
int judgeNumber[MAXMEMBERS][MAXJUDGES];
double average[MAXMEMBERS];
int weightedScore[MAXMEMBERS];
int category; //category of music the students are playing
int judgeCount[MAXMEMBERS];
int numPlayers;
// Methods
int ReadScores(ifstream& fin);
void PrintReport(ofstream& fout);
void ProcessScores();
Ok, I've separated the globals, constants and methods. You should do that too. It makes reading them a lot easier.
Notice that I have also reduced your
PrintReport method that it only takes in an
ofstream as its parameter. Remember what I told you about global variables? Since all the variables required by
PrintReport are global (i.e. declared outside of any method), you can access them without passing them as parameters into the method.
int main()
{
ifstream fin("PianoREV.data");
ofstream fout("Report.out");
if (!fin)
{
cout << "Error: Input File";
return 1;
}
if (!fout)
{
cout << "Error: Output File";
return 1;
}
numPlayers = ReadScores(fin);
ProcessScores();
PrintReport(fout);
fin.close();
fout.close();
}
Look at how I've reduced your file I/O code. You can simply open an
ifstream or
ofstream by calling their constructors; in other words, just by doing this:
ifstream fin("PianoREV.data");
ofstream fout("Report.out");
After that, you can check if the open succeeded simply by:
if (!fin)
{
cout << "Error: Input File";
return 1;
}
if (!fout)
{
cout << "Error: Output File";
return 1;
}
Basically, putting a stream as the condition of an
if statement tells you if it is still valid. Doing this:
Is (sort of) the same as:
It's just much shorter. Why "sort of"? I will explain this later.
These are also present in the
ReadScores method, the one that you've been using (underlined):
int ReadScores (ifstream& fin)
{
int i= 0;
int j= 0;
fin >> category;
for (i = 0; fin && i < MAXMEMBERS; ++i)
{
if (!(fin >> pianoPlayer[i]))
break;
if (!(fin >> profLevel[i]))
break;
if (!(fin >> weightFactor[i]))
break;
// Process the judges
for (int j = 0; fin; ++j)
{
if (j >= MAXJUDGES) // If we have too many judges
{
// If the number of judges overflow the array size,
// we have to clear off the remaining judge entries
// so that we can continue reading from the next
// player entry
int k;
if (!(fin >> k) || k == -1)
{
judgeCount[i] = MAXJUDGES; // Set judgeCount to limit
break;
}
else
continue;
}
if (!(fin >> judgeNumber[i][j]) || judgeNumber[i][j] == -1)
{
judgeCount[i] = j;
break;
}
if (!(fin >> score[i][j]))
{
judgeCount[i] = j;
break;
}
}
}
return i;
} If the input (
>>) and output (
<<) operators makes it look confusing, think of them as methods, and that these methods
return the stream you call them with. What does this mean? Whenever you do something like:
cout << "Bob" << 123 << "Tom" << endl;
First of all, the stream you work with now is
cout.
You use the output operator (
<<) on
cout.
And with the output operator, you tell
cout to print
"Bob",
123,
"Tom" and
endl (I'll explain
endl later) Understood so far?
What I mean when that these operators are like methods and the return the stream you call them with, means that I call a method something like this happens when I use
<< (C++ pros, don't flame me with this, it's just an abstraction for explanation):
ostream& << (ostream& s)
{
// Some logic ...
return s;
} Don't get it? Basically, this:
cout << "Bob" << 123 << "Tom" << endl;
Is
exactly the same as:
cout << "Bob"; cout << 123; cout << "Tom"; cout << endl;
What does all these mean to you? Basically (look carefully at where the exclamation mark goes):
if (!(fin >> pianoPlayer[i]))
break;
Is exactly the same as:
fin >> pianoPlayer[i];
if (!fin)
break;
Which is also (sort of) the same as:
fin >> pianoPlayer[i];
if (fin.fail())
break;
Why "sort of the same"? Because (look, no exclamation mark):
Is actually doing this:
(And of course,
if (!fin) the same as
if (!fin.good()), the NOT operator (
!) just changes
true to
false and vice versa).
It's sort of the same, because
fin.good() is not
just the opposite of
fin.fail()! It's also the opposite of
fin.eof() and
fin.bad(). What are these?
fin.eof() returns true if the End-Of-File (EOF) has been reached.
fin.fail() returns true if some I/O error occurred.
fin.bad() returns true if some fatal I/O error occurred.
So, by using
if (!fin.good()), or simply
if (!fin) checks for all these possible errors.
Now, what is
endl?
endl is the C++ representation of a newline. You should not use
"\n" because this is quite restricted as different OSes use different
line terminators. *nix will use
"\n" but Windows
"\r\n". In order to make your code compile without being OS specific, you should use
endl.
I've used
endl in your
PrintReport method too (underlined):
void PrintReport (ofstream& fout)
{
for (int i = 0; i < numPlayers; ++i)
{
fout << "Piano Player: " << pianoPlayer[i] << endl;
for (int j = 0; j < judgeCount[i]; ++j)
{
fout << "Judge Number: " << judgeNumber[i][j] << " "
<< "Score: " << score[i][j] << endl;
}
fout << "Average Score: " << average[i] << endl
<< "Weighted Score: " << weightedScore[i] << endl << endl;
}
} You were asking why your
PrintReport method print every player and judge? Look at the changes (underlined):
void PrintReport (ofstream& fout)
{
for (int i = 0; i < numPlayers; ++i)
{
fout << "Piano Player: " << pianoPlayer[i] << endl;
for (int j = 0; j < judgeCount[i]; ++j)
{
fout << "Judge Number: " << judgeNumber[i][j] << " "
<< "Score: " << score[i][j] << endl;
}
fout << "Average Score: " << average[i] << endl
<< "Weighted Score: " << weightedScore[i] << endl << endl;
}
} You used
MAXMEMBERS and
MAXJUDGES earlier, and that's why you print to
MAXMEMBERS and
MAXJUDGES! It's that simple a logic error. Since you said you wanted a
judgeCount array, I've included it in too. Notice that this is also reflected in the
ReadScores method;
ReadScores will determine how many judges are there per student (underlined):
int ReadScores (ifstream& fin)
{
int i= 0;
int j= 0;
fin >> category;
for (i = 0; fin && i < MAXMEMBERS; ++i)
{
if (!(fin >> pianoPlayer[i]))
break;
if (!(fin >> profLevel[i]))
break;
if (!(fin >> weightFactor[i]))
break;
// Process the judges
for (int j = 0; fin; ++j)
{
if (j >= MAXJUDGES) // If we have too many judges
{
// If the number of judges overflow the array size,
// we have to clear off the remaining judge entries
// so that we can continue reading from the next
// player entry
int k;
if (!(fin >> k) || k == -1)
{
judgeCount[i] = MAXJUDGES; // Set judgeCount to limit
break;
}
else
continue;
}
if (!(fin >> judgeNumber[i][j]) || judgeNumber[i][j] == -1)
{
judgeCount[i] = j;
break;
}
if (!(fin >> score[i][j]))
{
judgeCount[i] = j;
break;
}
}
}
return i;
}
In case that you do not know what break and continue is, break terminates the innermost loop and continues immediately on the code outside the loop. continue forces the loop to reiterate and evaluate the condition immediately, not executing the remaining code before a normal iteration.
As for ProcessScores, I've also changed it to use judgeCount. Other than that, nothing else is changed. I was unable to find any fault with the logic.
void ProcessScores ()
{
int j;
double totalScore;
for (int i = 0; i < numPlayers; ++i)
{
for (j = 0, totalScore = 0; j < judgeCount[i]; ++j)
{
totalScore += score[i][j];
}
if (j != 0)
average[i] = totalScore / j;
weightedScore[i] = average[i] * weightFactor[i];
}
}
Putting everything together, here is the full source code:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
// Const Fields
const int MAXMEMBERS = 20;
const int MAXJUDGES = 5;
// Globals
int pianoPlayer[MAXMEMBERS];
double score[MAXMEMBERS][MAXJUDGES];
double weightFactor[MAXMEMBERS];
int profLevel[MAXMEMBERS];
int judgeNumber[MAXMEMBERS][MAXJUDGES];
double average[MAXMEMBERS];
int weightedScore[MAXMEMBERS];
int category; //category of music the students are playing
int judgeCount[MAXMEMBERS];
int numPlayers;
// Methods
int ReadScores(ifstream& fin);
void PrintReport(ofstream& fout);
void ProcessScores();
int main()
{
ifstream fin("PianoREV.data");
ofstream fout("Report.out");
if (!fin)
{
cout << "Error: Input File";
return 1;
}
if (!fout)
{
cout << "Error: Output File";
return 1;
}
numPlayers = ReadScores(fin);
ProcessScores();
PrintReport(fout);
fin.close();
fout.close();
}
int ReadScores (ifstream& fin)
{
int i= 0;
int j= 0;
fin >> category;
for (i = 0; fin && i < MAXMEMBERS; ++i)
{
if (!(fin >> pianoPlayer[i]))
break;
if (!(fin >> profLevel[i]))
break;
if (!(fin >> weightFactor[i]))
break;
// Process the judges
for (int j = 0; fin; ++j)
{
if (j >= MAXJUDGES) // If we have too many judges
{
// If the number of judges overflow the array size,
// we have to clear off the remaining judge entries
// so that we can continue reading from the next
// player entry
int k;
if (!(fin >> k) || k == -1)
{
judgeCount[i] = MAXJUDGES; // Set judgeCount to limit
break;
}
else
continue;
}
if (!(fin >> judgeNumber[i][j]) || judgeNumber[i][j] == -1)
{
judgeCount[i] = j;
break;
}
if (!(fin >> score[i][j]))
{
judgeCount[i] = j;
break;
}
}
}
return i;
}
void ProcessScores ()
{
int j;
double totalScore;
for (int i = 0; i < numPlayers; ++i)
{
for (j = 0, totalScore = 0; j < judgeCount[i]; ++j)
{
totalScore += score[i][j];
}
if (j != 0)
average[i] = totalScore / j;
weightedScore[i] = average[i] * weightFactor[i];
}
}
void PrintReport (ofstream& fout)
{
for (int i = 0; i < numPlayers; ++i)
{
fout << "Piano Player: " << pianoPlayer[i] << endl;
for (int j = 0; j < judgeCount[i]; ++j)
{
fout << "Judge Number: " << judgeNumber[i][j] << " "
<< "Score: " << score[i][j] << endl;
}
fout << "Average Score: " << average[i] << endl
<< "Weighted Score: " << weightedScore[i] << endl << endl;
}
}
Ok, I admit, all the help I gave you thus far are all done without the use of a compiler. I wasn't able to get my C++ compiler up but I can give you the guarantee that the code works. It should. Unless I make some careless mistake, which I believe I didn't.
I would recommend two books if you intend to go into C++:
The first is an extremely good guide and reference (though it states only reference). I would dare to give you my fullest support that this book is the definite reference to C++ (and some C too). It even goes through some more advanced topics like the Standard Library and RTTI. The same author has written many other good books on C++, C and Java as well.
The second is also a must-have for every C++ programmer. The Standard Library is the equivalent of the Java API for C++ (though not as extensive), and no other book gives a tutorial and reference on it as worth as Mr. Josuttis'.
It's sometimes hard to find a good reference on the Internet (which is surprising), so I had to rely on these books for C++ help. In fact, these two books propelled me into programming C++.
You can also check out
How Not to Program in C++ by Steve Oualline. It's a rather light-hearted good read on the common mistakes people make with C++.
I believe all's done and you can submit your work. It's been nice working with ya on this, and if there's anything else that needs to be done, don't hesitate to post it. I've sent the PM. Thanks again!