1

I got an assignment to make program that asks for a number of teams, their names, wins and losses. I have got two problems with the code.

  • How do I get the team names with spaces in them correctly?
  • And how to sort the teams by total value (total=wins-losses) before printing?
#include <stdio.h>
#include <string.h>

#define NAME_LENGTH 25

typedef struct {
    char name[NAME_LENGTH];
    int wins;
    int losses;
    int total;
} Total;

Total readTeamInfo(void);
void printInfo(Total tt, int);

int main(void) {

    int i, teams;

    printf("Number of teams > ");
    scanf("%d", &teams);

    Total data[teams];

    for (i = 0; i < teams; i++) {
        data[i] = readTeamInfo();
        data[i].total = data[i].wins - data[i].losses;
    }

    for (i = 0; i < teams; i++) {
        printInfo(data[i], i);
    }
    return (0);
}

Total readTeamInfo(void) {

    Total tt;

    printf("Team name > ");
    scanf("%s", tt.name);

    printf("Wins > ");
    scanf("%d", &tt.wins);

    printf("Losses > ");
    scanf("%d", &tt.losses);

    return (tt);
}

void printInfo(Total tt, int i) {
    printf("Team #%d %s: %d wins and %d loses\n", i + 1, tt.name, tt.wins, tt.losses);
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Arttu
  • 23
  • 2
  • Don't use `scanf()` if the value can have spaces. Use `fgets()` to read a whole line, then [remove the newline at the end](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input). – Barmar Oct 19 '22 at 15:59
  • Don't use `scanf`. If you do use `scanf`, you can't use `%s` if you expect to distinguish whitespace. You should *never* use `%s` but should always use a width modifier and write it `%24s` (you can dynamically generate the 24 from the macro if you need to). You *must* *always* *check* the value returned by scanf. But it's really easier if you just stop using `scanf`. – William Pursell Oct 19 '22 at 15:59
  • http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html – William Pursell Oct 19 '22 at 16:00
  • Use the `qsort()` function to sort the array. – Barmar Oct 19 '22 at 16:00
  • And for qsort use a comparator similar to the following int cmpfunc (const void * a, const void * b) { return ((Total *)a)->total - ((Total *)b)->total; } – Sven Nilsson Oct 19 '22 at 16:13

1 Answers1

0

To read the team name, you can use scanf() with a " %24[^\n]" format. This format specifies a class of characters, namely all characters different from '\n' and the maximum number of characters to store into the destination array before the null terminator. The number 24 is hardcoded here and there is no simple way to specify this number as an expression involving NAME_LENGTH. An alternative solution is to use fgets() to read a full line and strip the newline.

To sort the array of structures, you should use qsort() with a custom comparison function.

Also check the return value of scanf() to detect invalid or missing input and exit with an error message.

It is quite confusing to name the team structure Total. You should use meaningful names such as Team.

Here is a modified version:

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

#define NAME_LENGTH 25

typedef struct {
    char name[NAME_LENGTH];
    int wins;
    int losses;
    int total;
} Team;

Team readTeamInfo(void);
void printInfo(Team tt, int);

int compare_teams(const void *p1, const void *p2) {
    const Team *t1 = p1;
    const Team *t2 = p2;
    return (t1->total > t2->total) - (t1->total < t2->total);
}

int main() {
    int i, teams;

    printf("Number of teams > ");
    if (scanf("%d", &teams) != 1 || teams <= 0) {
        fprintf(stderr, "invalid input\n");
        exit(1);
    }

    Team data[teams];

    for (i = 0; i < teams; i++) {
        data[i] = readTeamInfo();
        data[i].total = data[i].wins - data[i].losses;
    }

    qsort(data, teams, sizeof(*data), compare_teams);

    for (i = 0; i < teams; i++) {
        printInfo(data[i], i);
    }
    return 0;
}

Team readTeamInfo(void) {
    Team tt;

    printf("Team name > ");
    if (scanf(" %24[^\n]", tt.name) != 1) {
        fprintf(stderr, "invalid input\n");
        exit(1);
    }

    printf("Wins > ");
    if (scanf("%d", &tt.wins) != 1) {
        fprintf(stderr, "invalid input\n");
        exit(1);
    }
    printf("Losses > ");
    if (scanf("%d", &tt.losses) != 1) {
        fprintf(stderr, "invalid input\n");
        exit(1);
    }
    return tt;
}

void printInfo(Team tt, int i) {
    printf("Team #%d %s: %d wins and %d loses\n",
           i + 1, tt.name, tt.wins, tt.losses);
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189