tags:

views:

164

answers:

3

Here is my code:

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

int cmp(const void *a, const void *b) {
    const char **ia = (const char **)a;
    const char **ib = (const char **)b;
    return strcmp(*ia, *ib);
}

void print_array(char **array, size_t len) {
    size_t i;
    for(i=0; i<len; i++) {
        printf("%s, ", array[i]);
    }
    putchar('\n');
}

int main(int argc, char *argv[]) {

        char *strings[] = { "z1.doc", "z100.doc",  "z2.doc", "z3.doc", "z20.doc"};
        size_t strings_len = sizeof(strings) / sizeof(char *);
        print_array(strings, strings_len);
        qsort(strings, strings_len, sizeof(char *), cmp);
        print_array(strings, strings_len);

        system("PAUSE");
        return 1;
}

the actual output is

z1.doc, z100.doc, z2.doc, z20.doc, z3.doc

and I want it to be

z1.doc, z2.doc, z3.doc, z20.doc, z100.doc

What am doing wrong?

+4  A: 

The actual output is correct, the string "z100.doc" is less than "z2.doc". The strcmp compares character by character and when it gets to the '1' that is less than '2' and it stops there, so z100 < z2.

If you name the files z001.doc, z002.doc, z003.doc, z020.doc, z100.doc it will sort the way you want.

progrmr
It's not that the output is incorrect, just undesirable.
D.Shawley
-1 Renaming the files is not the answer to this question. The OP wants to do work for the user, not make the user do (unnecessary) work to get his/her files displayed properly. Anyone who upvotes this doesn't understand the concept of "interface usability" - _no one_ other than us programmers expects lists to be sorted in the order that the standard `strcmp()` sorts in.
Chris Lutz
I agree but the question was how to correctly sort strings.
progrmr
The question was "Why is the sorted output I get not the sorted output I expect, and how can I fix that?"
Chris Lutz
+3  A: 

Change your comparator to say:

return (atoi(*ib + 1) - atoi(*ia + 1));
Dan
almost, it sort but in reserve... thank you
netdur
that will only work if there is only 1 number in the filename and all the characters are identical. it won't work properly for "z1aa.doc", "z1zz.doc", "z1bb.doc". it wont' work for "z10_10.doc" and "z10_5.doc", etc.
progrmr
return (atoi(*ia + 1) - atoi(*ib + 1));
netdur
+1  A: 

You want a natural sorting algorithm as opposed to the ASCIIbetical sorting algorithm provided by default. See Jeff's blog entry for a long rant about this, and some nice links to implementations of this natural algorithm. Just as a warning, the correct implementation (as opposed to the hacky answer you've accepted) is quite complicated, so don't try to implement it yourself, take someone else's (hopefully public domain or liberally licensed) implementation and use that instead.

Chris Lutz