anon
anon

Reputation:

Sort strings by length in C

I am aware there are other questions like this, but they don't work hence this question.

I am trying to sort an array of strings by their length (descending) and I have been trying to use qsort as that is what is suggested, but every solution doesn't work for me. I believe the reason is because in all the examples of using qsort they have an array as such;

char *arrayOfStrings...

but my array starts as such

char **arrayOfStrings;

this is because I am dynamically adding the strings to the array but either way I can't seem to get qsort to sort the strings in order.

Code for reference:

int numberOfStrings = 0;
int numberOfStringsTwo = 0;
int totalNoStrings = 0;

scanf("%d", &numberOfStrings);
totalNoStrings += numberOfStrings;
char **inputArray = malloc(numberOfStrings * sizeof(char*));
for (int i = 0; i < numberOfStrings; i++) {
    char input[100];
    scanf("%s", input);
    inputArray[i] = (char *)malloc((strlen(input) + 1));
    strcpy(inputArray[i], input);
}

scanf("%d", &numberOfStringsTwo);
totalNoStrings += numberOfStringsTwo;
inputArray = realloc(inputArray, totalNoStrings * sizeof(char*));
for (int j = numberOfStrings; j < totalNoStrings; j++) {
    char input[100];
    scanf("%s", input);
    inputArray[j] = (char *)malloc((strlen(input) + 1));
    strcpy(inputArray[j], input);
}

qsort(inputArray, totalNoStrings, sizeof(char *), compareStrings);

size_t z;
for (z = 0; z < totalNoStrings; z++) {
    printf("%s\n", inputArray[z]);
}

and

int compareStrings(const void *one, const void *two) {
    const char *iOne = (const char*)one;
    const char *iTwo = (const char*)two;
    return strcmp(iOne, iTwo);
}

Upvotes: 0

Views: 1840

Answers (1)

chqrlie
chqrlie

Reputation: 144800

The compareStringLens() function is incorrect: it receives pointers to the string pointers, you miss one level of indirection in your code, calling strlen on the address of a pointer has undefined behavior.

Here is a comparison function that sorts strings in decreasing length and lexicographical order for the each length:

int compareStrings(const void *one, const void *two) {
    const char *iOne = *(const char * const *)one;
    const char *iTwo = *(const char * const *)two;
    size_t len1 = strlen(iOne);
    size_t len2 = strlen(iTwo);
    if (len1 > len2)
        return -1;
    if (len2 > len1)
        return +1;
    return strcmp(iOne, iTwo);
}

Upvotes: 4

Related Questions