Reputation: 129
So I have a custom data type 'Medicine'. I also created an array where I store not instances of this data type, but pointers to instances of this data type. So each element from the array points to an instance of the data type. I want to sort this array using the name of each medicine. I have already done it using a selection sort that I wrote, but I'm trying to do it using the qsort
function, so that I shorten the code. The problem is that I can't figure out how to write the compare
function which I need to pass to the qsort
function. It's not as easy as usual, since as I said I don't have instances in the array but rather pointers to instances of the array. This is the code that I wrote:
int compare(const void *a, const void *b) {
Medicine *m1 = *((Medicine **) a);
Medicine *m2 = *((Medicine **) b);
if (strcmp(get_medicine_name(m1), get_medicine_name(m2)) < 0) {
return 1;
}
return -1;
}
void sort_medicine_descending_name(DynamicArray *meds) {
qsort(meds, get_dynamic_array_size(meds), sizeof(Medicine*), compare);
}
When I run this code I get a segmentation fault. I am positive that I don't have bugs in other parts of my code since I have quite a few other functions and they all work fine. I think my problem is when I try to cast and dereference those void pointers (although I am not sure). My logic behind it went something like this: Since I have pointers to Medicine in my array I need to type cast the arguments a
and b
as pointer to pointer, and then dereference them so that I get the pointers to Medicine. But since it didn't work, my intuition was clearly wrong. I'm still not fully competent when it comes to working with pointers, so I don't really know why this is not right, nor what I should do instead.
This is my implementation for Dynamic Array:
typedef struct {
int capacity;
int size;
void **elems;
} DynamicArray;
I create instances of this dynamic array using the following "constructor":
DynamicArray *create_dynamic_array(int capacity) {
DynamicArray *da = (DynamicArray *) malloc(sizeof(DynamicArray));
da->capacity = capacity;
da->size = 0;
da->elems = (void**) malloc(sizeof(void*) * capacity);
return da;
}
The way I wanted to write it is so that a dynamic array can store any type of elements. That's why da->elems
is a pointer to pointer of void. This way I can just store the pointer to any data type in the dynamic array. So I can store the meds in a dynamic array by storing pointers to instances of Medicine
(which, by the way, is also dynamically allocated). da->capacity
is the capacity of the dynamic array, and whenever the array gets filled the capacity increases. da->size
is the current number of elements in the dynamic array, which increases whenever I add an element to it and decreases whenever I remove an element.
I get the size of the dynamic using the following function:
int get_dynamic_array_size(DynamicArray *da) {
return da->size;
}
Finally, the "class" Medicine
stores, among other things, a dynamically allocated char array where the name is stored. get_medicine_name()
takes as argument a pointer to medicine and returns the pointer to this char array.
Upvotes: 0
Views: 177
Reputation: 6925
The problem of your code is, that qsort
assumes that it gets an array of equal types.
But you pass your root structure to that. So your compare
function gets the size
and capacity
member as the pointer, that surely cause a segfault.
Instead you should pass the elem
array.
qsort(meds->elem, meds->size, sizeof(*meds->elem), compare);
Upvotes: 1