I want to sort an array of pointers by Id's. However qsort fails to work because of my lack of experience with pointers.
typedef struct block{
int Id;
char * name;
} block;
typedef struct {
block ** data;
int size_array;
} database;
if( ( database = malloc(sizeof(database)) ) == NULL ) {
printf("Error: malloc failed\n");
exit(EXIT_FAILURE);
}
if( ( database->data = malloc( sizeof( block * ) * database->size_array ) ) == NULL ) {
exit(EXIT_FAILURE);
}
for( i = 0; i < database->size_array; i++ ) {
DB->data[i] = NULL;
}
I'm trying to sort using qsort, but I'm clearly doing something wrong.
int compare(const void * a, const void * b ){
const block * eval1 = a;
const block * eval2 = b;
if (eval1->Id < eval2->Id){
return(-1);
}
else if (eval1->Id > eval2->Id)
return 1;
return 0;
}
Calling code:
qsort(database->data, database->size_array, sizeof(int), compare);
for(i = 0; i<DB->database->size_array; i++) {
if(database->data[i] != NULL)
printf("Id: %d\n", database->data[i]->Id);
}
By using a for loop I see that the sorting failed.
Insert Function:
void insertE(int Id, char * name){
block * item = malloc(sizeof(block));
item->name = malloc(strlen(name)+1);
strcpy(item->name, name);
item->Id = Id;
}
current output:
Id: 13
Id: 243
Id: 121
Id: 87
.
.
.
You have an array of pointers to
block
, not an array ofint
. Thesizeof
argument is the size of the elements in the array, not the size of the data you want to compare.So the correct call would be e.g.
When you use
qsort()
(orbsearch()
or other similar functions), the pointers passed to your comparison function are of the type 'pointer to the array element type'. If you pass an array ofint
, the comparison function is passedint *
(disguised asvoid *
). Consequently, if you have an array ofblock *
, the type passed to the comparator is ablock **
(disguised as avoid *
).Hence you need something like this (though there are other ways to write it too):
However, there are other problems too. Your call to
qsort
is suspect; the size of the array elements issizeof(db->data[0])
(assumingdb
is a variable of typedatabase *
), which is alsosizeof(block *)
. In general, on 64-bit Unix and Windows systems in particular,sizeof(int) != sizeof(block *)
. You will get away with usingsizeof(int)
on platforms wheresizeof(int) == sizeof(void *)
, a category which include most 32-bit systems. Therefore, you need to fix the call toqsort()
too:MCVE
Any residual problems are most probably related to how the array of block pointers is populated. Here is an MCVE (Minimal, Complete, Verifiable Example) that shows the sort working on an array of block pointers. It assumes you have a C99 or C11 compiler available — it uses 'compound literals' which were not in C90.
The
dump_blocks()
function follows a pattern I find very useful: the function takes a string tag that is printed first to identify which set of output is being dumped, and then prints all the relevant information from the data structure (using otherdump_xxxxx()
functions if appropriate). This can then be called in multiple places. If need be, I provide aFILE *fp
output stream as a first argument; it didn't seem to be necessary here. It can also usefflush(fp);
orfflush(stdout);
or perhapsfflush(0);
at the end of the function to ensure that the output is produced. This can help when debugging a program that's crashing. Note that the outputs are terminated with a newline to help ensure they appear in a timely manner.Example output: