Использование групп захвата регулярных выражений в C для заполнения структуры - PullRequest
0 голосов
/ 06 мая 2020

Я использую регулярное выражение POSIX для анализа файла конфигурации, который выглядит следующим образом:

ROOM NAME: XYZZY
CONNECTION 1: PLOVER
CONNECTION 2: Dungeon
CONNECTION 3: twisty
ROOM TYPE: START_ROOM

1) Мой алгоритм зависит от массива указателей на структуру Room ниже. Я хочу создать экземпляр объекта Room * на основе данных после двоеточий выше. На самом деле, я хочу, если возможно, поместить объект прямо в RoomArray [n]. В любом случае, ниже я создал регулярные выражения вместо strtok (но я полагаю, что меня можно убедить использовать некоторую строковую функцию). Я не могу понять, как набить группу захвата, которая будет называться, например, $ 2 в Perl, что означает данные как таковые.

2) Как можно "разыменовать" массив в Room-> outBound, чтобы "pu sh" СОЕДИНЕНИЕ 1..N в него? Простое выполнение RoomArray [0] -> outBound [0], похоже, не работает.

Вот мой код. Спасибо за понимание!

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h> // malloc
#include <math.h>
#include <time.h>
#include <sys/stat.h>
#include <regex.h>
#include <errno.h>

enum RoomType { START_ROOM, MID_ROOM, END_ROOM, END };

struct Room {
    char* name;
    int type;
    int id;
    int numConnects;
    struct Room* outBound[6];
};

int roomId;
struct Room* RoomArray[7];

/* this function cribbed from https://stackoverflow.com/a/16844977/9727704 */
enum RoomType getRoomType(char * val) {

    static char const * roomTypeArray[] = { "START_ROOM", "MID_ROOM", "END_ROOM" };
    int i;
    for (i = 0; i < END; ++i)
        if (!strcmp(roomTypeArray[i], val))
            return i;
    return END;
}

// slurp in a configfile
int parseFile(char *filename) {

    int rv;
    char buffer[100];
    FILE *fp;

    fp = fopen(filename, "r");

    if (fp == NULL) {
        fprintf(stderr, "Error opening file.");
        exit(1);
    }


    struct Room* RoomArray[roomId];
    struct Room* newRoom;

    /* each room file has three kinds of entries. We compile the regexes
     * for parsing the room files */

    /* the name of the room */
    regex_t name_regex;
    rv = regcomp(&name_regex, "^(ROOM NAME)(: )([a-zA-Z]+)\n$", REG_EXTENDED);
        if (rv) {
        fprintf(stderr, "Could not compile name_regex.\n");
        exit(1);
    }

    /* the names of the connections -- at least 3, less than 7 */
    regex_t conn_regex;
    rv = regcomp(&conn_regex, "^(CONNECTION [0-9])(: )([a-zA-Z]+)\n$", REG_EXTENDED);
        if (rv) {
        fprintf(stderr, "Could not compile conn_regex.\n");
        exit(1);
        }

    /* the kind of room it is */
    regex_t type_regex;
    rv = regcomp(&type_regex, "^(ROOM TYPE: )([a-zA-Z_]+)\n$", REG_EXTENDED);
        if (rv) {
        fprintf(stderr, "Could not compile type_regex.\n");
        exit(1);
        }

    while (fgets(buffer, 100, fp) != NULL ) {

        printf("buffer is %s\n",buffer);
        if (regexec(&name_regex, buffer, 0, NULL, 0) == 0) {
            puts("name match");
            newRoom->name = (char *) malloc(4 * sizeof(char));
            RoomArray[roomId]->name = (char *) malloc(4 * sizeof(char));

            // Cant figure out what to do without making valgrind puke all over my screen!

            //char* str = "foo";    
            //strcpy(RoomArray[roomId]->name,str);
            //strcpy(newRoom->name,"aaa");

        } else if (regexec(&conn_regex, buffer, 0, NULL, 0) == 0) {

            puts("conn match");

            // same here.

        } else if (regexec(&type_regex, buffer, 0, NULL, 0) == 0) {

            // I will use getRoomType() here to fill in Room->id    
            puts("type match");
        }
    }

    fclose(fp);

    /* free the memory */
    regfree(&name_regex);
    regfree(&type_regex);
    regfree(&conn_regex);

    roomId++;

    return 0;   
}


int main() {

    roomId = 0;
    char * filename = "room.txt";

    parseFile(filename);

    return 0;   
}

1 Ответ

1 голос
/ 06 мая 2020

Ваш массив указателей RoomArray разыменовывается перед тем, как указывать на что-то.

RoomArray[roomId]->name

RoomArray [roomId] ни на что не указывает. Вам не хватает чего-то вроде

RoomArray[roomId]=malloc(sizeof(Room));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...