Двойное сравнение по qsort в C - PullRequest
0 голосов
/ 07 апреля 2020

Могу я спросить, как работает двойная сортировка?

Я просто хочу сравнить двух человек по количеству голосов (например, 10 ДЖЕЙМС и 8 ДЖЕК) должно выглядеть как 10 ДЖЕЙМС 8 ДЖЕК

я использовал qsort, чтобы сделать это возможным, но если я хочу сортировка людей с одинаковым количеством голосов по альфа-порядку (например, 10 JAMES, 8 JACK, 10 ALEXA) должна выглядеть так: 10 ALEXA 10 JAMES 8 JACK

мои функции сравнения выглядят так:

int compare(const void* p1, const void* p2){
           return ( ((const struct student*) p2)->votes - ((const struct student*) p1)->votes );
           int value = (((const struct student*)p2)->name - ((const struct student*)p1)->name);
           if(value==0)
           {
                return stcrmp(((const struct student*) p1)->name - ((const struct student*) p2)->name);
           }

}

и qsort там

qsort ((void*) databaza, size, sizeof(struct student), compare);

Но это не работает, кто-нибудь может объяснить почему? Большое спасибо!

1 Ответ

2 голосов
/ 07 апреля 2020

Вот вы.

int compare( const void *p1, const void *p2 )
{
    const struct student *left  = p1;
    const struct student *right = p2;

    int result = ( right->votes < left->votes ) - ( left->votes < right->votes );

    return result == 0 ? strcmp( left->name, right->name ) : result;
}

Вот демонстрационная программа.

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

#define NAME_SIZE   20
struct student
{
    unsigned int votes;
    char name[NAME_SIZE];
};

int compare( const void *p1, const void *p2 )
{
    const struct student *left  = p1;
    const struct student *right = p2;

    int result = ( right->votes < left->votes ) - ( left->votes < right->votes );

    return result == 0 ? strcmp( left->name, right->name ) : result;
}

int main(void) 
{
    struct student students[] =
    {
        { 10, "JAMES" },
        {  8, "JACK" }, 
        { 10,  "ALEXA" }
    };

    const size_t N = sizeof( students ) / sizeof( *students );

    qsort( students, N, sizeof( struct student ), compare );

    for ( size_t i = 0; i < N; i++ )
    {
        printf( "%2u, %s\n", students[i].votes, students[i].name );
    }
    putchar( '\n' );

    return 0;
}

Выход программы:

 8, JACK
10, ALEXA
10, JAMES

Что касается функции сравнения

int compare(const void* p1, const void* p2){
           return ( ((const struct student*) p2)->votes - ((const struct student*) p1)->votes );
           int value = (((const struct student*)p2)->name - ((const struct student*)p1)->name);
           if(value==0)
           {
                return stcrmp(((const struct student*) p1)->name - ((const struct student*) p2)->name);
           }

}

тогда в его начале есть оператор return. Таким образом, код после оператора return не будет выполнен.

Этот оператор

int value = (((const struct student*)p2)->name - ((const struct student*)p1)->name);

имеет неопределенное поведение, поскольку существует различие между двумя указателями, которые не указывают на элементы одного и того же массива.

Этот вызов

stcrmp(((const struct student*) p1)->name - ((const struct student*) p2)->name);

doea не имеет смысла и не будет компилироваться, потому что функция strcmp ожидает два аргумента типа char *.

...