C - re-allocation doesn't seem to work, can't add to a "dynamic array" - c

I have a Team struct which has field of pointer to a struct called Player.
I have a function that returns a pointer to a player,
everytime the user adds a player, it suppose to re-allocate the memory size of the "array" that contains the players, and to add a new player.
like a dynamic array of players.
for some reason it only accepts one player.
I have seen problems that resembles mine, but no answer worked.
Please help me.
the code:
struct Player {
float pointsAverage;
int uniformNumber;
int pointsOfLastFiveGames[5];
char *playerName;
};
struct Team {
int numberOfPlayers;
char *managerName = nullptr;
struct Player *players = (Player*)malloc(sizeof(Player));
};
struct Player* setPlayer(){
struct Player *player = NULL;
player = (struct Player*)malloc(sizeof(struct Player));
char name[81] = {0};
int jerseyNumber = -1;
int sumOfPoints = 0;
int currentPoint = 0;
printf("Player name?\n");
scanf("%s", &name);
int nameLength = strlen(name);
player->playerName = (char*)malloc(sizeof(char)*(nameLength + 1));
strcpy(player->playerName, name);
printf("Jesrsey number?\n");
scanf("%d",&jerseyNumber);
player->uniformNumber = jerseyNumber;
printf("Player point history?\n");
int i;
for (i=0; i<NUM_OF_PLAYER_POINT; i++) {
scanf("%d",&currentPoint);
sumOfPoints+=currentPoint;
}
player->pointsAverage = (float)(sumOfPoints/NUM_OF_PLAYER_POINT);
return player;
}
struct Team* setTeam(){
//initialize a team
struct Team *team = NULL;
team = (struct Team*) malloc(sizeof(struct Team));
team->managerName = NULL;
team->numberOfPlayers = 0;
team->players = NULL;
int usersChoice = -1;
// temp char array of name so i can take its size after user input
char name[81] = {0};
printf("Hello, please enter manager's name:\n");
scanf("%s",&name);
// checking the length of the user input.
int nameLength = strlen(name);
// dynamically allocating the manangerName memory space.
team->managerName = (char *)malloc(sizeof(char) * (nameLength + 1));
// setting the managername to the name the user typed.
strcpy(team->managerName, name);
int playerCounter = 1;
int addedPlayerCounter = 0;
while (1){
printf("Would you like to buy a player (1) yes (else) no?\n");
scanf("%d",&usersChoice);
if(usersChoice==1){
usersChoice = 0;
playerCounter++;
Player *temp = NULL; // here I tried make a new pointer but it still doesn't work
struct Player* tempPlayer = setPlayer();
temp = (Player*)realloc(team->players, sizeof(Player)*playerCounter);
(temp+(sizeof(Player)*addedPlayerCounter))->playerName = tempPlayer->playerName;
(temp+(sizeof(Player)*addedPlayerCounter))->pointsAverage = tempPlayer->pointsAverage;
addedPlayerCounter++;
team->numberOfPlayers++;
}else{
return team;
}
}
}
the main function just calls the setTeam function.

Related

Student of the Year program using structure

