Lucky
Lucky

Reputation: 713

Using regex capture groups in C to populate a struct

I am using POSIX regex to parse a config file that looks like this:

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

1) My algorithm depends on an array of pointers to the Room struct below. I want to instantiate a Room* object based on the data after the colons above. Actually, I want to plop the object directly into RoomArray[n] if possible. Anyways, below I created regexes instead of strtok, (but I suppose I could be convinced to use some string function.) I can't figure out how to stuff the capture group that would be called $2 in Perl for example, meaning the data per se.

2) How can "dereference" the array at Room->outBound in order to "push" the CONNECTION 1..N into it? Just doing RoomArray[0]->outBound[0] doesn't seem to work.

Here is my code. Thanks for any insight!

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

Upvotes: 0

Views: 75

Answers (1)

AndersK
AndersK

Reputation: 36082

Your pointer array RoomArray gets dereferenced before it points to something.

RoomArray[roomId]->name

RoomArray[roomId] is not pointing to anything. You are missing something like

RoomArray[roomId]=malloc(sizeof(Room));

Upvotes: 1

Related Questions