Richard Trinh
Richard Trinh

Reputation: 439

C - Qsort By Count then Alphabetically

I'm trying to run a qsort to sort first by number then by alphabetical order. The array words is:

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

Struct is:

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

My compare function so far is:

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

And my qsort function is:

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

but I don't know how to sort it by alphabetical order after I sort it by frequency.

Upvotes: 0

Views: 480

Answers (1)

Rafael
Rafael

Reputation: 7746

Richard, note a few things here:

  1. I do not cast void pointers when assigning to non-void pointers
  2. I do not use typedef for the sake of it
  3. To get the length of an array, I divide the size of the array by the size of the first element in the array
  4. I use char * in struct word
  5. I do not simply subtract frequencies in compare_words. To derive the order, I actually use if, else if, else. Simply subtracting integers could have strange behavior depending on the operands.
  6. I maintain const pointers in my comparison function, to enforce immutability.

Code:

#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;
}

Output:

FOO 8
ACK 2
BAR 2
BAS 2
ZIP 1

Upvotes: 1

Related Questions