D33J4Y
D33J4Y

Reputation: 11

Is there a way to program a better code for sorting a struct in C?

I'd like to sort the items with the cheapest on top. The c code works fine, I'm just wondering if there's a better way to sort a struct in c?

typedef struct
{
  float price;  
  char  product[50]; 
  char  brand[50]; 
}clothes;

void sort(clothes*pt, int count)
{
 int a, b;
 float price;
 char product[50];
 char brand[50];
 for(a = 0; a < count - 1; a++){
    for(b = a + 1; b < count; b++){
        if((pt+a)->price > (pt+b)->price){
            price = ((pt+b)->price);
            strcpy(product,(( pt+b)->product));
            strcpy(brand,((pt+b)->brand));
            ((pt+b)->price) = ((pt+a)->price);
            strcpy(((pt+b)->product),((pt+a)->product));
            strcpy(((pt+b)->brand),((pt+a)->brand));
            ((pt+a)->price) = price;
            strcpy(((pt+a)->product),product);
            strcpy(((pt+a)->brand),brand);
        }
    }
  }
}

Upvotes: 1

Views: 89

Answers (3)

Juan Leni
Juan Leni

Reputation: 7638

If you want to be a little more efficient:

  • Create an array of pointers to your structs.
  • Later, use qsort to sort the array of pointers.

This is almost the same as the other answers so I won't explain it some details again.

The KEY difference in my suggestion is that by sorting pointers to your structs you don't need to copy the contents of the whole struct every time qsort swaps.

Look for instance, how other answers pass sizeof(clothes):

 qsort(pt, count, sizeof(clothes), compare);

That means that when the struct is big, you need more work If you were just sorting pointers it would be much faster.

 qsort(pt, count, sizeof(clothes*), compare);

but you need to adjust your array and the comparison function

Upvotes: 2

Crowman
Crowman

Reputation: 25936

You can use the standard qsort(). Here's an example:

#include <stdio.h>
#include <stdlib.h>

typedef struct clothes {
    float price;
    char product[50];
    char brand[50];
} clothes;

int sort_clothes(const void *s1, const void *s2) {
    const struct clothes *c1 = s1;
    const struct clothes *c2 = s2;
    if (c1->price == c2->price) {
        return 0;
    } else if (c1->price < c2->price) {
        return -1;
    } else {
        return 1;
    }
}

void print_clothes(struct clothes * c, const size_t count)
{
    for ( size_t i = 0; i < count; ++i ) {
        printf("%s, %s: %f\n", c[i].product, c[i].brand, c[i].price);
    }
}

int main(void)
{
    struct clothes c[] = { {59.99, "Jeans", "Levi"},
                           {10.99, "T-shirt", "Acme"},
                           {5.99, "Socks", "Feet Inc."} };

    printf("Before sorting...\n");
    print_clothes(c, 3);

    printf("\nAfter sorting...\n");
    qsort(c, 3, sizeof *c, sort_clothes);
    print_clothes(c, 3);

    return 0;
}

which outputs:

paul@thoth:~/src/sandbox$ ./sortstruct
Before sorting...
Jeans, Levi: 59.990002
T-shirt, Acme: 10.990000
Socks, Feet Inc.: 5.990000

After sorting...
Socks, Feet Inc.: 5.990000
T-shirt, Acme: 10.990000
Jeans, Levi: 59.990002
paul@thoth:~/src/sandbox$ 

Upvotes: 2

You could, and you probably should, use the standard sorting function qsort(3). You need to give it a compare function.

static int compare_clothes_by_price (const void*p1, const void*p2) 
{
   const clothes* c1 = (const clothes*)p1;
   const clothes* c2 = (const clothes*)p2;
   if (c1->price == c2->price) return 0;
   else if (c1->price < c2-price) return -1;
   else if (c1->price > c2-price) return 1;
   // this is reached only if a price is NAN
   abort();
}

Then you call

 qsort(pt, count, sizeof(clothes), compare_clothes_by_price);

Upvotes: 2

Related Questions