[comp.lang.c] Help with qsort

ilan343@violet.berkeley.edu (11/21/89)

I am trying to use the standard C qsort routine to rank an array of
floats.  I don't want to disturb the original data, so I tried the
following:

a) Copy the addresses of each array element into an array of pointers.
b) Invoke qsort on the array of pointers. 
c) Print ranks by subtracting pointers

Well, it didn't work.
If you are in "good samaritan" mode you can have look at the code in the
next page, and tell me where I went wrong.

Thank for your help,

     Geraldo Veiga


This is the output produced by the code below:

Before sort	  	After sort
  Data     Rank 	  Data     Rank
0 0.427055 0  		0 0.427055 0 
1 0.230254 1  		1 0.230254 1 
2 0.020845 2  		2 0.020845 5 
3 0.052413 3  		3 0.052413 6 
4 0.052413 4  		4 0.052413 4 
5 0.122733 5  		5 0.122733 3 
6 0.094287 6  		6 0.094287 2 


They should be in descending order. The exact same behavior was
replicated in every compiler I tried (Turbo-C, BSD 4.3, pcc (on a
3B2)), so I can only assume I messed up somewhere.

Here is the code:

/* Test qsort routine */
#include <stdio.h>
main ()
{
    float           data[7], *rank[7];
    int             n, i, compare ();
    data[0] = 0.427055; data[1] = 0.230254; data[2] = 0.020845;
    data[3] = 0.052413; data[4] = 0.052413; data[5] = 0.122733;
    data[6] = 0.094287;

/* Collect addresses */
    for (i = 0; i < 7; i++)
	rank[i] = &data[i];
/* Sort */
    printf ("Before sort\n");
    for (i = 0; i < 7; ++i)
	printf ("%d %f %d \n", i, data[i], rank[i] - data);
    (void) qsort ((void *) rank, 7, sizeof (float *), compare);
    printf ("After sort\n");
    for (i = 0; i < 7; ++i)
	printf ("%d %f %d \n", i, data[i], rank[i] - data);
}
int
compare (p1, p2)
    float         **p1, **p2;
{
    if (**p1 < **p2)
	return(1);
    else if (**p1 == **p2)
	return(0);
    else
	return(-1);
}

aic@mentor.cc.purdue.edu (George A. Basar) (11/21/89)

In article <1989Nov20.213702.20821@agate.berkeley.edu>, ilan343@violet.berkeley.edu writes:
> I am trying to use the standard C qsort routine to rank an array of
> floats.  I don't want to disturb the original data, so I tried the
> following:
> 
> a) Copy the addresses of each array element into an array of pointers.
> b) Invoke qsort on the array of pointers. 
> c) Print ranks by subtracting pointers

  No need for step c, the entries in rank are pointers which had been sorted
  based upon the values in data.

> 	printf ("%d %f %d \n", i, data[i], rank[i] - data);

  This should be
 	printf ("%d %f %f \n", i, data[i], *rank[i]);

  Since your compare checks the value in data, qsort swapped pointers in 
rank.  Printing out the values referenced by the elements in rank in
order, as above, gives a sorted list.


* George A. Basar                              (317)742-8799 (home)
* aic@mentor.cc.purdue.edu                     BASAR@PURCCVM.BITNET    
| General Consultant                   	       (317)494-1787 (work)
| Purdue University Computing Center
Disclaimer: My opinions are just that, mine.