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

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);

Related

Remove Items from a struct array

So I'm implementing a TCP server chatroom in C and using poll to handle multiple clients. Users register with a username and password and then Login with it. When they login I want to add them to this struct array.
struct onlineUsers{
int sockfd;
char username[9]; //usernames size is maximum 8 characters
};
struct onlineUsers users[10];
//The login function is pretty long so is here the relevant part.
if(!searchExist(search, db)){
printf("Account doesnt exist.\n");
fclose(db);
free(search);
return -1;
}
else{
printf("Logged in\n");
// Add to onlineUser struct arr[]
}
But when the client closes the connection how would you remove that specific element from the onlineUsers array? I haven't implemented the way to add them since I don't really have a good way to remove them.
I reworked this into a minimal example and implemented a linear search for you (use lfind in remove_user() and lsearch in add_user() if available):
#include <assert.h>
#include <string.h>
#define MAX_NAME 8
#define MAX_USERS 2
struct user {
char name[MAX_NAME + 1];
};
unsigned find_pos(struct user *users, const char *name) {
unsigned empty = MAX_USERS;
for(unsigned i = 0; i < MAX_USERS; i++) {
if(empty == MAX_USERS && !users[i].name[0]) empty = i;
if(!strcmp(users[i].name, name)) return i;
}
return empty;
}
int add_user(struct user *users, const char *name) {
unsigned pos = find_pos(users, name);
if(pos == MAX_USERS) return -1;
if(users[pos].name[0]) return 1;
// safe as name[8] is 0 initialized; otherwise
// copy MAX_NAME + 1 then set name[MAX_NAME] = '\0'
// to ensure string is \0 terminated.
strncpy(users[pos].name, name, MAX_NAME);
return 0;
}
int remove_user(struct user *users, const char *name) {
int pos = find_pos(users, name);
if(!users[pos].name[0] || strcmp(users[pos].name, name)) return 1;
users[pos].name[0] = '\0';
return 0;
}
int main() {
struct user users[MAX_USERS] = { 0 };
assert(add_user(users, "bob") == 0); // ok (1 of 2)
assert(add_user(users, "bob") == 1); // duplicate
assert(remove_user(users, "bob") == 0); // ok (empty)
assert(remove_user(users, "jane") == 1); // non-existing
assert(add_user(users, "bob") == 0); // ok (1 of 2)
assert(add_user(users, "jane") == 0); // ok (2 of 2)
assert(add_user(users, "jack") == -1); // full
assert(remove_user(users, "bob") == 0); // ok
assert(find_pos(users, "jane") == 1); // ok (not empty slot)
}

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.

Moving index of an array and then freeing it

