Problem with qsort () - Sorting is incorrect (C)

I have a question regarding qsort.

This is a bit strange, but my qsort function does not give me the correct result. It’s strange that some of my comparison functions are identical to my past projects, but they don’t give me the correct input at all. I'm not sure how to test it.

For instance:

int comp_name_asc(const void *a, const void *b) { const Rec *prec1 = (const Rec *) a; const Rec *prec2 = (const Rec *) b; return strcmp(prec1->name, prec2->name); } int comp_name_desc(const void *a, const void *b) { const Rec *prec1 = (const Rec *) a; const Rec *prec2 = (const Rec *) b; return strcmp(prec2->name, prec1->name); } 

The second function should be decreasing, but the result is identical: it is always in ascending order. I checked that the correct function was introduced at the right time. Rec is a typedef for the structure I created that has a char * parameter for the name.

Also (EDIT to avoid overflow):

 int comp_size_asc(const void *a, const void *b) { const Rec *prec1 = (const Rec *) a; const Rec *prec2 = (const Rec *) b; if (prec1->byteSize > prec2->byteSize) return 1; else if (prec1->byteSize < prec2->byteSize) return -1; else return 0; } 

The result is completely strange, not upward or downward (i.e.: 500, 515, 100, 200 ...). byteSize is of type off_t, obtained:

 char *path; // Build the path struct stat sb; if (lstat(path, &sb) == 0) { // Read sb.st_size 

I'm really not sure how to debug this. All I know is that the corresponding comparison function is introduced, and that some similar comparison functions are used to work in the past.

Any ideas or how I can debug this is welcome. Thanks.

EDIT:

Adding a call to qsort:

 int index = 0; Rec **array = (Rec **) malloc(sizeof(Rec *) * capacity); // Adds element to the array... qsort(array, index, sizeof(Rec *), comp_name_desc); 

(Each time an element is added to an array, the index increases.)

Thanks.

EDIT:

The solution was given below. Thanks!

I had to change:

 const Rec *prec1 = (const Rec *) a; 

to

 const Rec *prec1 = *(const Rec **) a; 

due to the way i defined my array. Thanks!

+4
source share
3 answers

Do you have an array of Rec , or rather an array of Rec pointers? I ask, because the comparison function receives pointers in the array as parameters, and not directly into your records.

Here is a demonstration of both ways:

 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Rec { char *name; } Rec; /* * The pointers a and b point directly into the array, * where the Records themselves are. */ static int cmp_Rec_by_name(const void *a, const void *b) { const Rec *rec1 = (Rec *)a; const Rec *rec2 = (Rec *)b; return strcmp(rec1->name, rec2->name); } /* * The pointers point directly into the array, where * not the records but pointers to them are. So they * are a pointer to a pointer to a record. */ static int cmp_Rec_ptr_by_name(const void *a, const void *b) { const Rec *rec1 = *(Rec **)a; const Rec *rec2 = *(Rec **)b; return strcmp(rec1->name, rec2->name); } static void sort_Rec(void) { Rec record[3]; record[0].name = strdup("hello"); record[1].name = strdup("world"); record[2].name = strdup("how are you"); qsort(record, 3, sizeof (Rec), cmp_Rec_by_name); for (int i = 0; i < 3; i++) printf("%s\n", record[i].name); } static void sort_Rec_ptr(void) { Rec *(record[3]); record[0] = malloc(sizeof (Rec)); record[1] = malloc(sizeof (Rec)); record[2] = malloc(sizeof (Rec)); record[0]->name = strdup("hello"); record[1]->name = strdup("world"); record[2]->name = strdup("how are you"); qsort(record, 3, sizeof (Rec *), cmp_Rec_ptr_by_name); for (int i = 0; i < 3; i++) printf("%s\n", record[i]->name); } int main() { sort_Rec(); sort_Rec_ptr(); return 0; } 
+2
source

You should never compare numbers by subtracting one from the other. This will usually lead to overflow with signed types and will not work with unsigned types at all. The general idiom for comparing numbers with the result of three states is as follows

 (a > b) - (a < b) 

Otherwise, the comparison functions look great, so the problem should be how you call the sort function.

+1
source

to hear that this behavior may be supposedly that the names are not really names if strcmp() has two arguments and the results are still increasing. One suggestion might be to print the names using printf , as well as shorten the names to 2 or 3 (number of entries) to simplify debugging and check why this is so.

0
source

All Articles