C program football team structure with pointer elements and dynamic allocation - c

I have a question about passing function to another function which both have structure as arguments. First I created two structures:
typedef struct
{
char name[25],surname[25];int number;
}PLAYER;
typedef struct
{
char nameofteam[25];int numberofplayers;char *players;
}TEAM;
Then I defined a function to read elements of one player:
void readplayer(PLAYER *);
void readplayer(PLAYER *pi)
{
printf("name:");scanf("%s",pi->name);
printf("surname:");scanf("%s",pi->surname);
printf("number of player:");scanf("%d",&pi->number);
}
My question is how to create function which prototype is void readteam(TEAM*) which will read data for one team, but using function readplayer and call it in main()? Here is what I have tried:
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
char name[25],surname[25];int number;
}PLAYER;
typedef struct
{
char nameofteam[25];int numberofplayers;char *players;
}TEAM;
void readplayer(PLAYER *pi)
{
printf("name:");scanf("%s",pi->name);
printf("surname:");scanf("%s",pi->surname);
printf("number of player:");scanf("%d",&pi->number);
}
void readteam(TEAM *pt)
{
char players[101];int i;
printf("name of team:");scanf("%s",pt->nameofteam);
printf("number of players in team:");scanf("%d",&pt->numberofplayers);
printf("players:");scanf("%s",players);
pt->players=(char *)calloc(length(players)+1,sizeof(char));
copy(pt->players,players);
for(i=0;i<pt->numberofplayers;i++)
{
printf("%d.",i+1);
readplayer(pt+i);
}
}
void erase(TEAM *);
void erase(TEAM *pt)
{
free(pt->players);
}
int length(char *s)
{
int d=-1;
while(s[++d]);
return d;
}
void copy(char *s1,char *s2)
{
while(*s1++ = *s2++);
}
int main()
{
int i,n;
TEAM *p;
do
{
printf("n=");scanf("%d",&n);
}
while(n<1);
p=(TEAM *)malloc(n * sizeof(TEAM));
for(i=0;i<n;i++)
{
printf("%d.",i+1);readteam(p+i);
}
free(p);
}
This gives me an error at the last input (in compiling, not debugging). Must be because of inappropriate use of dynamic allocation. I didn't use <string.h library. Obviously, only the readteam function has to be in main().
Thanks for the answers.

You are confused on how to store the playsrs. You have created a PLAYER struct, but you never use it. Instead, you insist that players must be a single string.
But it should work like this: You have n teams. Ecah team has m players. All team info is stored in your ´TEAMstruct. All player info is stored in yourPLAYERstruct. Because a team is made up of players, there should be aPLAYER` entry in your struct:
typedef struct {
char name[25];
char surname[25];
int number;
} PLAYER;
typedef struct {
char nameofteam[25];
int numberofplayers;
PLAYER *players;
} TEAM;
Then, when you read players, you read the bare team info in readteam. But you don't read anything about individual players there, because you delegate that to readplayer. Of course, the pointer you pass to that function must be that for a player, not one for a team:
void readplayer(PLAYER * pi)
{
printf("name:");
scanf("%s", pi->name);
printf("surname:");
scanf("%s", pi->surname);
printf("number of player:");
scanf("%d", &pi->number);
}
void readteam(TEAM * pt)
{
int i;
printf("name of team:");
scanf("%s", pt->nameofteam);
printf("number of players in team:");
scanf("%d", &pt->numberofplayers);
pt->players = calloc(pt->numberofplayers, sizeof(*pt->players));
for (i = 0; i < pt->numberofplayers; i++) {
printf("Player %d:\n", i + 1);
readplayer(pt->players + i);
}
}
Your cast to (char *) hides the warning about incompatible types. You should cast only when you know what you're doing. In this simple program, you don't need casts.
In your original code, there are warnings about "implicit declarations". These concern your copy and length functions. (By the way, what's wrong with strlen and strcpy?) You should move these functions to the top so that they are declared before they are called. ALternatively, provide prototypes at the beginning of your code or in a header file, which you #include at the top. (But now that you read into PLAYER structs, these functions are no longer needed.)

Related

How to correctly pass structures to functions

So the question I'm working on has me creating a structure with 5 elements: id number, name, department, course, and year. I have to write a function that prints the names of people with certain years and a function that prints all data based on id number input.
When I type in 2020 as an input I get a segmentation fault. What could be causing this?
#include <stdio.h>
struct stud
{
int id;
char name[50];
char dep[50];
char course[50];
int year;
};
void printbyyear(struct stud *student,size_t sz, int a);
void printspecific(struct stud *b,size_t sz, int a);
int main()
{
int yr,num,b;
struct stud students[]={
{1,"Jon","math","calc",2019},
{2,"Tim","Language arts","calc",2020},
};
printf("Input year to search for:");
scanf("%d",&yr);
printbyyear(students, sizeof(students),yr);
printf("Input ID # to search for:");
scanf("%d",&num);
printspecific(students, sizeof(students),num);
return 0;
}
void printbyyear(struct stud *b,size_t sz, int a)
{
int i;
for(i=0;i<sz;i++)
{
if (b[i].year==a)
{
printf("%d %c %c %c %d",b[i].id,b[i].name,b[i].dep,b[i].course,b[i].year);
}
}
}
void printspecific(struct stud *b,size_t sz, int a)
{
printf("%d %c %c %c %d",b->id,b->name,b->dep,b->course,b->year);
return 0;
}```
There are many mistakes in your programs.
printbyyear(struct stud,yr);
that is not how you call a function with struct variable, change it as printbyyear(b1,yr); or printbyyear(b2,yr);
you are not using array of structs , so you don't need to use loops at all for your code.
if (b.year == a)
{
printf("%d %s %s %s %d",b.id,b.name,b.dep,b.course,b.year);
}
finally if you want to store multiple records, then use array of struct's like below.
struct stud students[]= {
{2,"Tim","Language arts","calc",2020},
{1,"Jon","math","calc",2019}
};
and call it as below ( sizeof(students)/sizeof(students[0]) ) gives the number of elements you have in your structure)
printbyyear(students, sizeof(students)/sizeof(students[0]), yr);
now you can use loops for printing because you passed an array
void printbyyear(struct stud *student, size_t sz, int y)
{
int i;
for(i=0;i<sz;i++)
{
if (student[i].year == y)
{
printf("%d %s %s %s %d",student[i].id,student[i].name,student[i].dep,student[i].course,student[i].year);
}
}
}
and you declaration of function should be as below
void printbyyear(struct stud *b,size_t size, int a);
I guess that here
if (b[i]stud.year==a)
You are trying to access b1, b2 and any other possible student. To do that you need an array of type struct stud
struct stud b[5];
Now your if condition makes sense. The function call should be:
printbyyear(b,yr);
And the declaration
void printbyyear(struct stud *b, int a)
Also since you initialize only two students, i.e. only two elements of your array, the for loop should be for(i=1;i<=2;i++) with a 2 not a 5.
Accessing uninitialised elements or accessing an array out of bounds will result in an undefined behaviour.
Correct is an ambiguous term, so I will just say this method is one that I prefer:
Passing the address of an object of significant size is advantageous in that the address of that object is going to be smaller than the object itself.
So given for example your struct (typedefed for readability) I would make the following modifications (i.e. to pass by reference to the address of the object.)
Read in-line comments and note corrections in code:
typedef struct
{
int id;
char name[50];
char dep[50];
char course[50];
int year;
}stud_s;
//modify to accept pointer, and add size of array argument
void printbyyear(stud_s *s, int yr, size_t size);
int main()
{
int yr,num;
stud_s b1[] = { {1,"Jon","math","calc",2019},
{2,"Tim","Language arts","calc",2020},
{3,"Jen","the arts","calc",2021},
{4,"Bob","painting arts","calc",2022},
{5,"jed","numeric arts","calc",2023}
};
size_t size = sizeof(b1)/sizeof(b1[0]);
printf("Input year to search for:");
scanf("%d",&yr);
printbyyear(b1,yr, size);// b1 is a pointer to array of struct here.
printf("Input ID # to search for:");
scanf("%d",&num);
return 0;
}
void printbyyear(stud_s *b, int a, size_t size)
{
int i=0;
//for(i=1;i<=5;i++)//results in out of bounds access to array
for(i=0;i<size;i++) //change magic number for actual size of array
{
if (b[i].year==a)
{
//fix format specifiers
printf("%d %s %s %s %d\n",b[i].id,b[i].name,b[i].dep,b[i].course,b[i].year);
//printf("%d %c %c %c %d",b[i].id,b[i].name,b[i].dep,b[i].course,b[i].year);
i++;
}
}
}

