Home > Net >  Sorting Structures using qsort
Sorting Structures using qsort

Time:04-18

I have to use quicksort to sort the states by percentage of population whose ages are equal or greater than 65 years old.

    for (i = 0; i < n; i  ) {
        qsort(input_file, n, sizeof(int), sort_states);
    }

CodePudding user response:

You have to define a comparison function for your struct:

int state_compare_by_age_65_or_gt(const void *s1, const void *s2)
{
    const struct state *ss1 = s1;
    const struct state *ss2 = s2;
    
    if (ss1->ages_65_or_greater < ss2->ages_65_or_greater)
        return -1;
    else if (ss1->ages_65_or_greater > ss2->ages_65_or_greater)
        return 1;
    else
        return 0;
}

And a function to print your states (for testing purposes, but you can use it for non-testing purposes as well):

void state_print(const struct state *st)
{
    printf("%s\t%d\t%d\t%.2lf\t%.2lf\t%.2lf",
        st->state_name,
        st->population_2020,
        st->population_2010,
        st->ages_under_5,
        st->ages_under_18,
        st->ages_65_or_greater
    );
}

Now you can use it with qsort():

int main(void)
{
    struct state states[] = {
        {"state1", 100, 200, 2.0, 3.0, 13.0},
        {"state2", 100, 200, 2.0, 4.0, 10.0},
        {"state3", 100, 200, 2.0, 5.0, 12.0},
        {"state4", 100, 200, 2.0, 6.0, 11.0},
        {"state5", 100, 200, 2.0, 7.0, 36.0},
        {"state6", 100, 200, 10.0, 8.0, 140.0},
    };

    qsort(states, 6, sizeof(struct state), state_compare_by_age_65_or_gt);

    for (int i = 0; i < 6; i  ) {
        state_print(&states[i]);
        puts("");
    }
}

Output:

state2  100 200 2.00    4.00    10.00
state4  100 200 2.00    6.00    11.00
state3  100 200 2.00    5.00    12.00
state1  100 200 2.00    3.00    13.00
state5  100 200 2.00    7.00    36.00
state6  100 200 10.00   8.00    140.00

CodePudding user response:

Alternatively, you can use array of structure pointers for optimal sorting.

  1. Input file (borrowing from above answer)
state1, 111, 211, 2.0, 3.0, 13.0
state2, 222, 322, 2.0, 4.0, 10.0
state3, 333, 433, 2.0, 5.0, 12.0
state4, 444, 544, 2.0, 6.0, 11.0
state5, 555, 655, 2.0, 7.0, 36.0
state6, 666, 755, 10.0, 8.0, 140.0
  1. qsort using structure pointers:
#include <stdio.h>
#include <stdlib.h>

#define str(x)          # x
#define xstr(x)         str(x)

#define MAX_NAME_LEN    127

typedef struct {
    char name [MAX_NAME_LEN  1];
    int pop_2020;
    int pop_2010;
    double age_lt5;     // less than 5
    double age_lt18;
    double age_gte65;    // greater or equal
} state_dtls;

int qsort_cmp (const void *p, const void *q) {
    state_dtls *x = *(state_dtls **) p;
    state_dtls *y = *(state_dtls **) q;
    return (x->age_gte65 < y->age_gte65);
}

#define RECORD_STEP_SZ 2

int main() {
    char in_file[MAX_NAME_LEN   1]; /* intializing the variables */
    char out_file[MAX_NAME_LEN   1];

    printf ("Enter Input file name: ");
    scanf (" %" xstr(MAX_NAME_LEN) "s", in_file);

    printf ("Enter Output file name: ");
    scanf (" %" xstr(MAX_NAME_LEN) "s", out_file);

    FILE *ipFile = fopen (in_file, "r");
    if (!ipFile) {
        perror ("Error Opening Input File"); return 1;
    }
    int rec_step = 0;
    state_dtls** SPA = malloc (sizeof (state_dtls*) * RECORD_STEP_SZ * (  rec_step)); // state-details pointers array
    if (!SPA) {
        perror ("Error malloc SPA"); return 3;
    }
    int records = 0;
    for (int ri = 0; 1;   ri) {
        state_dtls* sd = malloc (sizeof (state_dtls));
        if (!sd) {
            perror ("Error malloc state-dtls"); return 4;
        }
        if ((rec_step * RECORD_STEP_SZ) == ri) { // need more space for pointers
            SPA = realloc (SPA, sizeof (state_dtls*) * RECORD_STEP_SZ * (  rec_step));
            if (!SPA) {
                perror ("Error malloc SPA2"); return 5;
            }
        }
        if (6 != fscanf (ipFile, "%[^,], %d, %d, %lf, %lf, %lf\n",
            sd->name, &sd->pop_2020, &sd->pop_2010,
            &sd->age_lt5, &sd->age_lt18, &sd->age_gte65)) {
                printf ("Error reading record [%d]\n", ri  1);
                records = ri;
                free (sd);
                break; // break the loop // EOF
            }
        SPA[ri] = sd;
    }
    fclose (ipFile);

    qsort (SPA, records, sizeof (state_dtls*), qsort_cmp);

    // write to output file
    FILE *opFile = fopen (out_file, "w");
    if (!opFile) {
        perror ("Error Opening output File"); return 2;
    }
    for (int ri = 0; ri < records;   ri) {
        fprintf (opFile, "%s, %d, %d, %lf, %lf, %lf\n",
                 SPA[ri]->name, SPA[ri]->pop_2020, SPA[ri]->pop_2010,
                 SPA[ri]->age_lt5, SPA[ri]->age_lt18, SPA[ri]->age_gte65);
        free (SPA[ri]); // free memory resources as well
    }
    free (SPA);
    fclose (opFile);

    return 0;
}
  1. Output file with descending age_gte65 parameter:
state6, 666, 755, 10.000000, 8.000000, 140.000000
state5, 555, 655, 2.000000, 7.000000, 36.000000
state1, 111, 211, 2.000000, 3.000000, 13.000000
state3, 333, 433, 2.000000, 5.000000, 12.000000
state4, 444, 544, 2.000000, 6.000000, 11.000000
state2, 222, 322, 2.000000, 4.000000, 10.000000
  • Related