Глобальный массив указателей структуры, не хранящих данные - PullRequest
0 голосов
/ 17 января 2019

У меня есть программа на Си, которая пытается представить планировку дома. Он читает в комнатах из текстового файла в следующем формате:

Room
Door
Door
*
Room
Door
Door

Комнаты и двери хранятся в виде структур, и у меня есть глобальный массив указателей для хранения 10 комнат. Я использую метод readrooms() для чтения в комнатах из текстового файла и сохранения их в массиве. Однако после прочтения, когда я пытаюсь напечатать содержимое массива, я получаю строку случайных символов.

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

}

Вот вывод:

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

1 Ответ

0 голосов
/ 17 января 2019

Одна проблема.

struct room *newRoom(char *name) {
    struct room r;

    r.name = name;
    r.dp = 0;

    rooms[rp++] = &r;

    return &r;
}

struct room r; является локальной переменной и исчезнет, ​​когда управление выйдет из функции newRoom.

Вместо этого вы можете

struct room *r = malloc(sizeof(struct room));
r->name = name;
r->dp = 0;

rooms[rp++] = r;

В readLine выделите достаточно памяти для чтения всей строки, в противном случае вы в конечном итоге получите доступ за пределами привязки и вызовете неопределенное поведение.

 char *readLine(FILE *fin) {
    char *str = (char *) malloc(sizeof(char) * 256);
                                                 ^^^Max line length
     ...
  }

Если вы не хотите выделять память вслепую realloc - это то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...