struct if1
{
  string idnum;//id number for the student
  string lastname;//last name of student
  string firstname;//first name of student
  int examscore[maxexam];//array of all the exam scores of the student
  int hwscore[maxhw];//array of all the home work scores of the student
};


void alphasort(if1 student[], int n)
//the alphasort function will sort the records into alphabetical order by last name. It expects the list as well as the total number of 
//names and will return the sorted array. The basic format for this function came from the class handout on bubblesorting.
{
  if1 temp;//used as a swapping mechanism
  int i; int j;// used for implementing for loop checks
  int f=1;//used for checking letters after the first
   for (i=0; i < n-1; i++)
       for (j=0; j < n-(i+1); j++)
	 if(student[j].lastname[0] > student[j+1].lastname[0])
	   {
	     temp = student[j];
	     student[j] = student[j+1];
	     student[j+1] = temp;
	   }
	 else if(student[j].lastname[0] == student[j+1].lastname[0])
	   {
	     while(student[j].lastname[f] == student[j+1].lastname[f])
	        {
		  f++;
		}
		 if (student[j].lastname[f] > student[j+1].lastname[f])
		   {
	             temp = student[j];
	             student[j] = student[j+1];
	             student[j+1] = temp;
		   }
	   }
}

im new here, so i hope i didnt post in the wrong area or something...


using an array of structs this function does not work, while the same function using only a simple array of strings does work properly.

i cant figure out why there would be any difference.

the array of structs will not sort alphabetically using all letters in the name if necessary while the simple array will sort 100% correct.

any ideas?

Recommended Answers

All 13 Replies

structs are nearly identical to classes, so maybe you need to add an = operator

struct if1
{
  string idnum;//id number for the student
  string lastname;//last name of student
  string firstname;//first name of student
  int examscore[maxexam];//array of all the exam scores of the student
  int hwscore[maxhw];//array of all the home work scores of the student

  void operator=(if1& f1)
  {
       idnum = f1.idnum;
       // etc for the rest of the structure members

   }
};

havent learned classes yet, so i dont really follow what your doing.

What I'm doing is writing my own version of the = operator. So when you way temp = student[j]; the compiler will call my version of the = operator instead of the compiler's default version. The parameter to the operator is the equilivent of passing student[j] by reference to any normal function.

I believe the reason your sort does not work as you wrote it is because the structure contains c++ STL class -- std::string. In such cases when the structure includes other class objects you should write the overloaded = operator.

That might also be similar to writing a swap function

void swap(if1& f1, if1& f2)
{
    if1 temp;
    temp.idnum = f1.idnum;
    temp.lastname = f1.lastname;
    temp.firstname = f1.firstname;
    temp.examscore = f1.examscore;
   temp.hwscore = f1.hwscore;

   f1.idnum = f2.idnum;
   // etc for f1

   f2.idnum = temp.idnum;
   // etc for f2
}

As you can see, the above code is pretty lengthly. The overloaded = operator is consideratly shorter and less pron to typing errors.

i tried implementing your code into my program and it does compile without any errors. unfortunately the same problem exists when it sorts the names it still only sorts them by the first letter and does not compare the rest of the name in the event that the first letters match.

please post your code. Its kind of hard for me to see your monitor from where I am sitting.

the entire program you mean?

oh and also, using bubblesort was a requirement for this program...

///////////////////
//
//This program will use filestreams to read in some information from two files about students including their first and last name, 
//id number and grades on their homeworks and exams. It will sort the list of students by their last name and calculate percentage and
//letter grades. The second input file containing the scores for exams and homeworks must contain a 'Q' symbol at the end of each line and
//and an end line character after the last line in the file. 
//The output of this program involves four outputs. the first is a list of names, sorted alphabetically by last name and their
//corresponding id numbers. The second is the list, again sorted the same way with the set of homework scores. if no homework score was
//read, there would be a 0 in the place of that score.
//The third output contains the list of sorted names and their corresponding scores on exams. again, if there is no score for an exam,
//there would be a 0 in the place of that score.
//The fourth and final output displays the sorted names and a percentage of their total grade(points earned vs. total points). and a
//letter grade corresponding to the percentage(A,B,C,D, or F).

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

const int maxstu(30);//maximum students per class constant
const int maxexam(3);//maximum exams per student constant
const int maxhw(10);//maximum home work assignments per student constant

struct if1
{
  string idnum;//id number for the student
  string lastname;//last name of student
  string firstname;//first name of student
  int examscore[maxexam];//array of all the exam scores of the student
  int hwscore[maxhw];//array of all the home work scores of the student

};

