user2976389
user2976389

Reputation: 575

Saving pointers of struct c

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

Answers (3)

WhozCraig
WhozCraig

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:

  • the source data must remain un-touched.
  • the "sorted" access must be provided via a list of pointers to the untouched data from above

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

Zach P
Zach P

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

LucidLunatic
LucidLunatic

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

Related Questions