-1

I am trying to sort the array of structure which takes 20 inputs and sort them using C's standard library function qsort() but not getting proper sorted output.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma pack(1)
struct player{
    char name[4];
    short age;
    short match;
    float average;
};
#pragma pack()
int comp(const void *p,const void *q){
    float *a=(float*)p;
    float *b=(float*)q;
    if(*b-*a>0)return 1;
    if(*b-*a<0)return 1;
    if(*b-*a==0)return 0;
}
int main(){
    struct player list[20];
    for(int i=0;i<20;i++){
        scanf("%s",list[i].name);       
        scanf("%hu %hu %f",&list[i].age,&list[i].match,&list[i].average);
    }
    qsort((void*)list,20,sizeof(struct player),comp);
    for(int i=0;i<20;i++){
        printf("%2.2f %10s %4hu %4hu\n",list[i].average,list[i].name,list[i].age,list[i].match);
    }
    return 0;
}

one may use the following test case to check there output.

aaa 21  22  34
qsd 33  21  44
qqq 1   2   55.2
www 33  22  12.2
ewe 22  11  13.3
qaz 22  33  12.33
aaa 21  22  34
qsd 33  21  44
qqq 1   2   54.2
www 33  22  12.2
eee 22  11  16.3
qaz 22  33  18.33
aaa 21  22  34
qsd 33  21  49
qqq 1   2   52.2
www 33  22  12.2
eee 22  11  10.3
qaz 22  33  11.33
eee 22  11  14.3
qaz 22  33  11.33
3
  • Why your comp is trying to interpret the passed pointers as float*? Commented Jul 22, 2019 at 17:27
  • 1
    const void *p does not point to float but to the whole struct element of the array. So the comp function can first cast the arguments to the correct type, and then compare members of the structs. Commented Jul 22, 2019 at 17:27
  • your "a>b" and "a<b" cases both return the same result. Commented Jul 22, 2019 at 17:28

2 Answers 2

2

Use a compare function like this:

int comp(const void *p, const void *q) {
  struct player *p1 = (player*)p;
  struct player *p2 = (player*)q;

  if (p1->average > p2->average) return 1;
  if (p1->average < p2->average) return -1;
  return 0;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Why not replace ifs with return p1->average - p2->average? More concise and is the norm for comparison functions
@JonathanLam because that can overflow. It's typical, but faulty.
Not (only) that. The difference can be less than one, but then it is cast to int
@JonathanLam think twice, that can't be true, a utopia, to say the least... :)
1

Your custom comparison method should look like this:

int comp(const void *p, const void *q) {
  struct player *a = (struct player*)p;
  struct player *b = (struct player*)q;

  if(b->average > a->average)
    return 1;
  else if (b->average < a->average)
    return -1;
  else
    return 0;
}

As @EugeneSh. and @WeatherVane commented, the parameters of that method are pointers to structs - for example the first element of your array will be pointed by p and the second by q at a certain comparison.

So, you first need to cast to a pointer to the struct, and then use its field to perform the actual comparison.

Now the comparison has a logical flaw as @Gereon and I commented: It returns 1 in the less AND in the greater case, which is surely not what you want. Return 1 in one case, and -1, for example, in the other case.

As for the return 0; case, it's good as it is, ensuring a stable sort.

Tip: Do not be tempted to use return p1->average - p2->average, as typically illustrated in the ref's example, since you are dealing with floats, and the least thing you need is a numerical instability, since it can overflow. Moreover, the difference can be less than one, but then it is cast to int.

3 Comments

@WeatherVane we just practiced the paradigm of maieutics, introduced by Socrates 25 centuries ago.. Thanks guys (+EugeneSh.), you helped me improve my answer!
@EugeneSh. well there is the infinity representation, but if the values are very small, their difference might be 0.0 when it is not. Integers don't have that, so best to use a foolproof method all the time.
@WeatherVane No argument here :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.