void nameread(ifstream&, if1[], int&);
void currentname(string&, string&, int, int);
void alphasort(if1[], int);
void dataread(ifstream&, if1[], int);
void gradecalc(float[], char[], int);

int main()
{
  string input1;//name of first input file
  string input2;//name of second input file
  string output;//name of output file
  ifstream infile1;//the first input file via filestreams
  ifstream infile2;//the second input file via filestreams
  ofstream outfile;//the output file accessed via filestreams
  if1 student[maxstu];//array of type if1 that stores all student records
  int n;//counter used for totalling the number of students in the class
  int total[maxstu];//array for storing total points earned by each student
  float percent[maxstu];//array for storing percentage grades for each student
  char grade[maxstu];//array for storing letter grades for each student

  cout << "please enter the name of the first input file" << endl;
  cin >> input1;

  cout << "please enter the name of the second input file" << endl;
  cin >> input2;

  cout << "please enter the name of the output file" << endl;
  cin >> output;

  infile1.open(input1.c_str());
  infile2.open(input2.c_str());
  outfile.open(output.c_str());

  nameread(infile1, student, n);

  alphasort(student, n);

  for(int v=0; v <n; v++)
    {
      total[v] = 0;
    }

  for (int i = 0; i < n; i++)
    {
  for(int h=0; h < 10; h++)
    {
      student[i].hwscore[h] = 0;
    }
  for(int e=0; e < 4; e++)
    {
      student[i].examscore[e] = 0;
    }
    }
  dataread(infile2, student, n);

 outfile << left << setw(25) << "NAME" << right << setw(17) << "ID#" << endl;

  for(int j = 0; j < n; j++)
    {
      outfile << left << setw(student[j].lastname.length()) << student[j].lastname << ", " << setw(15) <<  student[j].firstname << setw(13-student[j].lastname.length()) << " " << right << setw(12) << student[j].idnum << endl; 
    }
  outfile << endl;

  outfile << right << setw(42) << "HOMEWORK" << endl;

  outfile << left << setw(28) << "NAME";

  outfile << left << setw(1) << " ";

  for(int x = 1; x < 11; x++)
    {
      outfile << right << setw(6) << x;
    }
  outfile << endl;

  for(int u = 0; u < n; u++)
    {
      outfile << left << setw(student[u].lastname.length()) << student[u].lastname << ", " << setw(14) <<  student[u].firstname << setw(13-student[u].lastname.length()) << " ";

  for(int f = 0; f < 10; f++)
    {
      outfile << right << setw(6) << student[u].hwscore[f];
    }
  outfile << endl;
    }
  outfile << endl;

  outfile << right << setw(42) << "EXAMS" << endl;

  outfile << left << setw(28) << "NAME";

  outfile << left << setw(1) << " ";

for(int z = 1; z < 4; z++)
    {
      outfile << right << setw(6) << z;
    }

 outfile << endl;

  for(int p = 0; p < n; p++)
    {
      outfile << left << setw(student[p].lastname.length()) << student[p].lastname << ", " << setw(14) <<  student[p].firstname << setw(13-student[p].lastname.length()) << " ";

for(int o = 0; o < 3; o++)
    {
      outfile << right << setw(6) << student[p].examscore[o];
    }
 outfile << endl;
    }

  for(int r=0; r < n; r++)
    {
      for(int q=0; q < 3; q++)
	{
	  total[r] = total[r] + student[r].examscore[q];
	}
    }
  for(int w=0; w< n; w++)
    {
      for(int t=0; t < 10; t++)
	{
	  total[w] = total[w] + student[w].hwscore[t];
	}
    }

  for(int y=0; y < n; y++)
    {
      percent[y]= static_cast<float>(total[y])/5.0;
    }

  gradecalc(percent, grade, n);

  outfile << endl;

  outfile << left << setw(8) << "ID#" << setw(25) << "NAME" << right << setw(14) << "PCT" << setw(8) << "GRADE" << endl;

  outfile << fixed << showpoint << setprecision(2);

  for(int b=0; b < n; b++)
    {
      outfile << right << setw(3) << student[b].idnum << left << setw(5) << " " << setw(student[b].lastname.length()) << student[b].lastname << ", " << setw(14) << student[b].firstname << setw(13-student[b].lastname.length()) << " " << right << setw(10) <<  percent[b] << setw(8) << grade[b] << endl;
    }

  return 0;
}

