C - Qsort по количеству, затем по алфавиту

Я пытаюсь запустить qsort для сортировки сначала по номеру, а затем по алфавиту. Слова массива:

COPY 3
CLOSER 2
TAUGHT 2
AW 2
LOOKS 2
SHAD 3
HA 3

Структура:

typedef  struct {
    char word[101];
    int freq;
} Word;

Моя функция сравнения до сих пор:

int compare(const void *c1, const void *c2){
    Word *a1 = (Word *)c1;
    Word *b1 = (Word *)c2;
    return (b1->freq - a1->freq);
}

И моя функция qsort:

qsort(words, count, sizeof(Word), compare);

но я не знаю, как сортировать его по алфавиту после сортировки по частоте.


person Richard Trinh    schedule 22.09.2018    source источник
comment
Ричард, твоя функция сравнения должна быть более сложной. Сравните частоту и строки...   -  person Rafael    schedule 22.09.2018
comment
Если частота слов одинакова, то вам нужно сравнить слова. if (b1->freq != b2->freq) return (b1->freq - b2->freq) else return strcmp(b1->word, b2->word);.   -  person Jonathan Leffler    schedule 22.09.2018
comment
@JonathanLeffler Почему бы не написать ответы как ответы? однако вы перепутали имена некоторых переменных.   -  person Swordfish    schedule 22.09.2018
comment
Да, я перепутал имена, потому что имена в вопросе были несовместимы. Текста недостаточно, чтобы его можно было преобразовать в ответ, даже с исправленными именами. (Или, если хотите, я ленив и не вижу достаточной пользы от предоставления ответа, не в последнюю очередь потому, что мне придется написать больше, чтобы сделать его ответом, с которым я могу жить.)   -  person Jonathan Leffler    schedule 22.09.2018
comment
больше для меня, я думаю :)   -  person Rafael    schedule 22.09.2018


Ответы (1)


Ричард, обратите внимание на несколько вещей:

  1. Я не использую пустые указатели при назначении непустым указателям
  2. Я не использую typedef ради этого
  3. Чтобы получить длину массива, я делю размер массива на размер первого элемента массива.
  4. Я использую char * в struct word
  5. Я не просто вычитаю частоты в compare_words. Чтобы вывести порядок, я фактически использую if, else if, else. Простое вычитание целых чисел может иметь странное поведение в зависимости от операндов.
  6. Я поддерживаю указатели const в своей функции сравнения, чтобы обеспечить неизменность.

Код:

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

struct word {
    char *str;
    int freq;
};

int compare_words(const void *a, const void *b)
{
    const struct word *w1 = a;
    const struct word *w2 = b;

    int order;

    if (w2->freq > w1->freq) {
        order = 1;
    } else if (w2->freq < w1->freq) {
        order = -1;
    } else {
        order = strcmp(w1->str, w2->str);
    }

    return order;
}

int main(int argc, char const *argv[])
{
    struct word mywords[] = {
        { "BAR", 2 },
        { "BAS", 2 },
        { "ACK", 2 },
        { "FOO", 8 },
        { "ZIP", 1 }
    };

    int len = sizeof(mywords) / sizeof(mywords[0]);

    qsort(mywords, len, sizeof(mywords[0]), compare_words);

    int i;
    for (i = 0; i < len; i++) {
        struct word w = mywords[i];
        printf("%s\t%d\n", w.str, w.freq);
    }

    return 0;
}

Выход:

FOO 8
ACK 2
BAR 2
BAS 2
ZIP 1
person Rafael    schedule 22.09.2018