My first problem is that I have problem to make that for loop and implement it into the code and somehow finish my program.
My second problem is compiler showing problem in this: memset(database,0,SIZE*sizeof(struct student)); type specifier missing, defaults to 'int'
And at the end of program i have problem with memcpy(database.name,name,size_of_name); member reference base type 'struct student [100]' is not a structure or union
There are my structure and functions:
#define SIZE 100
struct student {
char name[SIZE];
int votes;
};
struct student database[SIZE];
memset(database,0,SIZE*sizeof(struct student));
int size = 0;
int find_student(struct student* students,int size, const char* name){
// for loop,which take all entries in database
// if it find same name, then reutrn his index
//otherwise reuturn -1;
int i;
for(i=0; i<SIZE;i++){
// how to make that loop
}
return -1;
}
int compare(const void* p1, const void* p2){
struct student* s1 = (struct student*)p1;
struct student* s2 = (struct student*)p2;
// s1->votes
// s1->name
return 0;
}
And there is my code what I already did( sorry for my grammar):
char line[SIZE];
memset(line,0,SIZE);
char* r = fgets(line,SIZE,stdin);
if (r == NULL){
printf("End of input");
return (-1);
}
char* end = NULL;
int value = strtol(line,&end,10);
if (value == 0){
printf("Convertion was not sucessful");
return (-1);
}
// helping array
char name[SIZE];
// set on zero
memset(name,0,SIZE);
// get begining of a name = one position after space
char* beginning_name = end + 1;
// Size of name is number of signs to end of string
// minus end of line
int size_of_name = strlen(beginning_name) - 1;
if (size_of_name > 0){
// copy
memcpy(name,beginning_name,size_of_name);
// At the end is saved string with name
// without end of line and with zero at the end
}
else {
// failed to read a name
printf("Failed to read a name");
return (-1);
}
int id = find_student(database,size,name);
if (id< 0){
// copy it to last place in array
memcpy(database.name,name,size_of_name);
// increase number of entries
size+=1;
}
else {
// there I need add to votes,something like votes++;
}
}
Sorry for formating but I am new at stackoverflow.

Why am I getting these errors when I am trying to compile my C code?

