简体   繁体   中英

Address boundary error when sorting an array of structs

I am working through a book called "Think Like a Programmer." Chapter 2 is about solving problems with arrays. There's an exercise at the end of the chapter that asks us to use qsort to sort a an array of structs created earlier in the chapter.

Following the process of the chapter, I created a function, comparator that will be passed to qsort to sort the array, studentArray . My code is...working? However, I'm getting an Address boundary error when running it.

#include <string>
#include <iostream>

using std::cout;
using std::string;

int comparator(const void * voidA, const void * voidB) {
  int * intA = (int *)(voidA);
  int * intB = (int *)(voidB);

  return *intA - *intB;
}

int main() {

  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"},
  };

  qsort(studentArray, ARRAY_SIZE, sizeof(student), comparator);

  for (int i = 0; i < ARRAY_SIZE; i++) {
    cout << studentArray[i].grade << "\n";
  }
}

My first assumption was that I messed up the call to qsort with the third parameter. Maybe, I thought, I should only be asking for the size of the first member of the struct (since that's what the first part of the exercise asks us to sort). So, I changed it to:

qsort(studentArray, ARRAY_SIZE, sizeof(student[0]), comparator);

This didn't throw any errors, but it didn't sort the array either. So, all in all, I think I'm just confused about what I'm doing wrong. I don't work with C++ regularly, it's just for the purpose of the book. However, I am really enjoying using it and learning about it, so I would like to understand what causes this problem*. I have searched around online for a while and have seen similar asks, but I can't seem to piece together a solid understanding. I will update this post with any missing information; please just let me know what's needed. I appreciate any and all help with this and hope that it makes sense.

As stated above, I tried a few different things (some of which I'm too embarrassed to mention here).

EDIT: I appreciate the comments and the resources: I'll add one more question to this post? are the concepts taught in the book so closely coupled with the author's C++ implementation that one wouldn't be able to understand what causes this error without a proper understanding of modern C++? Thanks again!

For comparisson if your book was more current code would look like this: As you see you can use a custom compare function as argument to sort.

#include <algorithm> // for sort.
#include <string>
#include <iostream>
#include <vector>

//using std::cout;
//using std::string;

/*
int comparator(const void* voidA, const void* voidB) {
    int* intA = (int*)(voidA);
    int* intB = (int*)(voidB);

    return *intA - *intB;
}
*/

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

bool compare_students_by_grade(const student& lhs, const student& rhs)
{
    return lhs.grade < rhs.grade;
}

int main() 
{
    std::vector<student> students = // avoid types in your names
    {
      {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"},
    };

    //qsort(studentArray, ARRAY_SIZE, sizeof(student), comparator);
    std::sort(students.begin(), students.end(), compare_students_by_grade); 

    /*
    for (int i = 0; i < ARRAY_SIZE; i++) {
        cout << studentArray[i].grade << "\n";
    }
    */

    // prefer range based for loops, they cannot go out of range
    for (const student& student : students)
    {
        std::cout << student.name << " has grade : " << student.grade << "\n";
    }

    return 0;
}

student& is a reference to an instance of student (kind of like a pointer that must be valid al the time)

As mentioned in a comment, your comaprator pretends that the pointers it gets passed are pointers to int but they are pointers to student . Use std::sort :

#include <string>
#include <iostream>
#include <algorithm>
using std::cout;
using std::string;

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

bool comparator(const student& a, const student& b) {
    return a.grade < b.grade;
}

int main() {
  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"},
  };

  std::sort(std::begin(studentArray),std::end(studentArray),comparator);

  for (int i = 0; i < ARRAY_SIZE; i++) {
    cout << studentArray[i].grade << "\n";
  }
}

Here, the comparator is type safe, using wrong types would result in a compiler error. Also, you need not manually specify the number of elements or their size.

Note, that this answer illustrates how to change your code for more idomatic C++. The code presented here on the other hand is only replacing qsort and minimum changes otherwise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM