Home > database >  Getting wrong output while trying to sort information first by age and in case of same age then alph
Getting wrong output while trying to sort information first by age and in case of same age then alph

Time:12-13

So I have to sort a list of people's information by their ages. In case there are people of the same ages, I have to sort them by their names alphabetically.

Here's my code:

#include <stdio.h>
#include <string.h>

struct people{
    char name[30];
    int age;
};

int main(){
    int n, i, j, min, tmp1;
    scanf("%d", &n);
    struct people person[n], temp;

    for(i = 0; i < n; i  ){
        scanf("%s%d", person[i].name, &(person[i].age));
    }
    
    // SELECTIONN SORT
    for(i = 0; i < n - 1; i  ){
        min = i;
        for(j = i   1; j < n; j  ){
            if (person[j].age < person[i].age ||
                strcmp(person[j].name,person[min].name) < 0 && person[j].age == person[min].age){
                min = j;
            }
        }
        if(min != i){
            temp.age = person[i].age;
            person[i].age = person[min].age;
            person[min].age = temp.age;

            strcpy(temp.name, person[i].name);
            strcpy(person[i].name, person[min].name);
            strcpy(person[min].name, temp.name);
        }
    }

    for(i = 0; i < n; i  ){
        printf("%s %d\n", person[i].name, (person[i].age));
    }
}

In almost all of the cases I tried, the code works, however, on this certain input I get "Mary 15" before "Anna 15" and I have no idea why, here's the input:

5
Gilbert 35
Anna 35
Anna 15
Mary 15
Joseph 40

CodePudding user response:

I think the compare you're doing isn't right.

Change:

person[j].age < person[i].age

Into:

person[j].age < person[min].age

And, as I mentioned in my top comment, the swap can be simplified.

And, we can split up the if to make it clearer with no loss of speed.


Here is the corrected code. It is annotated:

#include <stdio.h>
#include <string.h>

struct people {
    char name[30];
    int age;
};

int
main(void)
{
    int n, i, j, min, tmp1;
#if 1
    int dif;
#endif

    scanf("%d", &n);

    struct people person[n], temp;
    for (i = 0; i < n; i  ) {
        scanf("%s%d", person[i].name, &(person[i].age));
    }

    // SELECTIONN SORT
    for (i = 0; i < n - 1; i  ) {
        min = i;
        for (j = i   1; j < n; j  ) {
#if 0
            if (person[j].age < person[i].age ||
                strcmp(person[j].name, person[min].name) < 0 &&
                person[j].age == person[min].age) {
                min = j;
            }
#else
            dif = person[j].age - person[min].age;

            // ages are out-of-sort
            if (dif < 0) {
                min = j;
                continue;
            }

            // ages are in-sort
            if (dif > 0)
                continue;

            // compare names only if ages are the same
            dif = strcmp(person[j].name, person[min].name);
            if (dif < 0) {
                min = j;
                continue;
            }
#endif
        }

        if (min != i) {
// we can simplify this ...
#if 0
            temp.age = person[i].age;
            person[i].age = person[min].age;
            person[min].age = temp.age;

            strcpy(temp.name, person[i].name);
            strcpy(person[i].name, person[min].name);
            strcpy(person[min].name, temp.name);
#else
            temp = person[i];
            person[i] = person[min];
            person[min] = temp;
#endif
        }
    }

    for (i = 0; i < n; i  ) {
        printf("%s %d\n", person[i].name, (person[i].age));
    }
}

In the code above, I've used cpp conditionals to denote old vs. new code:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif

Note: this can be cleaned up by running the file through unifdef -k


Here is the output of the corrected code:

Anna 15
Mary 15
Anna 35
Gilbert 35
Joseph 40
  • Related