I am getting this error when compiling:
browninz.buildrooms.c:191:29: error: expected expression before ‘struct’
AddRandomConnection(struct room RoomA.outboundConnections, struct room RoomB.outboundConnections);
^
browninz.buildrooms.c:191:29: error: too few arguments to function ‘AddRandomConnection’
browninz.buildrooms.c:40:6: note: declared here
void AddRandomConnection(struct room *RoomA, struct room *RoomB)
^
Originally I started with about 20+ errors and I have finally scaled it down to a single error within my AddRandomConnections method, I am trying to compile this code and it keeps throwing an error for this single line. I have been trying for a few hours for different methods to fix the error, but I cannot get it to go away. Can anyone help me figure out why I am getting this error?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
/*#include <stdbool.h>*/
typedef enum
{
false,
true
} bool;
// Creating the template for each of the rooms via struct
struct room
{
int id;
char* name;
char* type;
int numOutboundConnections;
struct room* outboundConnections[5];
};
// Returns true if all rooms have 3 to 6 outbound connections, false otherwise
int IsGraphFull(struct room *structureRooms)
{
int k = 0;
while (k < 7){
if (sizeof(structureRooms[k].numOutboundConnections) < 3){
return 0;
}
k++;
}
return 1;
}
// Adds a random outbound connection between two rooms
void AddRandomConnection(struct room *RoomA, struct room *RoomB)
{
while(true)
{
RoomA = GetRandomRoom(RoomA);
if (CanAddConnectionFrom(RoomA) == true)
break;
}
do
{
RoomB = GetRandomRoom(RoomB);
}
while(CanAddConnectionFrom(RoomB) == false || IsSameRoom(RoomA, RoomB) == true || ConnectionAlreadyExists(RoomA, RoomB) == true);
ConnectRoom(RoomA, RoomB); // TODO: Add this connection to the real variables,
ConnectRoom(RoomB, RoomA); // because this A and B will be destroyed when this function terminates
}
// Returns a random Room, does NOT validate if connection can be added
int GetRandomRoom(struct room *connections[])
{
// Initializes random number generator
srand(time(0));
// Generate random room
int x = rand() % 7;
return x;
}
// Returns true if a connection can be added from Room x (< 6 outbound connections), false otherwise
int CanAddConnectionFrom(struct room *RoomA)
{
if (sizeof(RoomA->numOutboundConnections) < 6)
{
return 1;
}
else{
return 0;
}
}
// Returns true if a connection from Room x and Room y already exists, false otherwise
int ConnectionAlreadyExists(struct room *RoomA, struct room *RoomB)
{
int myConnections;
int i = 0;
for (i; i <= 6; i++){
if ((RoomA->numOutboundConnections = RoomB->id)){
myConnections = 1;
break;
}
if(myConnections == 1)
{
return 1;
}
else
return 0;
}
}
// Connects Rooms A and B together, does not check if this connection is valid
void ConnectRoom(struct room *RoomA, struct room *RoomB)
{
RoomA->numOutboundConnections = RoomB->id;
}
// Returns true if Rooms x and y are the same Room, false otherwise
int IsSameRoom(struct room *RoomA, struct room *RoomB)
{
if (strcmp(RoomA->name, RoomB->name) == 0){
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
// Room names
char Forest[] = "Forest";
char Beach[] = "Beach";
char Cliff[] = "Cliff";
char River[] = "River";
char Cave[] = "Cave";
char Mountain[] = "Mountain";
char Cabin[] = "Cabin";
char Castle[] = "Castle";
char Fountain[] = "Fountain";
char Homeria[] = "Homeria";
// Initializing a room array variable to store contents of all room names
char* roomName[] = {Forest, Beach, Cliff, River, Cave, Mountain, Cabin, Castle, Fountain, Homeria};
// Creating the structs of 7 rooms each labeled with a name and type slot
struct room Room1;
Room1.id = 1;
Room1.name = calloc(16, sizeof(char));
Room1.type = calloc(16, sizeof(char));
strcpy(Room1.type, "START_ROOM");
struct room Room2;
Room2.id = 2;
Room2.name = calloc(16, sizeof(char));
Room2.type = calloc(16, sizeof(char));
strcpy(Room2.type, "MID_ROOM");
struct room Room3;
Room3.id = 3;
Room3.name = calloc(16, sizeof(char));
Room3.type = calloc(16, sizeof(char));
strcpy(Room3.type, "MID_ROOM");
struct room Room4;
Room4.id = 4;
Room4.name = calloc(16, sizeof(char));
Room4.type = calloc(16, sizeof(char));
strcpy(Room4.type, "MID_ROOM");
struct room Room5;
Room5.id = 5;
Room5.name = calloc(16, sizeof(char));
Room5.type = calloc(16, sizeof(char));
strcpy(Room5.type, "MID_ROOM");
struct room Room6;
Room6.id = 6;
Room6.name = calloc(16, sizeof(char));
Room6.type = calloc(16, sizeof(char));
strcpy(Room6.type, "MID_ROOM");
struct room Room7;
Room7.id = 10;
Room7.name = calloc(16, sizeof(char));
Room7.type = calloc(16, sizeof(char));
strcpy(Room7.type, "END_ROOM");
// Randomizing the room names to append to a random room #
srand(time(0));
struct room structureRooms[7] = {Room1, Room2, Room3, Room4, Room5, Room6, Room7};
int i = 0;
int array1[] = {0 ,0, 0, 0, 0, 0, 0, 0, 0, 0};
// Loop for each of the rooms which checks to see if a name is available, if so, apply to random room
while ( i < 7 ){
int randNum = rand() % 10;
if (array1[randNum] == 0){
array1[randNum] = 1;
strcpy(structureRooms[i].name, roomName[randNum]);
i++;
}
}
// Create all connections in the graph
while (IsGraphFull(structureRooms) == false)
{
AddRandomConnection(struct room RoomA.outboundConnections, struct room RoomB.outboundConnections);
}
// Assigning char limits
char dirname[100];
char dir0[100];
char dir1[100];
char dir2[100];
char dir3[100];
char dir4[100];
char dir5[100];
char dir6[100];
// Generate the "rooms" directory name with the PID
sprintf(dirname, "./browninz.rooms%d", getpid());
// Generate the room names concatenated with the directory name
sprintf(dir0, "%s/Room1", dirname);
sprintf(dir1, "%s/Room2", dirname);
sprintf(dir2, "%s/Room3", dirname);
sprintf(dir3, "%s/Room4", dirname);
sprintf(dir4, "%s/Room5", dirname);
sprintf(dir5, "%s/Room6", dirname);
sprintf(dir6, "%s/Room7", dirname);
// Create a new directory that the "rooms" files will be stored in
mkdir(dirname, 0770);
// Pointer files of each of the rooms
FILE *myRoom1;
FILE *myRoom2;
FILE *myRoom3;
FILE *myRoom4;
FILE *myRoom5;
FILE *myRoom6;
FILE *myRoom7;
// Now opening the room files / directories to create or write them in the folder.
myRoom1 = fopen(dir0, "w+");
myRoom2 = fopen(dir1, "w+");
myRoom3 = fopen(dir2, "w+");
myRoom4 = fopen(dir3, "w+");
myRoom5 = fopen(dir4, "w+");
myRoom6 = fopen(dir5, "w+");
myRoom7 = fopen(dir6, "w+");
// Creating a pointer array of all of the room pointers
FILE *myRooms[7] = {myRoom1, myRoom2, myRoom3, myRoom4, myRoom5, myRoom6, myRoom7};
// Printing room file name, type, and connections and iterates for each room
int counter = 0;
while (counter < 7) {
fprintf(myRooms[counter], "ROOM NAME: %s\n", structureRooms[counter].name);
fprintf(myRooms[counter], "ROOM TYPE: %s\n", structureRooms[counter].type);
// fprintf(myRooms[counter], "CONNECTION 1: %s\n", structureRooms[counter].outboundConnections[counter]);
// test to see if connection works
fprintf(myRooms[counter], "CONNECTION 1: %s\n", structureRooms[counter].name);
counter++;
}
return 0;
}
In your call below, remove the "struct room". You've already declared the type in the function declaration.
// Create all connections in the graph
while (IsGraphFull(structureRooms) == false)
{
AddRandomConnection(struct room RoomA.outboundConnections, struct room RoomB.outboundConnections);
}
So that it is just AddRandommConnection(RoomA.outboundConnections, Roomb.outboundConnections);

Read txt file with different content in each line

Im trying to read a file a then insert it in a linked list but i'm having trouble to use sscanf. I dont know why but it never goes through the first if with sscanf.The file is a result from the user input and some users have more information than others so i need to differentiate the way a read each line.
The file is exactly like this.
201263066#1,2,3#9#1,2,3,4,5,6,7,8,10,11,
201263065#0,0,0#0#
201263064#0,0,0#0#
201363524#4,5,7#2#2,3,4
201596874#1,9,8#8#2,8,9,6,5,2,1
typedef struct user{
int id;
int city[3];
int *places;
int hot;
}User;
typedef struct Users_node *List_users;
typedef struct Users_node{
User user;
List_users next;
}Each_user;
void read_file(List_users u){
FILE *p;
int i=0,a,n=0;
char line[1024];
List_users aux2;
char city_ids[20];
char *pt,*pt2;
int hotspot;
int user_id;
char places_id[200];
p = fopen("userPref.txt", "r");
while(!feof(p)){
fgets(line,sizeof(line),p);
if(sscanf(line,"%d#%s#%d#%s",&user_id,city_ids,&hotspot,places_id) == 4){
aux2->user.id = user_id;
pt = strtok(city_ids,",");
while(pt != NULL) {
a = atoi(pt);
printf("%d\n", a);
aux2->user.city[n++] = a;
pt = strtok(NULL, ",");
}
aux->user.hot = hotspot;
pt2 = strtok(places_id,",");
while(pt2 != NULL) {
a = atoi(pt);
printf("%d\n", a);
aux2->user.places[n++] = a;
pt2 = strtok(NULL, ",");
}
}else{
aux2->user.id = atoi(strtok(line,"#"));
aux2->user.city[0] = atoi(strtok(NULL,","));
aux2->user.city[1] = atoi(strtok(NULL,","));
aux2->user.city[2] = atoi(strtok(NULL,","));
aux->user.hot = atoi(strtok(NULL,"#"));
}
}
fclose(p);
}

Global array of struct pointers not storing data

I have a C program that is trying to represent the layout of a house. It reads in the rooms from a text file with the following format:
Room
Door
Door
*
Room
Door
Door
The rooms and doors are stored as structures, and I have a global array of pointers to store 10 rooms. I'm using the method readrooms() to read in the rooms from the text file and store them in the array. However, after reading it in, when I try to print the contents of the array, I get a string of random characters.
#include <stdio.h>
#define MAX 10
struct room * rooms[MAX];
int rp = 0; //room count
//Declare Structures
struct room {
char *name;
struct door *doors[4];
int dp; //door count
};
struct door {
char *name;
struct room *room;
};
//Declare Functions
char *readLine(FILE *fin);
readrooms(FILE *fin);
struct door *newDoor(char * name);
struct room *newRoom(char *name);
main(int argc, char const *argv[])
{
FILE *f = fopen("C:\\Users\\s\\Documents\\C\\explore\\rooms.txt", "r");
readrooms(f);
printf("\n----- READ FILE SUCCESSFULLY | Room Count: %d -----\n", rp);
for (int i = 0; i < rp; i++) {
if (rooms[i] != NULL) {
struct room r = *rooms[i];
printf("ROOM %d: %s\n", i, r.name);
}
}
return 0;
}
struct door *newDoor(char * name) {
struct door d;
//TODO: MAKE SURE THIS IS RIGHT
d.name = name;
d.room = NULL;
return &d;
}
struct room *newRoom(char *name) {
struct room r;
r.name = name;
r.dp = 0;
rooms[rp++] = &r;
return &r;
}
char *readLine(FILE *fin) {
char *str = (char *) malloc(sizeof(char) * 3);
char current = fgetc(fin);
int iter = 0;
while (1) {
if (current == '\n') {
str[iter] = '\0';
break;
}
else if (current == EOF) return NULL;
else {
str[iter++] = current;
current = fgetc(fin);
}
}
return str;
}
readrooms(FILE *fin) {
char *curr_room = readLine(fin);
while (curr_room != NULL) {
if (strcmp(curr_room, "*") == 0) {
curr_room = readLine(fin);
continue;
}
struct room r = *newRoom(curr_room);
printf("\n\nReading room %s\n", r.name);
curr_room = readLine(fin);
while (curr_room != NULL && strcmp(curr_room, "*") != 0) {
struct door d = *newDoor(curr_room);
d.room = &r;
r.doors[r.dp++] = &d;
printf("\t%s.doors[%d] = %s\n", r.name, r.dp-1, d.name);
curr_room = readLine(fin);
//printf("Current room is now %s\n\n", curr_room);
}
}
}
Here is the output:
Reading room Hall
Hall.doors[0] = Study
Hall.doors[1] = Cellar
Hall.doors[2] = Kitchen
Reading room Study
Study.doors[0] = Hall
Study.doors[1] = Garden
Reading room Cellar
Cellar.doors[0] = Hall
Reading room Kitchen
Kitchen.doors[0] = Hall
Kitchen.doors[1] = Garden
Reading room Garden
Garden.doors[0] = Study
Garden.doors[1] = Kitchen
----- READ FILE SUCCESSFULLY | Room Count: 5 -----
ROOM 0: ├ïuΣ uαΦ┤■  Y├jhxÖä
ROOM 1: É√o
ROOM 2: É√o
ROOM 3: É√o
ROOM 4: É√o
One problem.
struct room *newRoom(char *name) {
struct room r;
r.name = name;
r.dp = 0;
rooms[rp++] = &r;
return &r;
}
struct room r; is local variable and will be vanished once control exits newRoom function.
Instead what you can do is
struct room *r = malloc(sizeof(struct room));
r->name = name;
r->dp = 0;
rooms[rp++] = r;
In readLine allocate enough memory to read complete line, otherwise you end up accessing out of bound and invoking undefined behavior.
char *readLine(FILE *fin) {
char *str = (char *) malloc(sizeof(char) * 256);
^^^Max line length
...
}
If you don't want to allocate memory blindly realloc is the thing you are looking for.

ATP list in C, reading and saving usernames

I have a problem writing a code that should read usernames and put them in list. Every username should be connected to the number of times it has been entered. The problem occurs when entering the second username, my code places that username in the variable called first (where the first is kept). I guess I've done something wrong with the pointers, but I cannot find what. I am confused, in the end of one while loop the first one is the real first one, and when the program enters while again, variable first changes. How could that be? Please help me.
Thank you :)
typedef struct _user
{
char *name;
int counter;
struct _user *next;
} user;
int main() {
char userName [10];
int found = 0, go_on = 1;
user *first = NULL, *temp, *new;
while (go_on == 1) {
printf ("Username: ");
scanf("%s", userName);
if (first) {
// printf ("The first one in list: %s\n", first->name); - this prints the name of last username entered
for (temp = first; temp; temp = temp->next) {
if (strcmp (temp->name, userName) == 0) {
temp->counter++;
found = 1; }
if (found== 1) break;}
if (!found) {
new = (user*) malloc (sizeof(user));
new->name = userName;
new->counter = 1;
temp = new;
temp->next = NULL; } }
else {
new = (user*) malloc (sizeof(user));
new->name = userName;
new->counter = 1;
first = new;
first->next = NULL; }
printf ("Go on? (1/0)");
scanf("%d", &go_on);
printf ("Current list: ");
for (temp=first; temp; temp = temp->next)
printf("%s %d\n", temp->name, temp->counter);
//printf ("The first one in list: %s\n", first->name); - this prints the correct first
}
}
Your error, I think, is the userName array. You should allocate a new one for each element in your linked list. When you write new->name = userName;, you are not copying the name to the struct, you are making the struct point to your userName[10] array. As such every struct's actual "name" is storing only the single last name scanf-ed. That being said...
I generally prefer to write that kind of code with dedicated tools instead of logically embedding them in a loop construct:
Keeping your struct:
typedef struct _user
{
char *name;
int counter;
struct _user *next;
} user;
I would create a function that, given a properly constructed Sll returns a matching element:
function user *user_match_name(user *user_head, const ch *name)
{
user *cur_user = NULL;
/* look for a match */
for (cur_user = user_head ; cur_user ; cur_user = cur_user->next)
if(!strcmp(name,cur_user->name) return cur_user;
/* no match */
return NULL;
}
Then I usually prefer to have an Sll element builder:
function user *create_user(const ch *name)
{
user *new_user;
if(!(new_user = malloc(sizeof(user))))
printf("Error in allocation"); /* or better malloc error handling */
/* IMPORTANT: PROVIDE MEMORY FOR THE NAMES!!! */
if(!(new_user->name = malloc(sizeof(char)*256))) /* sizeof(char) is useless but I like to explicit it like that. And 256 should be enough a buffer could be better made */
printf("Error in allocation"); /* or better malloc error handling */
strncpy(new_user->name, name,256); /* not sure if I got the argument order right... */
new_user->counter = 0; /* or 1 depending on your prefered convention */
new_user->next = NULL;
return new_user;
}
It ease the debugging like you wouldn't believe! Then it's just a matter of rewriting your main function:
int main() {
char userName [10];
int found = 0, go_on = 1;
user *user_head = NULL, *new_user,*temp;
while (go_on == 1) {
printf ("Username: ");
scanf("%s", userName);
if( (new_user = user_match_name(user_head,userName)) )
++new_user->counter
else
new_user = create_user(userName);
/* Here we push on the Sll */
if(user_head){
new_user->next = user_head;
user_head = new_user;
} else {
user_head = new_user;
}
printf ("Go on? (1/0)");
scanf("%d", &go_on);
printf ("Current list: ");
for (temp = user_head; temp; temp = temp->next)
printf("%s %d\n", temp->name, temp->counter);
//printf ("The first one in list: %s\n", first->name); - this prints the correct first
}
}
Ahhhhhh! Much easier to read. Be mindful of: 1) I didn't compile check the code. The important ideas are there, leverage them. 2) Even in your previous implementation, you are white space vulnerable but that's somewhat another topic.
Or you could cimply fix it by doing:
typedef struct _user
{
char name[10];
int counter;
struct _user *next;
} user;
and strncpy(new->name,userName,10) instead of assigning the pointer.

Resources