Нужна помощь с использованием qsort с массивом структур - PullRequest
8 голосов
/ 24 мая 2011

Теперь я видел различные примеры, но я не понимаю, что они имеют в виду.

Вот моя структура

typedef struct profile{
    char gender[1];
    double soc;
       . . .
} PROFILE;

, где soc - это номер социального страхования, на который я идусортировать по.

Я знаю, что вам нужна функция сравнения, но я не знаю, как найти именно то, что мне нужно.

Ответы [ 4 ]

22 голосов
/ 13 января 2013

Вот пример использования qsort для массива структур в C

/* qsort example */
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int price;
    int id;
} order;
order list[6];
int i = 0;

int compare (const void * a, const void * b)
{

  order *orderA = (order *)a;
  order *orderB = (order *)b;

  return ( orderB->price - orderA->price );
}

int main ()
{
    srand ( time(NULL) );

    printf("Before sorting\n");
    for(i=0; i<6; i++){ 
        list[i].price = rand()%10;
        list[i].id = i; 
        printf ("Order id = %d Price = %d \n",list[i].id, list[i].price);           
    }
    printf("AFTER sorting\n");
    int n;
    qsort (list, 6, sizeof(order), compare);
    for (n=0; n<6; n++)
         printf ("Order id = %d Price = %d \n",list[n].id, list[n].price);          
    return 0;
}

надеюсь, что это поможет

katerina dimitris

(все относительно pitsi)

8 голосов
/ 24 мая 2011

Ваш Soc почти наверняка не должен иметь тип double, но в любом случае вот пример того, что должна возвращать функция сравнения:

int compare(const void *p1, const void *p2)
{
    const struct profile *elem1 = p1;    
    const struct profile *elem2 = p2;

   if (elem1->soc < elem2->soc)
      return -1;
   else if (elem1->soc > elem2->soc)
      return 1;
   else
      return 0;
}

Спасибо за указание const void *.

Вот полный пример (в архиве): Сортировка структур с помощью функции C qsort ()

5 голосов
/ 24 мая 2011

Строгая версия компаратора использует два постоянных указателя на пустоту:

int compare(const void *v1, const void *v2)
{
    const struct profile *p1 = v1;
    const struct profile *p2 = v2;
    if (p1->gender > p2->gender)
        return(+1);
    else if (p1->gender < p2->gender)
        return(-1);
    else if (p1->soc > p2->soc)
        return(+1);
    else if (p1->soc < p2->soc)
        return(-1);
    else
        return(0);
}

Сначала сравнивается поле пола, а затем поле соц.Вот как вы обрабатываете любое многочастное сравнение.

3 голосов
/ 11 ноября 2016

Чтобы отсортировать массив, используйте qsort() и передайте функцию сравнения.

Вот тот, который дает правильный результат для всех возможных значений price члена:

typedef struct profile {
    char gender[1];
    double soc;
    int price;
    ...
} PROFILE;

int compare_price(const void *a, const void *b) {
    const PROFILE *oa = a;
    const PROFILE *ob = b;

    return (oa->price > ob->price) - (oa->price < ob->price);
}

int compare_soc(const void *a, const void *b) {
    const PROFILE *oa = a;
    const PROFILE *ob = b;

    return (oa->soc > ob->soc) - (oa->soc < ob->soc);
}

Примечания:

  • простое вычитание значений дает неверные результаты, если разница не соответствует типу int. Например, -2 и INT_MAX нельзя правильно сравнить с методом вычитания. Это также не будет работать для значений с плавающей запятой.

  • вышеуказанный метод может использоваться для всех сопоставимых типов, включая double, за исключением NaN.

Если вы хотите обработать NaN, вот как сгруппировать их в конце:

#include <math.h>

int compare_soc_nan_at_the_end(const void *a, const void *b) {
    const PROFILE *oa = a;
    const PROFILE *ob = b;

    if (isnan(oa->soc)) {
        return isnan(ob->soc) ? 0 : 1;
    } else
    if (isnan(ob->soc)) {
        return -1;
    } else {
        return (oa->soc > ob->soc) - (oa->soc < ob->soc);
    }
}
...