1

So what I'm trying to do is to find out how to sort a file by lowest number. The numbers are inside a struct. The program is sort of a scoreboard. You can add a name and you include the score (in this case its about runners and time taken).

After adding the names the program sorts the scores and runners by best time into a file.

Im having trouble figuring out how to:

  1. Sort them by lowest/highest.
  2. Keep the runners name intact with their score after sorting it.

To the code:

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

struct kilpailijat     //The structure im using
{
char nimi[43+1];
float aika;
};


int main() {
int i, maara;
struct kilpailijat henkilo[50];
FILE *tulos;
size_t ln;

while (1 != 0) {
    printf("Montako kilpailijaa haluat lisätä? (max 50): "); //How many runners
    scanf_s("%d", &maara);        // User input of how many runners
    while (getchar() != '\n');    

    if (maara > 50) {   //Checks that the ammount of runners is no more then 50
        printf("Yritit lisätä liian monta kilpailijaa.\n");
    } else if (maara < 0) { //And no less then 0
        printf("Mielenkiintoista. Jos yrittäisit uudelleen.\n");
    } else if (maara == 0) { // Zero Quits the program
        return 0;
    } else {
        break;
    }
}

for (i = 0; i < maara; i++){  // Start loop to add runners and their score.
    printf("\nAnna kilpailijan nimi: ");
    fgets(&henkilo[i].nimi[0], 43, stdin); //Add name of runner

    ln = strlen(henkilo[i].nimi) - 1; //Remove newline off of fgets()
    if (henkilo[i].nimi[ln] == '\n'){
        henkilo[i].nimi[ln] = '\0';
    }

    printf("Kilpailijan aika: ");  //Add score
    scanf_s("%f", &henkilo[i].aika);
    while (getchar() != '\n');
}

if ((tulos = fopen("tulos.txt", "w")) == NULL){ // Check if file opens
    printf("Tiedoston avauksessa tapahtui virhe.\n");
}

for (i = 0; i < maara; i++){ //Writes Name and Score to file.
    fprintf(tulos, "%s\t%.1f\n", henkilo[i].nimi, henkilo[i].aika);
}
fclose(tulos);
}
dertzi
  • 79
  • 1
  • 1
  • 6

2 Answers2

2

Use qsort and implement a custom compare method.

int compare (const void * a, const void * b)
{
    float f1 = ((struct kilpailijat *)a)->aika;
    float f2 = ((struct kilpailijat *)b)->aika;
    int result = 0;
    if (f1 < f2) 
    {
        result = -1;
    }
    else if (f1 > f2) 
    {
        result = 1;
    }
    return result;
}

And then:

qsort (henkilo, maara, sizeof(kilpailijat), compare);

Update:

Ladies and Gentlemen, I'm proud to present a working example.

It uses three languages that I'm not particularly familiar with... Finnish, English and C!

Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
  • This seem a bit too complicated at 5 in the morning. Id better get some sleep and read this again later. Thanks! Seems like your Finnish is pretty fluent for a non Finnish speaker. A+ – dertzi Feb 01 '13 at 02:49
  • 1
    You can use an `else` before the second `if` since if the first is chosen, the second won't. You could even do `if (f1 < f2) return -1; else if (f1 > f2) return +1; else return 0;`, a pattern which can be extended readily if you need to compare more fields (such as the names) in case of a tie on the first field. – Jonathan Leffler Feb 01 '13 at 03:08
1

To build on Anthony Accioly's answer, but using my favorite operator.

int compare (const void * a, const void * b)
{
    float f1 = ((struct kilpailijat *)a)->aika;
    float f2 = ((struct kilpailijat *)b)->aika;
    return f1 < f2
        ? -1
        : f1 > f2
        ? 1
        : 0;
}
Phillip Scott Givens
  • 5,256
  • 4
  • 32
  • 54