Xref: utzoo comp.lang.c:26764 comp.unix.xenix:10513 Path: utzoo!attcan!lsuc!sq!msb From: msb@sq.sq.com (Mark Brader) Newsgroups: comp.lang.c,comp.unix.xenix Subject: Re: qsort() - HELP Message-ID: <1990Feb20.190143.3682@sq.sq.com> Date: 20 Feb 90 19:01:43 GMT References: <5916@ozdaltx.UUCP> Reply-To: msb@sq.com (Mark Brader) Followup-To: comp.lang.c Organization: SoftQuad Inc., Toronto Lines: 74 > > void qsort(base, nel, width, compar) > > char *base > > unsigned nel, width > > int (*compar)() > Yep, 'base' is supposed to the be the (char *)base of the array you > intend to sort. 'nel' is the number of elements to be sorted and > 'width' the sizeof(element_to_sort). > 'compar' is a pointer to int function that must behave like strcmp... > If is strings you want to sort might just call (I think): > qsort(array,nel,width,strcmp). This is correct as far as it goes but there is a tricky point that must be emphasized. The compar function that you provide will be called with arguments that *point to* the elements of the array. (It works this way because the array elements might have a type that cannot be passed efficiently, or at all, as a function argument.) Therefore, if you have a 2-dimensional array of chars where each row is used to contain a string, like this: char place[][MAXLEN+1] = {"Portugal", "Canada", "Paraguay", "Japan"}; then you can indeed sort it with #define NUMEL(x) (sizeof x / sizeof *x) int strcmp(); qsort ((char *) place, NUMEL (place), sizeof *place, strcmp); However, if your array itself contains pointers, like this: char *place[] = {"Portugal", "Canada", "Paraguay", "Japan"}; then you must define a function int indstrcmp (sp1, sp2) char *sp1, *sp2; { return strcmp ( * (char **) sp1, * (char **) sp2); } The arguments to indstrcmp() have to be declared as char * rather than char **, and then converted to char **,, because char * is what qsort() is going to pass to indstrcmp(). and invoke qsort using it: qsort ((char *) place, NUMEL (place), sizeof *place, indstrcmp); All of the above is in pre-ANSI style. In ANSI C, void * rather than char * is used as the generic pointer type (but they're represented the same way and passed the same way to functions, so strcmp() will work on void *'s). So the first example becomes: qsort ((void *) place, NUMEL (place), sizeof *place, strcmp); and the second one: int indstrcmp (const void *sp1, const void *sp2) { return strcmp ( * (char **) sp1, * (char **) sp2); } and: qsort ((void *) place, NUMEL (place), sizeof *place, indstrcmp); Followups are directed to comp.lang.c. -- Mark Brader "[This computation] assumed that everything SoftQuad Inc., Toronto would work, a happy state of affairs found utzoo!sq!msb, msb@sq.com only in fiction." -- Tom Clancy This article is in the public domain.