Function to sort the names of basketball players - c

I need to write a program that will recieve (from the user) the number of players in a basketball team and then I need to create an array in a dynamic way. The program will sort the array in an alphabetic order and then print it like that aswell.
I wrote this code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define LENGTH 20
int main(void)
{
int numplayers, i, j;
char persname[LENGTH], tname[LENGTH], temp[LENGTH];
printf("Please insert the amount of basketball players in the group\n");
scanf("%d", &numplayers);
char **players = (char **) malloc(numplayers * sizeof(char *));
printf("Please insert the names of your %d basketball players\n", numplayers);
for (i = 0; i < numplayers; i++) {
gets(persname);
strcpy(persname[i], tname[i]);
}
for (i = 0; i < numplayers-1; i++) {
for (j = i+1; j < numplayers; j++) {
if (strcmp(persname[i], persname[j])) {
strcpy(temp[i], persname[i]);
strcpy(persname[i], persname[j]);
strcpy(persname[j], temp);
}
}
}
for (i = 0; i < numplayers; i++) {
printf("%s\t\t%s\n", tname[i], persname[i]);
}
return 0;
}
But when I run the code, I get an error right after typing the amount of players in the team, Unhandled exception at 0x507340E3 (msvcr120d.dll) in Question4.exe: 0xC0000005: Access violation reading location 0xFFFFFFCC.
What did I do wrong.

Your loop that inputs all the names doesn't use players. Instead it uses pername and tname, incorrectly. This line:
strcpy(persname[i], tname[i]);
shouldn't compile, you're mixing up types in a way that just doesn't make any sense. You should input a line, then dynamically allocate new memory into players[i] and copy the input there. If you have strdup(), that's what it's good for.
Basically the input loop should be something like:
for (i = 0; i < numplayers; i++)
{
char line[1024];
if(fgets(line, sizeof line, stdin) != NULL)
{
const size_t len = strlen(line);
players[i] = malloc(len + 1);
if(players[i] == NULL)
{
fprintf(stderr, "**Out of memory!\n");
exit(1);
}
memcpy(players[i], line, len + 1);
}
else
fprintf(stderr, "**I/O error!\n");
}
This uses fgets() which is way safer than the horribly never-to-be-used gets() monster.
Also, you're not allocating any room for the individual names, just for the array of string pointers.
This line:
char** players = (char**)malloc(numplayers*sizeof(char*));
can be simplified to the much clearer:
char** players = malloc(numplayers * sizeof *players);
No need to repeat type names, and no need to cast the return value of malloc().

I managed to solve it! :)
Here is my updated code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define LENGTH 20
#define LENGTH2 20
int main(void)
{
int numplayers, i, j;
char persname[LENGTH][LENGTH2], temp[LENGTH];
printf("Please insert the amount of basketball players in the group\n");
scanf("%d", &numplayers);
char** players = (char**)malloc(numplayers*sizeof(char));
printf("Please insert the names of your %d basketball players\n", numplayers);
for (i = 0; i < numplayers+1; i++)
{
gets(persname[i]);
}
for (i = 1; i < numplayers+1; i++)
{
for (j = 1; j < numplayers+1; j++)
{
if (strcmp(persname[j - 1], persname[j]) > 0)
{
strcpy(temp, persname[j - 1]);
strcpy(persname[j - 1], persname[j]);
strcpy(persname[j], temp);
}
}
}
printf("\nBasketball players names in order are : ");
for (i = 0; i < numplayers+1; i++)
{
puts(persname[i]);
}
getch();
free(players);
system("PAUSE");
return 0;
}

Related

dynamic allocation string C

