I've got this code, but it isn't working as should. I need to virtually sort 'val' array in descending order, and store the order in 'order' array.
#include <stdio.h>
#define NUM_J_DIRS 4
#define FRAC_LEFT 0
#define FRAC_RIGHT 1
#define FRAC_FORWARD 2
#define FRAC_BACK 3
#define FIRST 0
#define SECOND 1
#define THIRD 2
#define FOURTH 3
struct iv
{
int index;
float value;
};
struct Fractions
{
int order[NUM_J_DIRS]; //this is where we store order of 'val'
float val[NUM_J_DIRS]; //once declared, this don't change
int enabled[NUM_J_DIRS]; //once declared, this don't change
};
int main ()
{
struct Fractions fractions;
struct iv iv[NUM_J_DIRS];
fractions.val[FRAC_LEFT] = 0.1;
fractions.val[FRAC_RIGHT] = 1.0;
fractions.val[FRAC_FORWARD] = 1.0;
fractions.val[FRAC_BACK] = 0.5;
// populate iv from val
for (int i = 0; i < NUM_J_DIRS; i )
{
iv[i].index = i;
iv[i].value = fractions.val[i];
}
// sort kv by value
for (int i = 0; i < NUM_J_DIRS; i )
{
for (int j = i 1; j < NUM_J_DIRS; j )
{
if (iv[i].value < iv[j].value)
{
struct iv temp = iv[i];
iv[i] = iv[j];
iv[j] = temp;
}
}
}
// set order
for (int i = 0; i < NUM_J_DIRS; i )
{
fractions.order[iv[i].index] = i;
}
printf("order = %i, dir: %i, the value was: %f\n",
FIRST, fractions.order[FIRST], fractions.val[fractions.order[FIRST]]);
printf("order = %i, dir: %i, the value was: %f\n",
SECOND, fractions.order[SECOND], fractions.val[fractions.order[SECOND]]);
printf("order = %i, dir: %i, the value was: %f\n",
THIRD, fractions.order[THIRD], fractions.val[fractions.order[THIRD]]);
printf("order = %i, dir: %i, the value was: %f\n",
FOURTH, fractions.order[FOURTH], fractions.val[fractions.order[FOURTH]]);
return 0;
}
outputs:
order = 0, dir: 3, the value was: 0.500000
order = 1, dir: 0, the value was: 0.100000
order = 2, dir: 1, the value was: 1.000000
order = 3, dir: 2, the value was: 1.000000
But should output:
order = 0, dir: 1, the value was: 1.000000
order = 1, dir: 2, the value was: 1.000000
order = 2, dir: 3, the value was: 0.500000
order = 3, dir: 0, the value was: 0.100000
The order between dir 1 and dir 2 is interchangeable since they have the same value. The order of direction of the same values is not important.
Code above should work imo, but doesn't. I have spent countless time figuring out why not.
CodePudding user response:
After sorting iv
, the elements are in descending order by value, and each one carries a corresponding index into the fractions.val
array. So iv[0].index
gives the index of the greatest element, iv[1].index
gives the index of the next greatest, etc. Therefore, when you read that out, you want the first element of order
to take the index
from the first element of iv
, the second from the second, and so on. But that's not what this says:
// set order for (int i = 0; i < NUM_J_DIRS; i ) { fractions.order[iv[i].index] = i; }
You have reversed the sense of i
and iv[i].index
. What you actually want is
for (int i = 0; i < NUM_J_DIRS; i )
{
fractions.order[i] = iv[i].index;
}
After I make that change, your program's output prints the values in descending order for me.
CodePudding user response:
Declare this as your compare function:
int compareFunction(const void *p1, const void *p2, void *arg) {
struct Fractions* f = (struct Fractions*)arg;
int index1 = *(int*)p1;
int index2 = *(int*)p2;
if (f->val[index1] < f->val[index2]) {
return 1;
}
if (f->val[index1] > f->val[index2]) {
return -1;
}
return 0;
}
Then to sort the "order" array based on the existing order of the "val" array:
for (int i = 0; i < NUM_J_DIRS; i ) {
fractions.order[i] = i;
}
qsort_r(fractions.order, NUM_J_DIRS, sizeof(int), &fractions);
You get qsort_r
by adding a #include <stdlib.h>
to the top of your source file.