I am doing a project that produces a gradebook for an amount of students and exam scores.
the project link is
http://www.ecst.csuchico.edu/~chmorris/csci111/projects/06/

There are some additional things I need to produce besides being able to print the array chart, but I am stuck and have been trying to solve this problem. My current program is prints some of the actual exam scores, mostly garbage numbers, and none of the students names.
Any help is greatly appreciated.
-Matt

Attached is the output that is read from the compiler.
Here is what I have so far:

#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;


int main ()
{

string students[20];
int st_num = 0;
int st_exam= 0;
int st_name = 0;
double exam_ave[11];
int st_total[20];
double st_ave[10];
int score[20][10];
int st_high[10];
int st_low[10];
ifstream input;
string filename;
string name;
char ch;




while (filename != "the_office.csv")
{
cout << "Enter the filename containing exam scores: ";
cin >> filename;
}

input.open(filename);

while(getline(input,students[0],',')  )
{	
	
	input >> score[st_num][st_exam];
	input.get(ch);
	st_exam++;
	st_num++;

}
 
cout << "\n" << setw(12) << "Exams |";


for(int i = 1 ; i < 5; i++){
    cout << setw(12) << i ;
}
cout << setw(5) << "      Total";
cout << endl;
for( int j = 0; j < 5; j++)
{
	cout << "---------------";

}
cout << endl;

for (int st_loc =0; st_loc < 20; st_loc++)
	{ cout << setw(10) << students[st_loc] << " |";


for (int exam_num = 0; exam_num < 5; exam_num++)
	{
	cout << setw(5) << score[st_loc][exam_num];


}
cout << endl;
}


cout << endl;



		

system("PAUSE");
return 0;
}

I think that this bit is the problem:

while( getline( input, students[0], ',' ) )
{
    input >> score[st_num][st_exam];
    input.get(ch);
    st_exam++;
    st_num++;
}

It's going to be over-writing student[0] every time and the score matrix is going to be filled in along its diagonal only (since you increment both st_exam and st_num on each iteration of the loop). And the details that go in the score matrix aren't going be what you think either, since the >> operator will split on white-space by default, so you'll be trying to convert an entire line into an int .

Looking at the format of the file on the link that you posted, it looks like you should read in the file a line at a time and then attempt to split each line on the , character to get the student name from the first part and then get the exam scores from the rest of the line.

If you've covered it in your class, you should think about using a simple struct to hold the data that you read in. Something like:

struct StudentGrades
{
   std::string name;
   std::vector< double > grades;
};

So, I'd imagine you'd want something along the lines of:

std::vector< StudentGrades > allStudentScores;
while( ! infile.fail() )
{
   std::string lineFromFile;

   /* Get a whole line from the file */
   getline( infile, lineFromFile );
   
   /* Split the line into tokens, separated by commas.  This function doesn't exist in */
   /* standard C++, so you should write your own.                                      */
   std::vector< std::string > tokens = Split( lineFromFile, ',' );

   /* Add in some checks to make sure that we read in some data */
   
   StudentGrades currentStudentScores;
   currentStudentScores.name = tokens[0];
   
   /* Go through the rest of the tokens, adding the scores you find to the grades   */
   /* vector in the currentStudentScores object.  They will be strings, so you will */
   /* have to convert them to numbers first.                                        */
}

Hope that helps :)

I am working off the code you have supplied, how would you define the split variable, and how would you suggest printing the data?

I was more kind of suggesting an approach, you need to do a bit of work to turn it into working code.

I am working off the code you have supplied, how would you define the split variable, and how would you suggest printing the data?

Are you familiar with defining functions in C++? If not you should look that up first.

As for making a Split function, there's really only one way that such a function can work:

  1. Go through the string one character at a time until you find the character that you're going to split on (a , in this case).
  2. Mark it's position
  3. Find the next copy of that character
  4. Push everything in between the two characters into a vector of "tokens".
  5. Repeat this until you find you're at the end of the original string.

There are a number of ways to find the next split character, you could do it manually, or use the std::string::find member function, or the std::find function in the <algorithm> header.

I guess pseudo(ish) code for the manual option would look something like:

int startPosition = 0;
while ( startPosition != endOfString )
{
   /* Set up the search for the current token */
   currentPosition = startPosition;
   endPosition = startPosition + 1;
   
   /* Go through the string searching for the next character to split on */
   while ( stringToBeSplit[ currentPosition ] != charToSplitOn &&
           currentPosition != endOfString )
   {
      ++currentPosition;
   }

   /* Add the part of the original string that was between the split chars to the vector */
   std::string token = stringToBeSplit.SubString( startPosition, currentPosition - startPosition );
   vectorOfTokens.push_back( token );
   
   ++startPosition;
}

Have fun :)

Edited 5 Years Ago by ravenous: Added link

This article has been dead for over six months. Start a new discussion instead.