I want the user to enter 3 names, and right after the program prints these 3 names
can someone tell me why is not printing anything???
I tried everything
if someone could explain it.....
there is no error, it simply exits after inserting the strings
#include <stdio.h>
#include <stdlib.h>
int main(){
int i, a, componentes;
char *nome;
componentes = 3;
nome = (char*) malloc(sizeof(char)*100);
printf("\n");
for(i = 0; i < componentes; i++){
// printf("String %d: ", i+1);
scanf("%s", &nome[i]);
}
printf("\n");
for(a = 0; a < componentes; a++){
printf("%s\n", nome[i]);
}
return 0;
}
I fixed the issues raised (plus free'ing the memory):
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define LEN 100
int main() {
char *components[N];
for(int i = 0; i < N; i++) {
components[i] = malloc(LEN);
fgets(components[i], LEN, stdin);
}
for(int i = 0; i < N; i++) {
printf("%s", components[i]);
free(components[i]);
}
return 0;
}
You could also allocate the 300 bytes for the 3 strings via local variable on the stack, either with char components[N][LEN]; or as a single string that you index just to show you a different way:
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define LEN 100
int main() {
char components[N * LEN];
for(int i = 0; i < N; i++) {
fgets(components + i * LEN, LEN, stdin);
}
for(int i = 0; i < N; i++) {
printf("%s", components + i * LEN);
}
return 0;
}

How can I duplicate a letter in a string?

I want to write a program where it duplicates every letter in a given string.
For example, if the input is abc then the output would be aabbcc.
How can I do this?
Here is my code so far. It only copies the string:
#include <stdio.h>
int main () {
char str_in[100];
char str_out[200] = "";
int i;
printf("Enter a word: ");
scanf("%s", str_in);
for (i = 0; i < sizeof(str_in); i++) {
str_out[i] += str_in[i];
}
printf("Duplicated word: %s", str_out);
return 0;
}
For starters the destination character array should be at least two times larger than the source array.
The loop that performs the copying can look the following way
size_t j = 0;
for ( size_t i = 0; str_in[i] != '\0'; i++ )
{
str_out[j++] = str_in[i];
str_out[j++] = str_in[i];
}
str_out[j] = '\0';
This is one way to do what you want - since you know that the two indexes in str_out that you want to access correspond to the ith and i+1th positions of str_in:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char str_in[SIZE];
char str_out[SIZE*2];
int i, len;
printf("Enter a word: ");
scanf("%s", str_in);
len = strlen(str_in);
for (i = 0; i < len; i++) {
str_out[i*2] = str_in[i];
str_out[i*2+1] = str_in[i];
}
str_out[i*2] = '\0';
printf("Duplicated word: %s\n", str_out);
return EXIT_SUCCESS;
}
You could also use another variable and update inside the loop as such:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char str_in[SIZE];
char str_out[SIZE*2];
int i, j, len;
printf("Enter a word: ");
scanf("%s", str_in);
len = strlen(str_in);
for (i = 0, j = 0; i < len; i++, j += 2) {
str_out[j] = str_in[i];
str_out[j+1] = str_in[i];
}
str_out[j] = '\0';
printf("Duplicated word: %s\n", str_out);
return EXIT_SUCCESS;
}
As a side note, it's best to #define your constants instead of having them in your code.
I would suggest only allocating the amount of memory you need:
char *str_out = malloc(strlen(str_in) + 1);
and then using another loop variable that counts by 2 each time so you have 2 times as much space for every character in your loop.
If you do that, you should also put + 1 next to the new loop variable to copy it to the current and next elements of the string, thereby duplicating the characters.
I would also advise you to use size_t for your loop variables to match the return of str_len.
Here I have implemented my suggestions:
size_t str_ctr;
size_t str_ctrx2;
size_t in_str_len = strlen(in_str)
/* ... */
for( str_ctrx2 = str_ctr = 0;
str_ctr < in_str_len;
str_ctr++, str_ctrx2 += 2 )
{
out_str[str_ctrx2] = in_str[str_ctr];
out_str[str_ctrx2 + 1] = in_str[str_ctr];
}
/* null-terminate the string */
out_str[str_ctrx2] = '\0';
I would also like to mention that you forget to null-terminate your string in your program. I have made a comment about that and have shown you how to do it above.
#include <stdio.h>
int main () {
char str_in[100];
char str_out[200] = "";
int i, j;
printf("Enter a word: ");
scanf("%s", str_in);
j=0;
for (i = 0; i < sizeof(str_in); i++) {
str_out[i] = str_in[j];
str_out[i+1] = str_in[j];
i++;
j++;
}
printf("Duplicated word: %s", str_out);
return 0;
}

String array prints out trash values

