Я не вижу необходимости в динамическом распределении и вызове memcpy для каждого автомобиля, подлежащего сортировке, в этом коде вообще.
Вы создаете слой указателей (последовательность указателей), так почему бы просто не выделить это (что вы и делаете), а затем сохранить там адреса каждого элемента из array
. Затем настройте свой компаратор для адресации того, что вы отправляете: адрес указателя (указатель на указатель) и соответствующим образом настройте разыменования.
Добавьте к этому, что вы должны передавать fl.cars
в qsort, а не &fl
, и аргумент sizeof в нем также неверен.
Наконец, я не знаю, хотели ли вы намеренно использовать логический стек больше, чем в вашем компараторе, но это именно то, что у вас получилось.
Пример
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
PETROL,
DIESEL,
ELECTRIC,
LPG,
BIOFUEL,
OTHER
} fuel_t;
typedef struct car_tag {
unsigned cc;
fuel_t fueltype;
} car_t;
typedef struct fleet_tag {
car_t ** cars;
size_t n_cars;
} fleet_t;
int car_comp(const void * vp1, const void * vp2)
{
const car_t * const *pc1 = vp1;
const car_t * const *pc2 = vp2;
if ((*pc1)->cc > (*pc2)->cc)
return -1;
if ((*pc1)->cc < (*pc2)->cc)
return 1;
return 0;
}
int main() {
car_t array[] = {
{ 600, PETROL},
{1200, PETROL},
{1000, PETROL},
{1600, DIESEL},
{1000, ELECTRIC}
};
int size = sizeof(array) / sizeof(array[0]);
fleet_t fl;
fl.n_cars = size;
fl.cars = malloc(size * sizeof *fl.cars);
for (int i = 0; i < size; i++)
fl.cars[i] = array+i;
// how to sort cars by cc
qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);
for (int i=0; i<size; ++i)
printf("%d (%u, %d)\n", i+1, fl.cars[i]->cc, fl.cars[i]->fueltype);
free(fl.cars);
return EXIT_SUCCESS;
}
Вывод
1 (1600, 1)
2 (1200, 0)
3 (1000, 0)
4 (1000, 2)
5 (600, 0)
qsort
работает, передавая ему последовательность «вещей», длину, указывающую, сколько «вещей» существует, размер, указывающий, насколько велика каждая «вещь» в последовательности, и, наконец, функцию сравнения, которая будет передан адрес каждой "вещи" во время выполнения алгоритма.
В вашем случае ваши "вещи" - это указатели на car_t
структуры. Фактически,
- Ваша последовательность представляет собой динамический массив указателей; ваша "вещь" - это указатель на
car_t
.
- Ваша длина
size
.
- Ваш размер каждой «вещи» равен размеру указателя.
- Ваш компаратор получит доступ к адресу двух ваших вещей (следовательно, два указателя, так что указатели на указатели) и будет действовать соответственно.
Таким образом, вызов становится:
qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);
Наконец, обратите внимание, что исходный array
остается неизменным. Сорт изменил только ваш указатель. Вероятно, это было желательно, и я надеюсь, вы понимаете, как это работает.
person
WhozCraig
schedule
07.07.2018