Reputation: 713
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
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