1

I have to use quicksort to sort the states by percentage of population whose ages are equal or greater than 65 years old. I can't figure out on how to use it in the function.

I cannot seem to change the compare function. I also have to make a new file to called output file. I used selection sort to sort the file.

struct state {
    char state_name[150];
    int population_2020;
    int population_2010;
    double ages_under_5;
    double ages_under_18;
    double ages_65_or_greater;
};

void sort_states(struct state list[], int n) 
{
    int i, j, p;
    struct state temp;

    for (i = 0; i < n; i++) {
        p = i;
        for (j = i + 1; j < n; j++) {
            if (list[p].ages_65_or_greater < list[j].ages_65_or_greater) {
                p = j;
            }
        }
        temp = list[p];
        list[p] = list[i];
        list[i] = temp;
    }
}

int main()
{
    char input_file_open[100]; /* initializing the variables */
    char output_file_name[110];

    printf("Enter the file name: \n");
    scanf("%s", input_file_open);

    FILE *input_file = fopen(input_file_open, "r"); 
    FILE *output_file;

    struct state list[100];
    int i, n = 0;

    do {
        fscanf(input_file, "%[^,], %d, %d, %lf, %lf, %lf\n",
               list[n].state_name, &list[n].population_2020,
               &list[n].population_2010, &list[n].ages_under_5,
               &list[n].ages_under_18, &list[n].ages_65_or_greater);
        n++;
    } while (!feof(input_file));

    fclose(input_file);

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

    return 0;
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Is your goal to _implement_ quicksort? Or is it to _use_ quicksort (i.e. qsort)? – Zakk Apr 17 '22 at 19:17
  • Add few lines of input file to the question to make it more relevant. – जलजनक Apr 17 '22 at 19:22
  • Tip: enable all warnings and save time. `qsort(input_file, n, sizeof(int), sort_states);` should complain. Review `qsort()` documentation. – chux - Reinstate Monica Apr 17 '22 at 19:29
  • My goal is to implement quicksort. – Maria Rivera Apr 17 '22 at 19:39
  • @MariaRivera If this is what you want, change the title of the question to implementing quicksort. – Zakk Apr 17 '22 at 19:43
  • Hm. `qsort` is a library function that does the sorting for you. If you want to implement your own quicksort, you don't need `qsort`. Call `sort_states` with the proper arguemnts instead. Sorting applies to the whole array, so you should call your sorting function just once, not inside a loop. After `fclose`, the file handle is useless. You're done reading; no need to pass `input_file` anywhere. By the way, your algorithm looks more like selection sort. – M Oehm Apr 17 '22 at 19:45
  • Hey @zakk.dev can you help me with one more thing. – Maria Rivera Apr 17 '22 at 22:15
  • @MariaRivera Post back the struct definition. Your question as-is doesn't make sense. – Zakk Apr 17 '22 at 22:27

2 Answers2

3

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
Zakk
  • 1,935
  • 1
  • 6
  • 17
0

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
जलजनक
  • 3,072
  • 2
  • 24
  • 30