void nameread(ifstream& in, if1 student[], int& n)
//the nameread function reads in the names of the students along with their id numbers. it also counts the number of students as they come
//in and calculates their name lengths for the formatting function.
//it is passed the filestream for the first input file as well as the student array of records and the counter. It returns the names 
//formatted but not sorted.
{
  n=0;
  int firstnamelength=0;//length of first name of the student initialized to zero
  int lastnamelength=0;//length of the last name of the student initialized to zero
  in >> student[n].idnum;
  in >> student[n].lastname;
  in >> student[n].firstname;
  while (!in.eof())
    {
      firstnamelength =student[n].firstname.length();
      lastnamelength = student[n].lastname.length(); 
      currentname(student[n].lastname, student[n].firstname, firstnamelength, lastnamelength);
      n++;
      in >> student[n].idnum;
      in >> student[n].lastname;
      in >> student[n].firstname;
    }
}

void currentname(string& lastname, string& firstname, int firstnamelength, int lastnamelength)
// the current name funtion is called from the read function. On each loop
// it is passed that name, unformatted and formats it.
//It will then pass back the name into the proper place in the array,
//properly formatted.
{
lastname[0] = toupper(lastname[0]);
firstname[0] = toupper(firstname[0]);
for(int j = 1; j < lastnamelength; j++)
 {
   lastname[j] = tolower(lastname[j]);
 }
for(int f=1; f < firstnamelength; f++)
  {
    firstname[f] = tolower(firstname[f]);
  }
}

void alphasort(if1 student[], int n)
//the alphasort function will sort the records into alphabetical order by last name. It expects the list as well as the total number of 
//names and will return the sorted array. The basic format for this function came from the class handout on bubblesorting.
{
  if1 temp;//used as a swapping mechanism
  int i; int j;// used for implementing for loop checks
  int f=1;//used for checking letters after the first
   for (i=0; i < n-1; i++)
       for (j=0; j < n-(i+1); j++)
	 if(student[j].lastname[0] > student[j+1].lastname[0])
	   {
	     temp = student[j];
	     student[j] = student[j+1];
	     student[j+1] = temp;
	   }
	 else if(student[j].lastname[0] == student[j+1].lastname[0])
	   {
	     while(student[j].lastname[f] == student[j+1].lastname[f])
	        {
		  f++;
		}
		 if (student[j].lastname[f] > student[j+1].lastname[f])
		   {
	             temp = student[j];
	             student[j] = student[j+1];
	             student[j+1] = temp;
		   }
	   }
}

void dataread(ifstream& in, if1 student[], int n) 
//the dataread function reads in and stores exam scores and home work scores into the proper place in the record for each student.
//it is passed the filestream of the second input file as well as the student array of records and the counter.
//it reads in an id number and checks for a match to a students record and if it exists, stores the necessary information into proper
//spots in the record. if no match is found in all the list of records, the rest of that line is ignored and the next id number is read
//in and checked in the same manner.
//it returns the array of records complete with previously stored information and the newly aquired exam and homework scores.
{
  string idnum;//id number from file 2 for comparison to the list of student id numbers
  char type;//type character for comparison of if it is an exam or homework score or if it is the end of line character marked by Q
  int number;//variable for which number of exam score is being read next.
  int number2;//variable for the grade of the homework score being read next. 
  in >> idnum;
  while(!in.eof())
    {
      for (int j =0; j < n; j++)
	{
	  if (idnum == student[j].idnum)
	    {
	      in >> type;
	      while(type != 'Q')
		{
		  if(type == 'E')
		    {
		      in >> number;
		      in >> student[j].examscore[number-1];
		    }
		  else if(type == 'H')
		    {
		      in >> number2;
		      in >> student[j].hwscore[number2-1];
		    }
		  in >> type; 
		}
	    }
	}
      in.ignore(1000,'\n');
      in >> idnum;
    }
}

void gradecalc(float percent[], char grade[], int n)
//the gradecalc function uses the array of percentages for the student and finds the proper letter grade for each percentage.
//it will store the letter grade into the properly ordered spot in the grade array.
//it is passed the percentages in an array, and an empty letter grade array, as well as the counter total.
//it will pass back the unaltered percentages and a list of letter grades for each student.
{
  for(int j = 0; j < n; j++)
    {
      if(percent[j] >= 90.0)
	grade[j] = 'A';
      else if(percent[j] < 90 && percent[j] >= 80)
	grade[j] = 'B';
      else if(percent[j] < 80 && percent[j] >= 70)
	grade[j] = 'C';
      else if(percent[j] < 70 && percent[j] >= 60)
	grade[j] = 'D';
      else if(percent[j] < 60)
	grade[j] = 'F';
    }
}

