Sort an array of pointers to a structure using qsort

I get weird results from trying to use qsort for this array of structures.

I have this structure:

struct access_data{ int sector; int arrival_time; int checked; int processed; }; 

I am creating an array of access_data pointers from a file so that they are sorted by arrival_time, but I need to sort them by sectors later, so I have the following:

 int compare_data(const void* a, const void* b){ if (((access_data*)a)->sector < ((access_data*)b)->sector) return 1; else if (((access_data*)a)->sector > ((access_data*)b)->sector) return -1; else return 0; } void scan(access_data* data[], int len, int sec_to_sec_seek){ qsort(data, len, sizeof(access_data*), &compare_data); show_data(data, len); } 

show_data just prints the data, but I get the following as an input; again, sorted by arrival time:

 data[0]: arrival_time: 7, sector: 3 data[1]: arrival_time: 6, sector: 8 data[2]: arrival_time: 5, sector: 6 data[3]: arrival_time: 4, sector: 5 data[4]: arrival_time: 3, sector: 12 data[5]: arrival_time: 2, sector: 10 data[6]: arrival_time: 1, sector: 1 data[7]: arrival_time: 0, sector: 2 

It’s just not sorting by sector, but by the return time of arrival. I really will completely lose what might cause this behavior.

+6
source share
3 answers

Your code tells you that you are actually trying to sort an array of pointers to a struct.

In this case, you lack the level of indirection. You also have reverse directions.

Your compare_data procedure will be useful for reverse sorting an array of structures, but you want to sort the array of pointers depending on what they point to.

 int compare_pointed_to_data(const void* a, const void* b) { // a is a pointer into the array of pointers struct access_data *ptr_to_left_struct = *(access_data**)a; struct access_data *ptr_to_right_struct = *(access_data**)b; if ( ptr_to_left_struct->sector < ptr_to_right_struct->sector) return -1; else if (ptr_to_left_struct->sector > ptr_to_right_struct->sector) return 1; else return 0; } 
+12
source

The problem is that you are telling QSort to sort the array of pointers, and as a result, the parameters in the comparator are pointers to pointers.

 int compare_data(const void* _a, const void* _b){ access_data *a = *(access_data**)_a, *b = *(access_data**)_b; if ((a)->sector < (b)->sector) return 1; else if ((a)->sector > (b)->sector) return -1; else return 0; } void scan(access_data* data[], int len, int sec_to_sec_seek){ qsort(data, len, sizeof(access_data*), &compare_data); show_data(data, len); } 

Let me know if you have any questions.

0
source

Error 1

 printf("size=%d",sizeof(access_data*)); 

prints 4, expected: 16. This was the biggest problem: sorting 8 times 4 bytes, not 8 times 16.

Oddity 2

qsort () expects a pointer to data, but scan () receives the data of a pointer to a pointer. Recommended Fix:

 void scan(access_data data[], int len, int sec_to_sec_seek){ qsort(data, len, sizeof(access_data), &compare_data); show_data(data, len); } 

Optimization 3

Your compare_data() is equal

 int compare_data(const void* a, const void* b){ return ((access_data*)b)->sector - ((access_data*)a)->sector; } 

My full work program:

 #include <stdio.h> #include <stdlib.h> struct access_data { int sector; int arrival_time; int checked; int processed; }; typedef struct access_data access_data; void show_data(access_data*data, int len) { printf("Showing size=%d",sizeof(access_data*)); for(int i=0;i<len;i++) {printf("data[%d]: arrival_time: %d, sector: %d\n",i,data[i].arrival_time,data[i].sector);} } int compare_data(const void* a, const void* b){ return ((access_data*)b)->sector - ((access_data*)a)->sector; } int compare_data1(const void* a, const void* b){ if (((access_data*)a)->sector < ((access_data*)b)->sector) return 1; else if (((access_data*)a)->sector > ((access_data*)b)->sector) return -1; else return 0; } void scan(access_data data[], int len, int sec_to_sec_seek){ qsort(data, len, sizeof(access_data), &compare_data); show_data(data, len); } int main() { printf("START\n"); access_data data[8]={ {3,4,5,6}, {2,1,5,5}, {1,1,3,6}, {4,4,5,4}, {5,4,3,4}, {6,2,5,6}, {7,2,5,4}, {0,4,5,6} }; scan(data,8, 0); } 
0
source

Source: https://habr.com/ru/post/969362/


All Articles