So I have an assignment where I should delete a character if it has duplicates in a string. Right now it does that but also prints out trash values at the end. Im not sure why it does that, so any help would be nice.
Also im not sure how I should print out the length of the new string.
This is my main.c file:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
The output from the printf("%c", string[i]); prints out trash values at the end of the string which is not correct.
The deleteDuplicates function looks like this in the functions.c file:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
There is a more efficent and secure way to do the exercise:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
You can see the results here:
http://codepad.org/wECjIonL
Or even a more refined way can be found here:
http://codepad.org/BXksElIG
Functions in C are pass by value by default, not pass by reference. So your deleteDuplicates function is not modifying the length in your main function. If you modify your function to pass by reference, your length will be modified.
Here's an example using your code.
The function call would be:
deleteDuplicates(string, &length);
The function would be:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
You can achieve an O(n) solution by hashing the characters in an array.
However, the other answers posted will help you solve your current problem in your code. I decided to show you a more efficient way to do this.
You can create a hash array like this:
int hashing[256] = {0};
Which sets all the values to be 0 in the array. Then you can check if the slot has a 0, which means that the character has not been visited. Everytime 0 is found, add the character to the string, and mark that slot as 1. This guarantees that no duplicate characters can be added, as they are only added if a 0 is found.
This is a common algorithm that is used everywhere, and it will help make your code more efficient.
Also it is better to use fgets for reading input from user, instead of scanf().
Here is some modified code I wrote a while ago which shows this idea of hashing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
Example input:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
Output:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10

word scramble with pointers in an array. Crashes when run

I am new to arrays with pointers, and I am trying to make an array of pointers word scramble game that allows 3 tries to guess the word before the game ends. Basically, I have created a function that scrambles a string. Then, that string is sent to a new string, which is shown to the user. The user then enters their guess. I am getting no signal from my compiler on what is wrong.. It just crashes when it is run. I believe the error is when I am sending the pointer to the method. Could someone please tell me why this error is happening? Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
void scramble(char *strings)
{
int length = strlen(strings), i, randomNum;
char temp;
for(i = 0; i < length/2; i++)
{
randomNum = rand()%length;
temp = strings[i];
strings[i] = strings[length - randomNum];
strings[length - randomNum] = temp;
}
}
int main()
{
int i, tries, NUMWORDS;
char *words[] = { "pumpkin", "cantalope", "watermelon", "apple", "kumquat" };
char *scramWords, *user;
NUMWORDS = strlen(words);
srand(time(NULL));
for(i = 0; i < NUMWORDS; i++)
{
scramWords[i] = words[i];
scramble(scramWords[i]);
}
printf("How to play: You get 3 tries to guess each scrambled word.\n");
for(i = 0; i < NUMWORDS; i++)
{
tries = 0;
while(tries !=4)
{
if(tries == 3)
{
printf("You Lose\n");
return 0;
}
printf("Unscramble: %s\n", scramWords[i]);
gets(user);
if(strcmp(user, words[i]) == 0)
{
printf("Correct!\n");
break;
}
else
{
tries++;
}
}
}
printf("You Win!");
return 0;
}
You must not try to modify string literals, or you will invoke undefined behavior. Copy strings before editing them instead of just assigning pointers.
length - randomNum may be length when randomNum is 0.
strlen(words) won't be the number of elements in words. You can use sizeof(words) / sizeof(*words).
You must allocate some buffer to scramWords and user before writing anything there.
You shouldn't use gets(), which has unavoidable risk of buffer overrun, deprecated in C99 and removed from C11.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
void scramble(char *strings)
{
int length = strlen(strings), i, randomNum;
char temp;
for(i = 0; i < length/2; i++)
{
randomNum = rand()%length;
temp = strings[i];
strings[i] = strings[length - randomNum - 1];
strings[length - randomNum - 1] = temp;
}
}
int main(void)
{
int i, tries, NUMWORDS;
char *words[] = { "pumpkin", "cantalope", "watermelon", "apple", "kumquat" };
char **scramWords, user[1024], *lf;
NUMWORDS = sizeof(words) / sizeof(*words);
srand(time(NULL));
scramWords = malloc(sizeof(*scramWords) * NUMWORDS);
if(scramWords == NULL)
{
perror("malloc");
return 1;
}
for(i = 0; i < NUMWORDS; i++)
{
scramWords[i] = malloc(strlen(words[i]) + 1); /* +1 for terminating null-character */
if(scramWords[i] == NULL)
{
perror("malloc");
return 1;
}
strcpy(scramWords[i], words[i]);
scramble(scramWords[i]);
}
printf("How to play: You get 3 tries to guess each scrambled word.\n");
for(i = 0; i < NUMWORDS; i++)
{
tries = 0;
while(tries !=4)
{
if(tries == 3)
{
printf("You Lose\n");
return 0;
}
printf("Unscramble: %s\n", scramWords[i]);
if(fgets(user, sizeof(user), stdin) == NULL)
{
puts("fgets failed");
return 1;
}
if((lf = strchr(user, '\n')) != NULL)
{
*lf = '\0'; /* remove newline character after string read */
}
if(strcmp(user, words[i]) == 0)
{
printf("Correct!\n");
break;
}
else
{
tries++;
}
}
}
printf("You Win!");
return 0;
}
you have a few issues in your code:
1), scramblegets a char * but here
scramWords[i] = words[i];
scramble(scramWords[i]);
you provide it with a char so define your scramWords as a char** instead of char*
2) You don't allocate space when declaring a pointer - that could lead to segfault. Use malloc or before accessing the pointer.
3) When assigning strings from one pointer to another use strcpy, not = operator
4) Use sizeof(words)/sizeof(*words) instead of NUMWORDS = strlen(words);
That should leave you with a working piece of code, but, as said in comments - take care of your warnings!