////////////////////

quite literally everything works except the sorting...

Would you also post the input files? Just attach them to your post .

Here is what I had in mind for the structure, but I need the input files for testing.

struct if1
{
  string idnum;//id number for the student
  string lastname;//last name of student
  string firstname;//first name of student
  int examscore[maxexam];//array of all the exam scores of the student
  int hwscore[maxhw];//array of all the home work scores of the student

  void operator=(if1& f1)
  {
      idnum = f1.idnum;
      lastname = f1.lastname;
      firstname = f1.firstname;
      memcpy(examscore, f1.examscore, sizeof(examscore));
      memcpy(hwscore,f1.hwscore,sizeof(hwscore));
  }
};

ill give you the data because the files i use dont have any extensions and i do not know which ones will still keep everything in order.

(the names are completely made up...

input 1
567 white robert
43 blackburn donna
722 Grey jAMes
19 bRoWn jAnE
25 greta jamescoonsilr
8 josephinalar billy
0 josephinalay jamescoonsilr
999 jimi hendricks
382 billy bob
2 a d

input file 2

722 E 1 95 E 2 89 E 3 90 Q
567 E 1 67 H 1 20 H 5 20 E 2 76 Q
83 this line should be ignored, 83 is not a valid ID#
19 H 1 20 H 2 20 H 3 19 H 4 18 H 5 16 Q
43 E 3 91 Q
19 H 6 20 H 7 20 H 8 20 H 9 20 H 10 18 Q
1 me 1903094389 lkadjf
722 H 5 20 H 6 20 H 7 20 Q
19 E 1 85 E 2 90 Q
567 E 3 80 Q
722 H 4 15 H 3 14 H 2 20 H 1 20 Q
25 H 10 20 E 1 90 Q

The program crashes during sort because it is attempting to reference non-existant index value. I simplified alphasort() algorithm as shown below and everything works ok.

struct if1
{
  string idnum;//id number for the student
  string lastname;//last name of student
  string firstname;//first name of student
  int examscore[maxexam];//array of all the exam scores of the student
  int hwscore[maxhw];//array of all the home work scores of the student

  void operator=(if1& f1)
  {
      idnum = f1.idnum;
      lastname = f1.lastname;
      firstname = f1.firstname;
      memcpy(examscore, f1.examscore, sizeof(examscore));
      memcpy(hwscore,f1.hwscore,sizeof(hwscore));
  }
};

...
...
<snip>
...

void alphasort(if1 student[], int n)
//the alphasort function will sort the records into alphabetical order by last name. It expects the list as well as the total number of 
//names and will return the sorted array. The basic format for this function came from the class handout on bubblesorting.
{
    if1 temp;//used as a swapping mechanism
    int i; int j;// used for implementing for loop checks
    int f=1;//used for checking letters after the first
    for (i=0; i < n-1; i++)
    {
        for (j=0; j < n-(i+1); j++)
        {
            if(student[j].lastname[0] > student[j+1].lastname[0])
            {
                temp = student[j];
                student[j] = student[j+1];
                student[j+1] = temp;
            }
        }
    }
}

Attached is the output file it produced

ahh but see thats the problem. it only sorts them alphabetically by the first letter and not the leters thereafter too.

its still not quite right, see how brown comes before billy?

thats not alphabetical.

Oh yes, here the problem if(student[j].lastname[0] > student[j+1].lastname[0]) change it to this and it will work if(student[j].lastname > student[j+1].lastname) Actually I would think you need to sort by both last name and first name, so that when two or more people have the same last name the function will sort those by first name.

void alphasort(if1 student[], int n)
//the alphasort function will sort the records into alphabetical order by last name. It expects the list as well as the total number of 
//names and will return the sorted array. The basic format for this function came from the class handout on bubblesorting.
{
    if1 temp;//used as a swapping mechanism
    int i; int j;// used for implementing for loop checks
    int f=1;//used for checking letters after the first
    for (i=0; i < n-1; i++)
    {
        for (j=0; j < n-(i+1); j++)
        {
            string n1 = student[j].lastname;
            string n2 = student[j+1].lastname;
            if(n1 == n2)
            {
                n1 = student[j].firstname;
                n2 = student[j+1].firstname;
            }
            if(n1 > n2)
            {
                temp = student[j];
                student[j] = student[j+1];
                student[j+1] = temp;
            }
        }
    }
}

thank you sir. it works now. we were told that there would be no students with the same last name, so that wasnt an issue, but thanks for finding it.

thanks for you help!

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.