Home > Software design >  Sorting array not working and changes a member variable C
Sorting array not working and changes a member variable C

Time:11-03

C . I'm tring to get records from a file and store a sorted copy to a different file.

When I call the void sort(Student A[], int count) function with sort(newStudent, Student::getnStudents()); the program will crash if the second argument is over 3 (no errors/warnings).

After sort is called, some entries will have their classList[0] be complete gibberish symbols. Not sure why. I used const for the overloaded <. Commenting out sort has the program run as expected.

enter image description here

#include <iostream>
#include <fstream> //for input output files
using namespace std;

#include "student.h"
#include "student.cpp"

// Inputs students from a text file using "lname fname n (list of n classes)" and sorts them to a seperate text file.
// Includes statistics about classes and the number of students taking each class.

//==================================================
void sort(Student A[], int count) { // Sort function     // <- PROBLEM
    for (int i=1; i<count; i  ) {
        for (int j=i; (j>0) && (A[j] < A[j-1]); j--) {
            swap(A[j],A[j-1]);
        }
    }
}

//==================================================

int main(int argc, char *argv[]) {
    if (argc != 4) {
        cout << "Usage:  " << argv[0] << " (input) (output) (# of elements)" << endl;
        exit(1);
    }

    // Variables from argv. input/output location and max elements for Student
    string inputFile = argv[1];
    string outputFile = argv[2];
    int maxStudents = atoi(argv[3]);
    // Array to calculate class statistics
    int numberClasses[6] = {0};
    string classNames[6] = {"CSC121", "CSC127", "CSC275", "CSC375", "CSC377", "CSC381"};
    // Array that is a copy of numberClasses
    int numberClasses2[6];
    // Most and least common classes
    string mostCommon;
    string leastCommon;
    // Average number of classes per student
    float avgClasses = 0.0;
    // Student array
    Student *newStudent;
    newStudent = new Student[maxStudents];

//==================================================

    ifstream inStream;
    inStream.open(inputFile);

    for (int i=0; i<maxStudents; i  ) {
        inStream>>newStudent[i];
    }

    inStream.close();

//==================================================

    ofstream outStream;
    outStream.open(outputFile);

    for(int i=0; i<Student::getnStudents(); i  ) {  //  TEST BEFORE
        cout<<newStudent[i]<<endl;
    }

    sort(newStudent, Student::getnStudents());      //  <- THIS IS THE PROBLEM

    cout<<endl;
    for(int i=0; i<Student::getnStudents(); i  ) {  //  TEST AFTER
        cout<<newStudent[i]<<endl;
    }

    for(int i=0; i<Student::getnStudents(); i  ) {
        outStream<<newStudent[i]<<endl;
    }

    outStream.close();

//==================================================

    // Go through student array and their class list to increase the corresponding numberClasses array. EX: numberClasses[0] = classNames[0].
    for(int i=0; i<Student::getnStudents(); i  ) {
        for (int j=0; j<newStudent[i].getnclasses(); j  ) {
            for (int k=0; k<6; k  ) {
                if (newStudent[i].getclassList(j) == classNames[k]) {numberClasses[k]  ;}
            }
        }
    }

    // loop to print statistics of number of students taking each class
    for (int i=0; i<6; i  ) {
        cout<<endl<<"Number of students taking "<<classNames[i]<<": "<<numberClasses[i];
    }

//==================================================

    for (int i=0; i<6; i  ) {
        numberClasses2[i] = numberClasses[i];
    }

    // Sort numberClasses2
    for (int i=0; i<6; i  ) {
        for (int j=i; (j>0) && (numberClasses2[j] < numberClasses2[j-1]); j--) {
            swap(numberClasses2[j],numberClasses2[j-1]);
        }
    }

    // Compare numberClasses2 to numberClasses
    for (int i=0; i<6; i  ) {
        if (numberClasses2[6-1] == numberClasses[i]) {
            mostCommon = classNames[i];
        }
        if (numberClasses2[0] == numberClasses[i]) {
            leastCommon = classNames[i];
        }
    }

    // Calculate average classes taken per student
    for (int i=0; i<Student::getnStudents(); i  ) {
        avgClasses  = newStudent[i].getnclasses();
    }
    avgClasses = avgClasses/Student::getnStudents();

//==================================================

    // Print rest of statistics
    cout<<endl<<"Most common course: "<<mostCommon;
    cout<<endl<<"Least common course: "<<leastCommon;
    cout<<endl<<"Average number of courses taken, per student: "<<avgClasses;

    return 0;

}
#ifndef STUDENT_H
#define STUDENT_H

class Student {
  public:
    Student();      //  Constructor
    ~Student();     //  Destructor

    // Accessors
    string getclassList(int idx) { return classList[idx]; }
    static int getnStudents(){return nStudents;}
    int getnclasses(){return nclasses;}

    // Overloaded I/O stream operators
    friend istream& operator>> (istream&, Student&);
    friend ostream& operator<< (ostream&, const Student&);

    // Overloaded compare
    friend bool operator < (const Student& S1, const Student& S2);

  private:
    string lname;       // Person's last name
    string fname;       // Person's first name
    int nclasses;       // Number of courses enrolled in
    string *classList;  // An array of strings for names of courses enrolled in

    // Static variables for # of students
    static int nStudents;
};

int Student::nStudents = 0;

#endif
#include "student.h"

using namespace std;

//  Destructor
Student::~Student() {
    delete[] classList;
    classList = NULL;
}

// Default constructor
Student::Student() : fname("First"), lname("Last") {
  classList = new string[6];
}

//==================================================

// Overloaded input
istream& operator >> (istream& inputStream, Student& S){
    inputStream >> S.lname;
    inputStream >> S.fname;
    inputStream >> S.nclasses;
    for (int i=0; i<S.nclasses; i  ) {
        inputStream >> S.classList[i];
    }

    if (S.nclasses>0) {Student::nStudents  ;}

    return inputStream;
}

// Overloaded output
ostream& operator<< (ostream& outputStream, const Student& S){
    outputStream<<S.lname<<" "<<S.fname<<" "<<S.nclasses;
    for (int i=0; i<S.nclasses; i  ) {
        outputStream<<" "<<S.classList[i];
    }

    return outputStream;
}

//==================================================

// Overloaded compare
bool operator < (const Student& S1, const Student& S2) {
    if (S1.lname == S2.lname) {
        return (S1.fname <= S2.fname);
    }
    return (S1.lname < S2.lname);
}

I've tried changing the sort function. Changing the overloaded < compare. Making lname public and comparing lname of two Student Arrays in the sort function without an overloaded <. This used to work, but then I changed something and now I can't figure out what else to do to fix it.

CodePudding user response:

Looks like you implement sorting not correct. Looks like you try to implement Selection Sort.

void selectionSort(Student A[], int count) {
    for (int i = 0; i < count; i  ) {
        for (int j = i   1; j < count; j  ) {
            if (A[j] < A[i]) {
                swap (A[i], A[j]);
            }
        }
    }
}

CodePudding user response:

The issue was the classList member variable (part of the class I was trying to sort) is a raw pointer and does not follow the rule of three. I modified that variable and now it works.

  • Related