Dachi_3210
Dachi_3210

Reputation: 3

Getting wrong output while trying to sort information first by age and in case of same age then alphabetically

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

Upvotes: 0

Views: 37

Answers (1)

Craig Estey
Craig Estey

Reputation: 33631

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

Upvotes: 0

Related Questions