Pakulu Papito
Pakulu Papito

Reputation: 29

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

Upvotes: 3

Views: 135

Answers (1)

kiran Biradar
kiran Biradar

Reputation: 12732

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.

Upvotes: 2

Related Questions