Need help scanning a char* into a function with struct

I'm just starting to learn C in one of my college courses. We have gone over similar topics but not quite like what my professor is asking. I'm not great at all with pointers or structs so this assignment is getting frustrating, but I'm getting only one error in my last scanf saying "expected type char* but getting struct user**" and I cannot figure it out.
#include <stdio.h>
#define PEOPLE 10
struct user {
int user_id;
char* user_name;
};
void populate(struct user* users, int size);
void main() {
struct user s1[PEOPLE], s2;
populate(&s2, s1->user_id);
}
void populate(struct user* users, int size) {
for(int i = 1; i < PEOPLE + 1; i++) {
printf("Enter an ID of user %d: ", i);
scanf("%d", &size);
printf("Enter the name of user %d: ", i);
scanf("%s", users);
}
}
Here is the assignment:
Write a C programs that do the following:
Program defines a C struct, called user, that has two attributes
int user_id;
char* user_name;
Program declares an array of about 10 struct user variables and a function called populate() that takes as parameters a pointer to a struct user variable and an integer size. The populate() method will ask the user for an id and name to be assigned to each cell in the array of struct user variables until the array is full.
Hint: A header for this function might look like void populate (struct user* users, int size);
Here is the error message:
https://i.stack.imgur.com/xLUyo.png
In your second scanf statement, you're trying to capture a string argument with a struct variable. Your second scanf statement should be the following:
scanf("%s", users-> user_name);
You're also passing the wrong arguments to your function. The complete code is as given below:
#include <stdio.h>
#define PEOPLE 10
struct user {
int user_id;
char user_name[20];
};
void populate(struct user* users, int size);
void main() {
struct user s1[PEOPLE];
populate(s1, PEOPLE);
}
void populate(struct user users[], int size) {
for(int i = 0; i < size; i++) {
printf("Enter an ID of user %d: ", i+1);
scanf("%d", &users[i].user_id);
printf("Enter the name of user %d: ", i+1);
scanf("%s", users[i].user_name);
}
}

String comparison in C(Game project)

I am making a little game, in which I would like to make string comparison, to compare 2 strings, and if they are equal I would like to print it out.:
I included stdio.h and string.h I use codeblocks.
I tried to run the code, but codeblocks says
code.exe has stopped working
Could someone help me?
The code looks like this:
int main(void)
{
typedef struct {
char * name;
} player;
int player_number;
player players[100];
printf("What's your name?\n");
scanf("%s",&players[0].name);
printf("How many players are playing the game?\n");
scanf("%d", &player_number);
printf("Can you name your friends?\n");
int d;
for(d=1;d<player_number;d++)
{
scanf("%s", &players[d].name);
}
printf("Who is starting the game?\n");
char * starter;
scanf("%s",&starter);
int e;
for(e=0;e<player_number;e++)
{
if(strncmp(players[e].name, starter, 10)==0)
{
printf("%s is starting the game",starter);
break;
}
}
return 0;
}
You need to have some memory for char *starter to point at.
Here's your mistake.
char * starter;
scanf("%s",&starter);
also here;
typedef struct {
char * name;
}player;
Instead try this;
typedef struct {
char name[100];
}player;
char starter[100];
scanf("%s",starter);
I don't know C that much but shouldn't there be a .name in the first input?
It should look like I suppose:
printf("What's your name?\n");
scanf("%s",&players[0].name);

Why am I getting garbage value after displaying the data

