Я использую регулярное выражение 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;
}