Почему этот код, использующий функцию qsort, не работает в C?
Сортирующая часть:
order = (struct order_s **) calloc(pm->len - q, sizeof(struct order_s*));
for (i = 0; i < window_pos; ++i) {
order[i] = (struct order_s *) malloc(sizeof(struct order_s));
order[i]->pos = i;
order[i]->good = good[i];
}
for (i = window_pos + q; i < pm->len; ++i)
{
order[i-q] = (struct order_s *) malloc(sizeof(struct order_s));
order[i-q]->pos = i;
order[i-q]->good = good[i];
}
qsort(order, pm->len - q, sizeof(struct order_s *), compare);
Функция сравнения:
int compare (const void * a, const void * b)
{
if ((((const struct order_s *)a)->good - ((const struct order_s *)b)->good) > 0)
return 1;
else
return -1;
}
Структура:
struct order_s {
int pos;
double good;
};
Ценности:
(gdb) p pm->len
$35 = 20
(gdb) p window_pos
$36 = 1
(gdb) p q
$37 = 5
Перед qsort():
(gdb) p *order[0]
$2 = {pos = 0, good = 1.3238653863672125}
(gdb) p *order[1]
$3 = {pos = 6, good = 0.96180564211148134}
(gdb) p *order[2]
$4 = {pos = 7, good = 1.0684181637005736}
(gdb) p *order[3]
$5 = {pos = 8, good = 0.92113662370476379}
После qsort():
(gdb) n
(gdb) p *order[0]
$6 = {pos = 0, good = 1.3238653863672125}
(gdb) p *order[1]
$7 = {pos = 6, good = 0.96180564211148134}
(gdb) p *order[2]
$8 = {pos = 7, good = 1.0684181637005736}
(gdb) p *order[3]
$9 = {pos = 8, good = 0.92113662370476379}
После qsort
функция, массив структуры не отсортирован правильно и позже выдает ошибку сегмента.
1 ответ
compare()
Аргументы функции являются указателями на элементы массива. В этом случае элементы массива struct order*
, что означает аргументы compare()
являются struct order**
не struct order*
,
Изменить на:
int compare (const void * a, const void * b)
{
const struct order_s** aa = a;
const struct order_s** bb = b;
/* Can two 'order_s' instances never be equal ? */
if ( (*aa)->good - (*bb)->good) > 0) return 1;
else return -1;
}
Из стандартного раздела C99 7.20.5.2 Функция qsort:
Содержимое массива сортируется в порядке возрастания в соответствии с функцией сравнения, на которую указывает сравнение, которая вызывается с двумя аргументами, указывающими на сравниваемые объекты. Функция должна возвращать целое число меньше, равно или больше нуля, если первый аргумент считается соответственно меньше, равен или больше второго.