I am getting garbage value when I display the records.
I have to create a database of students in C using array of structures and without pointers.
Is there any other way of doing this?
How to use array of structures?
#include <stdio.h>
struct student {
char first_name[10],last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student);
void display(struct student);
void main() {
struct student S[10];
int n, i;
printf("Enter the number of records to enter : ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
accept(S[i]);
}
for (i = 0; i < n; i++) {
display(S[i]);
}
}
void accept(struct student S) {
scanf("%s", S.first_name);
scanf("%s", S.last_name);
scanf("%d", &S.roll);
scanf("%s", S.address);
scanf("%f", &S.marks);
}
void display(struct student S) {
printf("\n%s", S.first_name);
printf("\n%s", S.last_name);
printf("\n%d", S.roll);
printf("\n%s", S.address);
}
Everything in C is pass-by-value. Which means you are modifying variable copy in stack frame, while real variable passed as parameter remains untouched.
You have to pass an pointer to variable which you want to modify in function.
// Function declaration
void accept(struct student *);
// Call
accept(&S[i]);
// Usage in function via dereference operator
scanf("%s",S->first_name);
If you would like to enter unknown amount of records, you should use VLA (since c99) or dynamically allocate structures.
VLA
scanf("%d",&n);
struct student S[n];
Dynamic callocation
scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);
Because in your case, if user input more that 9 records you are touching outside of bounds, which has undefined behavior.
There are multiple issues in your code:
The standard prototype for main without arguments is int main(void)
You should allocate the array dynamically with calloc.
you should pass structure pointers to the accept and display functions instead of passing structures by value. Passing the destination structure by value is incorrect as the accept function cannot modify the structure in the main function, which remains uninitialized and causes garbage to be displayed. Note that it is actually undefined behavior to access uninitialized data so the program could behave in even worse ways.
You should provide scanf() with the maximum number of arguments to store into character arrays to avoid potential buffer overflows.
you should verify the return values of scanf() to avoid undefined behavior on invalid input.
you could use the %[^\n] scan set to allow embedded spaces in the address field.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct student {
char first_name[10], last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student *sp);
void display(const struct student *sp);
int main(void) {
struct student *S;
int n, i, j;
printf("Enter the number of records to enter : ");
if (scanf("%d", &n) != 1)
return 1;
S = calloc(sizeof(*S), n);
if (S == NULL) {
return 1;
}
for (i = 0; i < n; i++) {
accept(&S[i]);
}
for (i = 0; i < n; i++) {
display(&S[i]);
}
free(S);
return 0;
}
void accept(struct student *sp) {
if (scanf("%9s%9s&d %19[^\n]%f",
sp->first_name, sp->last_name, &sp->roll,
sp->address, &sp->marks) != 5) {
printf("missing input\n");
exit(1);
}
}
void display(const struct student *sp) {
printf("%s\n", sp->first_name);
printf("%s\n", sp->last_name);
printf("%d\n", sp->roll);
printf("%s\n", sp->address);
printf("%f\n", sp->marks);
printf("\n");
}

passing a struct to a function and loop through it

Trying to pass a struct to a function and browse through it. Is this the correct way to pass a struct to a function? The for loop in the function view() doesn't seem to work. Any help with that too would be appreciated.
My structs:
typedef struct {
char name[20];
employee *list_employees;
int empl_count;
} agency;
typedef struct {
char name[30];
int age;
} employee;
Important pars of the code:
int main()
{
//...
int nmbr_agencies;
agency *list_agencies = malloc(sizeof(agency) * nmbr_agencies);
view(&list_agencies, &nmbr_agencies);
}
void view(agence *ListA[], int *nmbr)
{
int i=0;
for (i = 0; i < *nmbr; i++){
printf("name of agency: %s\n", ListeA[i]->name);
printf("number of employees\n, ListeA[i]->empl_count);
}
}
No.
You should just pass a single array if that is what you have, not pretend (in the call) that you have an array of pointers which you don't have.
Make the function:
void view(const agency *list, size_t number);
and call it like so:
view(list_agencies, nmbr_agencies);
Then inside the function, do direct accesses:
printf("name of agency: %s\n", list[i].name);
since you don't have an array of pointers.

Resources