1

I have this struct.

struct Transport
{
   int id;
   float Price;
};

Here I read the data into and array of structs.

void read (struct Transport **Car, int *m)
{
    int i;
    printf("Insert total number of cars: ");
    scanf("%d",m);
    *Car=(struct Transport*) malloc ((*m)*3*sizeof(struct Transport));               

    for(i=1; i<=*m; i++)
    {
       (*Car)[i].id=i;
       printf("Price: ");
       scanf("%f",&(*Car)[i].Price);
       printf("\n");
    }
}

And here is the display function.

void display(struct Transport *Car,int m)
{
    int i;
    for(i=1; i<=m; i++)
    {
        printf("Entry #%d: \n",i);
        printf("Price: %2.2f\n",(Car+i)->Price);
        printf("\n");
    }
}

Now here is the problem.I must sort the data by the Price field. So far I've tried this, but it does nothing.

int struct_cmp_by_price(const void *a, const void *b)
{
    struct Transport *ia = (struct Transport *)a;
    struct Transport *ib = (struct Transport *)b;
    return (int)(100.f*ia->Price - 100.f*ib->Price);
}

Here is how the main looks like.

int main()
{
    int m;
    struct Transport *Car;
    read(&Car,&m);
    qsort(Car, m, sizeof(struct Transport), struct_cmp_by_price);
    display(Car,m);
    return 0;
}

Can anyone help me?

5
  • 1
    qsort(Car, --> qsort(Car+1, or for(i=1; i<=*m --> for(i=0; i<*m Commented Nov 29, 2016 at 22:12
  • 1
    Array indices start at 0 in C Commented Nov 29, 2016 at 22:14
  • Sorting against the Car+1 does not fix the off the end of the array adds. Change the for loops. Commented Nov 29, 2016 at 22:17
  • that worked, thanks a lot! Commented Nov 29, 2016 at 22:18
  • @MichaelDorgan It is secured three times as necessary. malloc ((*m)*3*sizeof(struct Transport)); Commented Nov 29, 2016 at 22:28

2 Answers 2

1

There are multiple problems in your code:

  • You allocate too much memory in read(), and you do not need to cast the return value of malloc() in C, but you should check for allocation failure. you should instead use:

    *Car = calloc(*m, sizeof(struct Transport));
    if (*Car == NULL) {
        fprintf(stderr, "cannot allocate memory for %d structures\n", *m);
        exit(1);
    }
    
  • You should not use read as a function name because it is the name of a system call and may conflict with the standard library use of that function. Use readTransport.

  • indexes are 0 based in C. Instead of for(i=1; i<=*m; i++), use:

    for (i = 0; i < *m; i++)
    
  • The comparison function cannot use the subtraction trick. As a matter of fact, the subtraction trick can only be used for integer types smaller than int. Use this instead:

    int struct_cmp_by_price(const void *a, const void *b) {
        const struct Transport *ia = a;
        const struct Transport *ib = b;
        return (ia->Price > ib->Price) - (ia->Price < ib->Price);
    }
    
  • You should test the return value of scanf() to detect invalid input. The Price members are left uninitialized in case of conversion failure, which leads to undefined behavior, unless you use calloc(), but the result is still meaningless.

Sign up to request clarification or add additional context in comments.

Comments

0

You can also try using two separate structs, to make pointer operations easier to handle.

Something like this gives the right idea:

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

typedef struct {
    int id;
    float price;
} transport_t;

typedef struct {
    transport_t *Cars;
    int numcars;
} Cars_t;

Cars_t *initialize_struct(void);
void read(Cars_t *Car);
void display(Cars_t *Car);
int price_cmp(const void *x, const void *y);

int 
main(void) {
    Cars_t *Car;

    Car = initialize_struct();

    read(Car);

    printf("Before:\n");
    display(Car);

    qsort(Car->Cars, Car->numcars, sizeof(transport_t), price_cmp);

    printf("\nAfter:\n");
    display(Car);

    free(Car->Cars);
    free(Car);

    return 0;
}

void
read(Cars_t *Car) {
    int i, count = 0;

    printf("Insert total number of cars: ");
    if (scanf("%d", &(Car->numcars)) != 1) {
        printf("Invalid entry\n");
        exit(EXIT_FAILURE);
    }

    Car->Cars = calloc(Car->numcars, sizeof(transport_t));
    if (Car->Cars == NULL) {
        fprintf(stderr, "Issue allocating memory for %d members", Car->numcars);
        exit(EXIT_FAILURE);
    }

    for (i = 1; i <= Car->numcars; i++) {
        Car->Cars[count].id = i;
        printf("Car id %d\n", Car->Cars[count].id);

        printf("Price: ");
        scanf("%f", &(Car->Cars[count].price));

        count++;

        printf("\n");
    }
}

void
display(Cars_t *Car) {
    int i;

    for (i = 0; i < Car->numcars; i++) {
        printf("Car id: %d, Car price: %2.2f\n", 
                Car->Cars[i].id, Car->Cars[i].price);
    }
}

Cars_t
*initialize_struct(void) {
    Cars_t *Car;

    Car = malloc(sizeof(*Car));
    if (Car == NULL) {
        fprintf(stderr, "%s", "Issue allocating memory for structure");
        exit(EXIT_FAILURE);
    }

    Car->Cars = NULL;
    Car->numcars = 0;

    return Car;
} 

int
price_cmp(const void *x, const void *y) {
    const transport_t *car1 = x;
    const transport_t *car2 = y;

    if (car1->price > car2->price) {
        return +1;
    } else if (car1->price < car2->price) {
        return -1;
    }
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.