0

I have a temp2.dat file that looks like this:

0.060493 1 0.5 1
1.596961 0 0.1 2
0.87758  1 0.3 1.5
0.165453 1 0   3
0.07085  1 0.3 4
0.125379 1 0.2 3
0.454202 1 0.2 2
0.373227 1 0.3 1
0.131486 1 0.3 3
0.867477 0 0.5 4
0.122609 0 0.8 9

Now I want to write the function in C to sort these 4 columns in an increasing order but only based on the values of the first column. I tried modifying the following code but it failed:

struct data_t
{
    double x;
    int y;
    double z;
    double k;
};

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;
    if(m->x == n->x)
        return m->y > n->y;
        return m->z > n->z;
        return m->k > n->k;
    return m->x > n->x;
}

Could someone please help me do this? The expected result should look like this:

0.060493 1 0.5 1
0.07085  1 0.3 4
0.122609 0 0.8 9
0.125379 1 0.2 3
0.131486 1 0.3 3
................
0.87758  1 0.3 1.5
1.596961 0 0.1 2
3
  • Your compare function is bizarre. Please look up some examples of, presumably, qsort, and be wary of testing floating point values for equality. Please post the Minimal, Complete, and Verifiable example that shows the problem. Commented Mar 8, 2018 at 21:52
  • 2
    return m->k > n->k; and return m->x > n->x; are useless, they will never be reached, you can only return 1 object from a function. And I highly recommend adding some brackets { ... } to your if statement to make it clear with you want, or at least changing the indentation. What you have now is misleading. Commented Mar 8, 2018 at 21:54
  • 1
    @yano: thank you so much. I would note this point next time. Commented Mar 9, 2018 at 1:15

2 Answers 2

1

Try this compare function

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;

    if(m->x != n->x)
        return (m->x > n->x) - (m->x < n->x);

    if(m->y != n->y)
        return m->y - n->y;

    if(m->z != n->z)
        return (m->z > n->z) - (m->z < n->z);

    if(m->k != n->k)
        return (m->k > n->k) - (m->x < n->k);

    return 0;
}

This will compare the first column x. If x is the same in the two elements, it moves to the second column y. If the second column is the same, it moves to the third column and so on.

We want the difference between the two values. Example, m->y - n->y. The compare function should return an integer value 0, negative, or positive.

When comparing double values, we cannot use m->x - n->x, because the return value for compare is int. We use a comparison function instead.

Testing

struct data_t
{
    double x;
    int y;
    double z;
    double k;
};

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;

    if(m->x != n->x)
        return (m->x > n->x) ? 1 : -1;

    if(m->y != n->y)
        return m->y - n->y;

    if(m->z != n->z)
        return (m->z > n->z) ? 1 : -1;

    if(m->k != n->k)
        return (m->k > n->k) ? 1 : -1;

    return 0;
}

int main(void)
{
    struct data_t data[] = 
    { 
        { 0.060493, 3, 0.4, 7 },//1st column is the same
        { 0.060493, 2, 0.5, 8 },
        { 0.060493, 1, 0.6, 9 },

        { 0.060493, 3, 0.3, 4 },//1st & 2nd columns are the same
        { 0.060493, 3, 0.2, 5 },
        { 0.060493, 3, 0.1, 6 },

        { 0.060493, 1, 0.5, 3 },//1st & 2nd & 3rd columns are the same
        { 0.060493, 1, 0.5, 2 },
        { 0.060493, 1, 0.5, 1 },

        { 0.122609, 0, 0.8, 9 },
        { 0.125379, 1, 0.2, 3 },
        { 0.131486, 1, 0.3, 3 },
    };

    int count = sizeof(data) / sizeof(data[0]);
    qsort(data, count, sizeof(data[0]), compare);

    for(int i = 0; i < count; i++)
    {
        printf("%.6f %d %.1f %.0f\n",
            data[i].x, data[i].y, data[i].z, data[i].k);
    }

    return 0;
}

output:

0.060493 1 0.5 1
0.060493 1 0.5 2
0.060493 1 0.5 3
0.060493 1 0.6 9
0.060493 2 0.5 8
0.060493 3 0.1 6
0.060493 3 0.2 5
0.060493 3 0.3 4
0.060493 3 0.4 7
0.122609 0 0.8 9
0.125379 1 0.2 3
0.131486 1 0.3 3
Sign up to request clarification or add additional context in comments.

2 Comments

Many thanks for your great help! If the first column is not the same, each time your compare() function would automatically shift the elements in the same row but in remaining columns, down 1 row?
I printed the output, it looks right. It's sorting the 1st column, then 2nd column etc.
0

First off, in C if you want more than one statement inside any block, you have to surround it with { and }. So your last 3 return statements would never be reached (the indentation does not matter for the compiler, only for humans).

Second, when you call return, your code does not come back. So you could use nested ifs to compare the values in case they are the same in some of the columns. Something like:

int compare(const void *a, const void *b)
{
    const struct data_t *m = a;
    const struct data_t *n = b;
    if(m->x == n->x) {
        if (m->y == n->y) {
            if (m->z == n->z) {
                return m->k > n->k;
            }
            return m->z > n->z;
        }
        return m->y > n->y;
    }
    return m->x > n->x;
}

4 Comments

I'm assuming the correct logic is to subtract, not to compare
Ah, I missed the qsort tag. Just inferred what the compare function did from what OP wrote.
@BrunoEly: Thank you so much! Let me try your code to see if it actually does what I want to. Did you try it with the given sample dataset above?
Note: This compare() is sufficient to use with qsort() as that expects negative return values too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.