Reputation: 575
I am loading some data into struct.
struct test {
char x[101];
char y[101];
int z;
};
Then I create memory for structs
struct test * data;
data = malloc(10 * sizeof(struct test));
And fill data like this
data[0].z = 123;
This works alright. But I wanna sort these structs. Like sort them depending on z attribute.
My idea was to create a new array and fill it with pointers which will point to the right struct.
Can somebody tell me how or if there is better way?
Thanks
Upvotes: 1
Views: 575
Reputation: 66234
One way to do this is using qsort, the general sorting algorithm provided in the standard library for sorting sequences of user-defined data. With a goal of doing the following:
this is one way to do that using the qsort()
standard library function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct test {
char x[101];
char y[101];
int z;
};
int cmp_test_ptrs(const void* arg1, const void* arg2)
{
struct test const * lhs = *(struct test const * const*)arg1;
struct test const * rhs = *(struct test const * const*)arg2;
return (lhs->z < rhs->z) ? -1 : (rhs->z < lhs->z);
}
int main()
{
srand((unsigned int)time(0));
// populate data array.
struct test * data = malloc(10 * sizeof(*data));
for (int i=0; i<10; ++i)
{
data[i].z = rand() % 20;
printf("%d ", data[i].z);
}
printf("\n");
// allocate a pointer array to use as a sort-bed, copying each
// structure address into this pointer array afterward
struct test **ptrs = malloc(10 * sizeof(*ptrs));
for (int i=0; i<10; ++i)
ptrs[i] = data+i;
// sort the pointer bed using our comparator
qsort(ptrs, 10, sizeof(*ptrs), cmp_test_ptrs);
// ptrs now has sorted pointers. Note the dereference for access
// to the actual data, which remains where it originally was.
for (int i=0; i<10; ++i)
printf("%d ", ptrs[i]->z);
printf("\n");
free(ptrs);
free(data);
return 0;
}
Sample Output
11 7 6 17 8 8 11 4 7 5
4 5 6 7 7 8 8 11 11 17
Important to note is the original structure array remained untouched. We sorted a sequence of pointers, not the actual structures themselves, and used what those pointers pointed-to as the criteria for the sort.
Anyway, I hope it helps. Study the comparator and the setup for qsort()
carefully. They're important. You can read more about qsort()
here.
Upvotes: 0
Reputation: 1791
Or you can just sort them in the same array and probably save some memory (4 bytes for a pointer of any type) :P
Doesn't really matter though, pointers'll work fine I guess.
But I think that in some cases pointers will be more useful as if you would sort it in the array you'll need a temporary struct defined to contain structs when you're sorting and if you're struct is big than you'll actually take a lot more memory than 4 bytes.
+Also remember that when defining a pointer to a struct - access it with ->
operator.
Usage: STRUCT_POINTER_NAME->VARIABLE
Upvotes: 0
Reputation: 153
This depends on your goal. If you are trying to figure out what would be most programmer efficient, then creating an ordering functor based on the z attribute of your struct, and sorting the list directly, is easiest.
However, if you are concerned with program efficiency, then it will be faster to sort pointers, as suggested by Fiddling Bits. However, you must keep in mind that this will give you a sorted list of pointers- your data array will still be in the same order.
For instance, if datapoints
is your array of pointers, and you wanted to sort by the z value, you could define the comparison
int compare(const void *a, const void *b)
{
return ( (*(test *)a).z -(*(test *)b).z );
}
And then call
qsort( datapoints, 10, sizeof(test), compare);
Full documentation for qsort can be found here:
Upvotes: 2