La generación de estructuras de datos mediante el análisis de archivos de texto plano

StackOverflow https://stackoverflow.com/questions/799558

  •  18-09-2019
  •  | 
  •  

Pregunta

escribí un analizador de archivos para un juego que estoy escribiendo para hacer más fácil para mí para cambiar varios aspectos del juego (cosas como los datos de caracteres / etapa / colisión). Por ejemplo, podría tener una clase de caracteres como esto:

class Character
{
public:
    int x, y; // Character's location
    Character* teammate;
}

configuro mi analizador para leer desde un archivo de la estructura de datos con la sintaxis similar a C ++

Character Sidekick
{
    X = 12
    Y = 0
}

Character AwesomeDude
{
    X = 10
    Y = 50
    Teammate = Sidekick
}

Esto creará dos estructuras de datos y ponerlos en un map<std::string, Character*>, donde la cadena de clave es el nombre que se lo di (en este caso Sidekick y AwesomeDude). Cuando mi intérprete ve un puntero a una clase, al igual que el puntero compañero de equipo, es lo suficientemente inteligente como para buscar en el mapa para buscar el puntero a la estructura de datos. El problema es que no se puede declarar compañero de equipo de Sidekick ser AwesomeDude porque no se ha colocado en el mapa de caracteres todavía.

Estoy tratando de encontrar la mejor manera de resolver esto para que yo pueda tener mis objetos de referencia estructuras de datos que todavía no se han añadido al mapa. Las dos soluciones fáciles que se me ocurren son: (a) añadir la posibilidad de reenviar declaran estructuras de datos o (b) tenga el analizador leer el archivo dos veces, una para rellenar el mapa con punteros a estructuras de datos vacíos y una segunda vez para ir a través y rellenarlos.

El problema con (a) es que yo también puedo decidir qué constructor para llamar a una clase, y si me declaro adelante algo que me tiene que tener el constructor sea aparte del resto de los datos, lo que podría ser confuso . El problema con (b) es que puede ser que quiera declarar Sidekick y AwesomeDude en sus propios archivos. Tendría que hacer mi analizador sea capaz de tomar una lista de archivos para leer en lugar de sólo uno a la vez (esto no es tan malo, supongo, aunque a veces puede ser que quiera obtener una lista de archivos para leer desde una archivo). (B) también tiene el inconveniente de no ser capaz de utilizar estructuras de datos declarados más tarde en el mismo constructor, pero no creo que eso es un gran problema.

¿Por dónde suena como un mejor enfoque? ¿Hay una tercera opción que no he pensado? Parece que debe haber alguna solución inteligente para esto con referencias de puntero o de unión o algo ...: - / supongo que esto es algo subjetivo sobre la base de cuáles son las características que quiero dar a mí mismo, pero cualquier entrada es bienvenido.

¿Fue útil?

Solución

Cuando se encuentre con la referencia de la primera vez, sólo tiene que guardar como referencia. A continuación, puede poner el carácter, o la referencia, o lo que sea en una lista de "referencias que necesitan ser resueltos más adelante".

Cuando el archivo se hace, correr a través de los que tienen referencias y resolverlos.

Otros consejos

Bueno, que pidió una tercera opción. Usted no tiene que utilizar XML, pero si usted sigue la siguiente estructura, sería muy sencillo de utilizar un analizador SAX para construir su estructura de datos.

En cualquier caso, en lugar de hacer referencia a un compañero de equipo, cada personaje hace referencia a un equipo (equipo azul en este caso). Esto desacoplar el problema de referencia circular. Sólo asegúrese de que la lista de los equipos antes de los caracteres.

<team>Blue</team>

<character>
    <name>Sidekick</name>
    <X>12</X>
    <Y>0</Y>
    <teamref>Blue</teamref>
</character>

<character>
    <name>Sidekick</name>
    <X>10</X>
    <Y>50</Y>
    <teamref>Blue</teamref>
</character>

En lo personal, me gustaría ir con b). Dividir el código en clases analizador y el validador, a la vez funcionando en la misma estructura de datos. El analizador leer y analizar un archivo, llenando la estructura de datos y el almacenamiento de cualquier referencia de objeto como sus nombres textuales, dejando el puntero nulo real en su estructura por ahora.

Cuando haya terminado de cargar los archivos, utilice la clase de validación para validar y resolver todas las referencias, rellenando los punteros "reales". Usted tendrá que considerar cómo estructurar sus datos para hacer estas búsquedas agradable y rápido.

Will dijo exactamente lo que iba a escribir. Hemos de tener una lista o algo con las referencias sin resolver.

Y no se olvide de un error si hay referencias sin resolver, una vez que termine de leer el archivo = P

En lugar de almacenar objetos de carácter en su mapa, almacenar un indicador de carácter. El proxy contendrá de un puntero al objeto carácter real cuando se carga el objeto. El tipo de caracteres :: compañero de equipo será cambiado a este tipo de proxy. Cuando se lee en una referencia que no está ya en su mapa, se crea un proxy y utiliza el proxy. Cuando se carga un carácter que ya tiene un proxy de vacío en el mapa, llenarla con tu personaje recién cargada. También es posible que desee agregar un contador para realizar un seguimiento de la cantidad de proxy de vacío que tiene en el mapa, para saber cuándo se han cargado todos los caracteres de referencia.

Otra capa de indirección .... siempre facilitar la programación y más lento.

Una opción sería la de invertir la obligación. El mapa es responsable de llenar en la referencia

template<T> class SymbolMap // I never could rememeber C++ template syntax
{
   ...

   /// fill in target with thing name
   /// if no name yet, add it to the list of thing that will be name
   void Set(T& target, std::string name);

   /// define name as target
   /// go back and fill in anything that needs to be name
   void Define(T target, std::string name);

   /// make sure everything is resolved
   ~SymbolMap()
}

que no va a interactuar bien con valor / semántica en movimiento pero sospecho que no hay mucha voluntad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top