qsort массив структур в порядке убывания

У меня есть структура, которая выглядит так

typedef struct id_score{
   int id;
   int score;
} pair;

Массив размером 50 содержит указатели на эти пары.

pair* array[50]

Моя функция компаратора выглядит так

int struct_cmp(const void *a, const void* b) {
    pair* ia = (pair*)a;
    pair* ib = (pair*)b;
    printf("ia's score: %d ib's score: %d??? \n", ia->score, ib->score);
    return ib->score - ia->score;
}

Моя функция qsort здесь

size_t arr_len = sizeof(array) / sizeof(pair);
qsort(array, arr_len, sizeof(pair), struct_cmp);

Теперь моя проблема заключается в том, что в функции struct_cmp мой printf показывает, что значения, которые, по моему мнению, должны быть счетчиком в каждой структуре в массиве, все интерпретируются как 0, таким образом, массив вообще не сортируется. Вне функции, когда я печатаю через массив, у структуры есть оценки, которые она должна иметь.

Какие-либо предложения?? спасибо!


person namesake22    schedule 23.02.2017    source источник
comment
Разве a не является указателем на элемент? Элементы массива имеют тип pair* Итак, pair** ia = (pair**)a;?   -  person chux - Reinstate Monica    schedule 24.02.2017
comment
Вы сортируете массив указателей; вашему компаратору передается пара указателей на указатели, а не указатели одного уровня. Если бы вы сортировали массив int, вашей функции было бы передано два int *. Поскольку вы сортируете массив pair *, вашей функции передаются два pair **.   -  person Jonathan Leffler    schedule 24.02.2017
comment
Примечание. Когда вы вызываете qsort(), учитывайте qsort(array, arr_len, sizeof *array, struct_cmp); Это легче кодировать, просматривать и поддерживать, чем qsort(..., ..., sizeof(pair), ...)   -  person chux - Reinstate Monica    schedule 24.02.2017


Ответы (1)


Для одного

size_t arr_len = sizeof(array) / sizeof(pair);

Вышеприведенное неверно, так как ваш массив содержит указатели pair, а не pairs. Если сделать это немного более идиоматически и с меньшим количеством повторений, то получится:

size_t arr_len = sizeof(array) / sizeof(array[0]);

Следует также отметить, что ваша функция сравнения преобразуется в неправильный тип указателя, поэтому поведение вашей программы не определено.

Помните, что функция обратного вызова будет получать указатели на элементы массива, поэтому, если массив содержит указатели, она должна преобразовать аргументы в указатели в указатели:

int struct_cmp(const void *a, const void* b) {
    pair* const * ia = (pair* const *)a;
    pair* const * ib = (pair* const *)b;
    printf("ia's score: %d ib's score: %d??? \n", ia->score, ib->score);
    return (*ib)->score - (*ia)->score;
}

В отличие от вашей оригинальной функции, я также стремился сделать ее постоянной. Обратный вызов сравнения принимает указатель на const, поэтому преобразованный указатель также должен быть константным (при этом const применяется к типу элемента, который равен pair*).


Как указал chux, чтобы избежать переполнения при вычитании, основным улучшением будет возврат следующего:

return ((*ib)->score > (*ia)->score) - ((*ib)->score < (*ia)->score);

Что также имеет приятное свойство всегда возвращать -1, 0 или 1 вместо произвольных чисел.

person StoryTeller - Unslander Monica    schedule 23.02.2017
comment
Чтобы избежать переполнения при вычитании, можно использовать идиому (a>b) - (a< b). - person chux - Reinstate Monica; 24.02.2017
comment
@chux - Добавлено. И спасибо, что сообщили мне о существовании идиом :) - person StoryTeller - Unslander Monica; 24.02.2017
comment
Я так понимаю, что компиляторы тоже ищут его, так что разумный шанс выдать компактный код. Тем не менее, для меня это затыкает функциональную дыру по сравнению с return a-b. Немного о const правильном. LSNED - person chux - Reinstate Monica; 24.02.2017
comment
Я предполагаю, что моя самая большая ошибка произошла от return ib->score - ia->score; } ?? - person namesake22; 24.02.2017
comment
@ namesake22 Самыми большими проблемами, IMO, были те, которые вряд ли сразу сломают вашу программу. Например, проблема размера массива. Неправильное преобразование указателя раздражало бы вас, пока вы не решили эту проблему. - person StoryTeller - Unslander Monica; 24.02.2017