c++arraysstructqsort

Sorting struct arrays in C++ with qsort


I would like to use qsort() to sort an array of the student struct. First have it sort by grade, and then try it again using the student ID.

I'm seeing two problems:

  1. Although the grades are sorted correctly (ascending order), why do the grades not correspond to the respective student name?
  2. Why does some of the student names get cut off (like 'Ver' instead of "Veronica"?

RESULTS

Sorted by grades 
Ver Grade: 28
Alistair Grade: 68
Fred Grade: 70
Erin Grade: 75
Lesli Grade: 78
Belind Grade: 81
Sash Grade: 84
Tom Grade: 87
Aretha Grade: 98
Candy Grade: 100

CODE

#include <iostream>
#include <string>
using namespace std;

struct student {
    int grade;
    int studentID;
    string name;
};

const int ARRAY_SIZE = 10;
student studentArray[ARRAY_SIZE] = {
    {87, 10001, "Fred"},
    {28, 10002, "Tom"},
    {100, 10003, "Alistair"},
    {78, 10004, "Sasha"},
    {84, 10005, "Erin"},
    {98, 10006, "Belinda"},
    {75, 10007, "Leslie"},
    {70, 10008, "Candy"},
    {81, 10009, "Aretha"},
    {68, 10010, "Veronica"}
};


// Comparator Function 
int compareFunc(const void* voidA, const void* voidB)
{
    student* studentA = (student*) voidA;
    student* studentB = (student*) voidB;
    return (studentA->grade - studentB->grade);
}

int main()
{
    // Use qsort to sort an array of our student struct 
    qsort(studentArray, ARRAY_SIZE, sizeof(student), compareFunc);
    
    // First sort by grade
    cout << "Sorted by grades \n";
    for (int i = 0; i < ARRAY_SIZE; i++)
    {
        cout << studentArray[i].name << " Grade: " << studentArray[i].grade  << '\n';
    }
    
    // Second sort by student ID

Not too sure where I went wrong, thoughts are appreciated.


Solution

  • As @john commented above you cannot use std::qsort with a type which is not TriviallyCopyable (assuming C++11) or PODType (before C++11), and your isn't because it contains a std::string:

    From std::qsort:

    If the type of the elements of the array is not a PODType (until C++11) TriviallyCopyable type (since C++11), the behavior is undefined.

    (emphasys is mine)

    Instead you can use std::sort.
    You can also use a lambda instead of an external compare function:

    #include <algorithm>
    
    // ...
    
    std::sort(std::begin(studentArray), 
              std::end(studentArray),
              [](student const& a, student const& b) { return (a.grade > b.grade); });
    

    Side notes:

    1. Why is "using namespace std;" considered bad practice?.
    2. In C++ it is recommended to use std::vector or std::array instead of raw C arrays.