Char** arrays of string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I tried to do a code that gets number from the user and create array of strings (char**) by the number but for some reason it didn't work and the code crashed. After inputting the strings, the code sorts the strings using strcmp() and then I want to print the whole array. Could anyone help me?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 20
int main(void)
{
int players = 0,i=0,j=0;
char switchString[LENGTH];
printf("Hello user, Welcome to your basketball team!\nplease enter a number of players that plays in your team\n");
scanf("%d", &players);
char** team = (char**)malloc(players*sizeof(char));
for (i = 0; i < players; i++)
{
*(team+i) = (char*)malloc(LENGTH*sizeof(char));
printf("enter name of player %d\n",i+1);
fgets(*(team+i), LENGTH, stdin);
*(team+i)[strcspn(*(team+i), "\n")] = "\0";
}
for (i = 0; i <players; i++)
{
for (j = 0; j < players; j++)
{
if (strcmp(team[j - 1], team[j]) > 0)
{
strcpy(switchString, team[j-1]);
strcpy(team[j-1], team[j]);
strcpy(team[j], switchString);
}
}
}
for (i = 0; i <players; i++)
{
for (j = 0; j < players; j++)
{
printf("%c",team[i][j]);
}
printf("\n");
}
system("PAUSE");
free(team);
return 0;
}
This memory allocation
char** team = (char**)malloc(players*sizeof(char));
^^^^^^^^^^^^
is wrong. There shall be
char** team = (char**)malloc(players*sizeof(char *));
^^^^^^^^^^^^^^
This assignment
*(team+i)[strcspn(*(team+i), "\n")] = "\0";
^^^^^^^^^ ^^^^
is also wrong
There shall be
( *(team+i) )[strcspn(*(team+i), "\n")] = '\0';
^^^^^^^^^^^^^ ^^^^
Or you could just write
team[i][strcspn(team[i], "\n")] = '\0';
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^
Also this loop
for (j = 0; j < players; j++)
{
if (strcmp(team[j - 1], team[j]) > 0)
{
strcpy(switchString, team[j-1]);
strcpy(team[j-1], team[j]);
strcpy(team[j], switchString);
}
}
also incorrect because when j is equal to 0 then in the if statement in expression team[j - 1] there is an attempt to access memory beyond the array.
The loop should look at least like
for (j = 1; j < players; j++)
^^^^^
{
if (strcmp(team[j - 1], team[j]) > 0)
{
strcpy(switchString, team[j-1]);
strcpy(team[j-1], team[j]);
strcpy(team[j], switchString);
}
}
And at last these loops are also nvalid
for (i = 0; i <players; i++)
{
for (j = 0; j < players; j++)
{
printf("%c",team[i][j]);
}
printf("\n");
}
because in the inner loop there are attempts to output characters after the terminating zero.
Just write
for (i = 0; i <players; i++)
{
puts( team[i] );
}
Or you could write for example
for (i = 0; i <players; i++)
{
for (j = 0; players[i][j] != '\0'; j++)
{
printf("%c",team[i][j]);
}
printf("\n");
}
And at the end of the program you need to free the allocated memory.
For example
for (i = 0; i <players; i++)
{
free( team[i] );
}
free( team );
char** team = (char**)malloc(players*sizeof(char));
(Allocate memory of players bytes)
Should be
char** team = malloc(players*sizeof(char*));
(Allocate memory to store players pointers to character)
Replace line
char** team = (char**)malloc(players*sizeof(char));
with
char** team = malloc(players*sizeof(char*));
int i;
for (i = 0; i < players; i++)
team[i] = malloc(LENGTH*sizeof(char));
Assuming you have fixed the memory allocation for the main array of pointers, then the test in the inner loop like this:
if (strcmp(team[j - 1], team[j]) > 0)
is going to lead to unhappiness when j is equal to 0, as it is on the first iteration. That's because you don't have an element with index -1. This is a major problem, even if it isn't the only remaining cause of your crash.
There's a variety of ways to do this, and a variety of issues with the code given.
Here's a working example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 20
int main(void)
{
int players = 0;
char switchString[LENGTH];
printf("Hello user, welcome to your basketball team!\n"
"Please enter the number of players on your team.\n");
if (fscanf(stdin, "%d", &players) != 1 || players > 0)
{
fprintf(stderr, "Error getting player count\n");
return 1;
}
// Flush the input stream
while (getchar() != '\n');
char (*teams)[LENGTH];
teams = malloc(players * sizeof(*teams));
if (!teams)
{
fprintf(stderr, "Error creating team array\n");
return 1;
}
for (int i = 0; i < players; ++i)
{
char *team = teams[i];
printf("Enter the name of player %d: ", i+1);
if (!fgets(team, LENGTH, stdin))
{
fprintf(stderr, "Error getting name of player\n");
free(team);
return 1;
}
char *endline = strchr(team, '\n');
if (endline)
*endline = '\0';
}
// Bubble sort
for (int i = 0; i < players; ++i)
{
for (int j = i; j < players; ++j)
{
if (strcmp(teams[j - 1], teams[j]) > 0)
{
strncpy(switchString, teams[j-1], LENGTH);
strncpy(teams[j-1], teams[j], LENGTH);
strncpy(teams[j], switchString, LENGTH);
}
}
}
for (int i = 0; i < players; i++)
{
printf("%s\n", teams[i]);
}
free(teams);
return 0;
Let's go through this solution piece by piece.
if (fscanf(stdin, "%d", &players) != 1 || players > 0)
{
fprintf(stderr, "Error getting player count\n");
return 1;
}
// Flush the input stream
while (getchar() != '\n');
This will get the number of players and make sure that we the newline we gave doesn't mess with the following inputs.
char (*teams)[LENGTH];
teams = malloc(players * sizeof(*teams));
if (!teams)
{
fprintf(stderr, "Error creating team array\n");
return 1;
}
This completely changes how we store teams.
Why do more mallocs than you have to?
This declares teams as a pointer to an array of LENGTH.
This means that when we malloc, we store all of the memory for the names next to each other, and teams[0] points to the char * of the first team, teams[1] points to the char * of the second team, and so on.
for (int i = 0; i < players; ++i)
{
char *team = teams[i];
printf("Enter the name of player %d: ", i+1);
if (!fgets(team, LENGTH, stdin))
{
fprintf(stderr, "Error getting name of player\n");
free(team);
return 1;
}
char *endline = strchr(team, '\n');
if (endline)
*endline = '\0';
}
Instead of using *(team + i) everywhere, the type of teams allows us to naturally refer to each element like an array of arrays.
We also do a check that fgets succeeds.
We also use strchr to remove the newline as it is clearer to read.
// Bubble sort
for (int i = 0; i < players; ++i)
{
for (int j = 0; j < players; ++j)
{
if (strcmp(teams[j - 1], teams[j]) > 0)
{
strncpy(switchString, teams[j-1], LENGTH);
strncpy(teams[j-1], teams[j], LENGTH);
strncpy(teams[j], switchString, LENGTH);
}
}
}
We now use strncpy for safety. Bubble sort can also be made more efficient.
Notice that in the original code, free was only called for the array of pointers (char **), and not each char * pointer.

Resources