I am reading from a file and then putting it into a struct. While I'm reading the names, I am also checking for duplicate names and then testing to see if their ID's are greater than the other. If it is greater, then I am moving the greater entry ID down to replace it and then freeing the smaller entry ID. However, when I free the smaller entry ID (the one I don't want), it frees both memory locations.
Below I have my GDB tester showing my problem with memory locations more in detail:
89 cards[upd_j - 1] = cards[j];
1: cards[0]->name = 0x55555555a688 "Stolen by the Fae"
2: cards[1]->name = <error: Cannot access memory at address 0x10>
3: cards[2]->name = 0x55555555a898 "Eternal Isolation"
4: cards[3]->name = <error: Cannot access memory at address 0x91>
5: cardsaccum = 2
6: j = 2
7: num_entries = 3
8: upd_j = 2
(gdb) n
91 free(cards[upd_j]->start);
1: cards[0]->name = 0x55555555a688 "Stolen by the Fae"
2: cards[1]->name = 0x55555555a898 "Eternal Isolation"
3: cards[2]->name = 0x55555555a898 "Eternal Isolation"
4: cards[3]->name = <error: Cannot access memory at address 0x91>
5: cardsaccum = 2
6: j = 2
7: num_entries = 3
8: upd_j = 2
(gdb) n
92 free(cards[upd_j]);
1: cards[0]->name = 0x55555555a688 "Stolen by the Fae"
2: cards[1]->name = 0x55555555a898 "\020\220UUUU"
3: cards[2]->name = 0x55555555a898 "\020\220UUUU"
4: cards[3]->name = <error: Cannot access memory at address 0x91>
5: cardsaccum = 2
6: j = 2
7: num_entries = 3
8: upd_j = 2
Here is my struct:
typedef struct card
{
char* start;
unsigned int id;
char* name;
char* cost;
unsigned int converted_cost;
char* type;
char* text;
char* stats;
enum rarity rarity;
} card_t;
Code:
#include "card.h"
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void parser(struct card **cards,int i, char *pointer);
// FUNCTION FOR QSORT()
int cmpname (const void *pa, const void *pb) {
const card_t * const *p1 = pa;
const card_t * const *p2 = pb;
return strcmp((*p1)->name, (*p2)->name);
}
// FOR OUTPUTTING THE RARITY WITH A CHAR
const char *rarities[] = { "common", "uncommon", "rare", "mythic" };
int main(int argc, char **argv) {
int padding;
ssize_t result;
int num_entries = 0;
int i = 0;
int cardsaccum = 0;
int boolean;
FILE *input_file;
if((input_file = fopen(argv[1], "r")))
{
card_t **cards = malloc(sizeof(*cards));
// getline() STORES THE LINE IN BUF
char *buf = NULL;
size_t bufsiz = 0;
// SKIPS HEADER LINE
getline(&buf, &bufsiz, input_file);
// WHILE THE FILE STILL HAS TEXT
while ((result = getline(&buf, &bufsiz, input_file)) != -1)
{
//if (boolean != 1)
//{
num_entries++;
// ALLOCATES MEMORY
cards = realloc(cards, sizeof(*cards) * num_entries);
cards[cardsaccum] = malloc(sizeof(card_t));
//}
boolean = 0;
// STORE CHARACTERS OF BUF IN ARRAY
char *array = strdup(buf);
// MAKE COPY OF ARRAY TO MAKE CHANGES TO
char *stringp = array;
// COPIES MEMORY ADDRESS TO FREE LATER ON
cards[cardsaccum]->start = array;
// SEPERATES FILE WHEN , IS FOUND
cards[cardsaccum]->id = atoi(strsep(&stringp, ","));
stringp++;
cards[cardsaccum]->name = strsep(&stringp, "\"");;
//TESTING FOR DUPLCIATES
for (int j = 0; j < cardsaccum; j++)
{
//CHECK IF CURRENT = PREVIOUS
if (strcmp(cards[cardsaccum]->name, cards[j]->name) == 0)
{
// ID > THAN PREVIOUS?
if(cards[cardsaccum]->id > cards[j]->id)
{
// FREE CARD AT POSITION J
free(cards[j]->start);
free(cards[j]);
cards[j] = NULL;
// GET THE REST OF THE INFO FOR THE CORRECT ENTRY
parser(cards,cardsaccum, stringp);
j++;
int upd_j = j;
// FREEING THE LESSER CARD ID
cards[upd_j - 1] = cards[j];
free(cards[upd_j]->start);
free(cards[upd_j]);
cards[upd_j] = NULL;
// NO NEED TO ACCUM SINCE WE FREED ONE CARD
num_entries--;
}
else
{
free(cards[cardsaccum]->start);
free(cards[cardsaccum]);
cards[cardsaccum] = NULL;
num_entries--;
}
// IF DUPLICATE IS FOUND, SET BOOLEAN TO 1
boolean = 1;
break;
}
}
// IF NOT DUPLICATE
if (boolean != 1)
{
parser(cards,cardsaccum,stringp);
cardsaccum++;
}
}
if(boolean == 1)
{
cards[cardsaccum] = NULL;
}
// QSORT
qsort(cards, cardsaccum, sizeof(*cards), cmpname);
for(i = 0; i < cardsaccum;i++)
{
padding = strlen(cards[i]->name);
padding = 51 - padding;
printf("%-s %*s\n", cards[i]->name, padding, cards[i]->cost);
printf("%-*s %*s\n", 43, cards[i]->type, 8, rarities[cards[i]->rarity]);
printf("----------------------------------------------------\n");
printf("%s \n", cards[i]->text);
printf("----------------------------------------------------\n");
printf("%*s\n", 52, cards[i]->stats);
printf("\n");
}
for(i = 0; i < cardsaccum; i++)
{
free(cards[i]->start);
}
for(i=0; i < cardsaccum ;i++)
{
free(cards[i]);
}
free(buf);
free(cards);
// CLOSING FILE
fclose(input_file);
return 0;
}
else
{
fprintf(stderr, "./parser: cannot open(%s%s%s): No such file or directory\n", "\"", argv[1], "\"");
return 1;
}
}
When you find a duplicate at position j and you want to keep the new card at cardsaccum, you should:
"destroy" (i.e. free all resources of) the card at j;
put the new card into slot j.
You shouldn't do anything to the adjacet cards, so please forget about that little dance that you do with upd_j and j++.
Your code should look like this:
if(cards[cardsaccum]->id > cards[j]->id)
{
// destroy old card
free(cards[j]->start);
free(cards[j]);
// copy current card
cards[j] = cards[cardsaccum];;
// complete parsing current card
parser(cards, j, stringp);
num_entries--;
}
In general, your code is a bit complicated. For example, why have both num_entries and cardsaccum, which are basically the same thing, only that you update them in different places.
As I've already said in comments, I think the following strategy would be easier to implement:
Read all cards, don't care about duplicates.
Sort the cards by name or perhaps by name first, by id second.
Filter out the duplicates, which now are all adjacent.
I also recommend to write a destructor function for your cards, so that you don't have to write
free(cards[j]->start);
free(cards[j]);
all the time. A destructor will come in handy when you add more things you need to free when you destroy the card.

Problems on computing statistics and parsing a text file

a must be simple question but I couldn't manage to do it.
I have to scan on a struct a text file with entries in this format:
{"data1","data2",number1,number2}
And compute first populating a struct.
Text of the exercise:
Consider the definition of the following structure
typedef struct {
char teamHome [30];
char teamHost [30];
int goalSquadraHome;
int goalSquadraOspite;
} match;
which is used to represent the result of a football match.
Write a function that takes as parameters an array of games and its size e
returns a result structure containing the following information:
the number of games won by the home team,
the number of games won by the visiting team,
the number of ties,
the name of the team that has scored the most goals in a match.
Then write a program that, given the array containing all 380 Serie A 2019/2020 matches,
print the information contained in the result.
The code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char squadraCasa[30];
char squadraOspite[30];
int golSquadraCasa;
int golSquadraOspite;
} partita;
typedef struct {
int partite_casa;
int partite_ospite;
int pareggi;
char squad_magg_num_goal[30];
} risultato;
int main(){
FILE *fp;
risultato risultati;
int maxgoal = 0;
risultati.partite_casa = 0;
risultati.partite_ospite = 0;
risultati.pareggi = 0;
partita partite[380];
int i=0;
if((fp = fopen("partiteSerieA1920.txt","rt"))==NULL){
printf("Errore nell'apertura del file\n");
exit(1);
}
while(!feof(fp)){
fscanf(fp,"{\"%s\",\"%s\",%d,%d",partite[i].squadraCasa,partite[i].squadraOspite,partite[i].golSquadraCasa,partite[i].golSquadraOspite);
i++;
}
for(i=0;i<380;i++){
if(partite[i].golSquadraCasa>partite[i].golSquadraOspite){
risultati.partite_casa++;
}else if(partite[i].golSquadraCasa<partite[i].golSquadraOspite){
risultati.partite_ospite++;
}else
risultati.pareggi++;
if(partite[i].golSquadraCasa>maxgoal){
strncpy(partite[i].squadraCasa,risultati.squad_magg_num_goal,30);
maxgoal = partite[i].golSquadraCasa;
}
if(partite[i].golSquadraOspite>maxgoal){
strncpy(partite[i].squadraOspite, risultati.squad_magg_num_goal,30);
maxgoal = partite[i].golSquadraOspite;
}
}
fclose(fp);
printf("%d %d %d %s\n",risultati.partite_casa,risultati.partite_ospite,&risultati.pareggi,&risultati.squad_magg_num_goal);
return 0;
}
Please let me know how to arrange it properly.
There may be other issues, but certainly your flow control is wrong. Instead of the incorrect while/feof loop(Why is “while ( !feof (file) )” always wrong?), try something like:
partita *p = partite;
while( 4 == fscanf(fp, "{\"%29s\",\"%29s\",%d,%d",
p->squadraCasa,
p->squadraOspite,
&p->golSquadraCasa,
&p->golSquadraOspite
) ){
p++;
}
Give this a try, its a bit of a different approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char squadraCasa[30];
char squadraOspite[30];
int golSquadraCasa;
int golSquadraOspite;
} partita;
typedef struct
{
int partite_casa;
int partite_ospite;
int pareggi;
char squad_magg_num_goal[30];
} risultato;
// solves given problem and stores results in risultato struct
risultato *getResult(partita **playedGames, int size)
{
risultato *result = malloc(sizeof(risultato));
result->partite_casa = 0;
result->partite_ospite = 0;
result->pareggi = 0;
int currentHighest = 0;
for (int i = 0; i < size; i++)
{
if (playedGames[i]->golSquadraCasa > playedGames[i]->golSquadraOspite){
result->partite_casa++;
if(playedGames[i]->golSquadraCasa > currentHighest ){
currentHighest = playedGames[i]->golSquadraCasa;
strcpy(result->squad_magg_num_goal, playedGames[i]->squadraCasa);
}
}
else if (playedGames[i]->golSquadraCasa < playedGames[i]->golSquadraOspite){
result->partite_ospite++;
if (playedGames[i]->golSquadraOspite > currentHighest){
currentHighest = playedGames[i]->golSquadraOspite;
strcpy(result->squad_magg_num_goal, playedGames[i]->squadraOspite);
}
}
else{
result->pareggi++;
}
}
return result;
}
// This is a custom parser of a line from the file
// data = {"data1","data2",number1,number2}
// return -> partita struct
partita *newGame(char *data){
partita *partite = malloc(sizeof(partita));
char* temp;
// Get Home Team
temp = strchr(data, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraCasa, data + 2);
data = temp+1;
// Get Away Team
temp = strchr(data+1, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraOspite, data + 2);
data = temp + 1;
// Get Home Score
temp = strchr(data + 1, ',');
temp[0] = '\0';
partite->golSquadraCasa = atoi(data + 1);
data = temp + 1;
// Get Away Score
temp = strchr(data, '}');
temp[0] = '\0';
partite->golSquadraOspite = atoi(data);
// Return game
return partite;
}
int main()
{
FILE *fp;
partita **partite = malloc(sizeof(partita *)); // list of size one, currently...
risultato *risultati;
char linea[50];
int indice = 0;
if ((fp = fopen("./partiteSerieA1920.txt", "rt")) == NULL)
{
printf("Errore nell'apertura del file\n");
exit(1);
}
// For each linea in the file, load a game into an array.
while (fgets(linea, 50,fp))
{
//chomp the \n
linea[strlen(linea)-1]='\0';
// increase size of list
partite = realloc(partite, sizeof(partita *) * (indice + 1));
// insert game into array of games
partite[indice] = newGame(linea);
indice++;
}
risultati = getResult(partite, indice);
// Print risultato
printf("\n----RESULT----\nHome Wins: %d\nAway Wins: %d\nTies: %d\nTeam With Most Goals: %s\n\n", risultati->partite_casa, risultati->partite_ospite, risultati->pareggi, risultati->squad_magg_num_goal);
// free all allocated memory then return
for (int i = 0; i < indice;i++){
free(partite[i]);
}
free(partite);
free(risultati);
fclose(fp);
return 0;
}
I was trying to run your code but couldnt get it to parse data from the file properly so i made a quick parser for you (This is in the code above already):
partita *newGame(char *data){
partita *partite = malloc(sizeof(partita));
char* temp;
// Get Home Team
temp = strchr(data, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraCasa, data + 2);
data = temp+1;
// Get Away Team
temp = strchr(data+1, ',') -1;
temp[0] = '\0';
strcpy(partite->squadraOspite, data + 2);
data = temp + 1;
// Get Home Score
temp = strchr(data + 1, ',');
temp[0] = '\0';
partite->golSquadraCasa = atoi(data + 1);
data = temp + 1;
// Get Away Score
temp = strchr(data, '}');
temp[0] = '\0';
partite->golSquadraOspite = atoi(data);
// Return game
return partite;
}
You can always try to use something similar to this to parse strings or lines that you bring in as I find it is more efficient to just code something that you know works to the specification you want.
Let me know if there is some problem with the code or would like to know more about the functionality of this. I tried to keep as much of this in Italian.
Cheers

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.

Resources