Ver Mensaje Individual
  #9 (permalink)  
Antiguo 15/03/2014, 06:16
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 12 años, 3 meses
Puntos: 83
Respuesta: Lectura de Comandos desde un TXT

Lo que necesitas es un parser, puedes usar alguno que ya exista; puede que puedas adaptar el parser a tu formato, o puede que debas adaptar tu formato al parser. La otra opcion es crear tu propio parser, pero ten en cuenta que puede llegar a ser mas complejo de lo que puedas imaginar :)

Te pongo un ejemplo muy simple que puede ayudarte a seguir con esto. Primero el archivo de comandos:

Código C:
Ver original
  1. Begin
  2. Create(1,2,3,4,5,A)
  3. Delete(0)
  4. Create(6,7,8,9,0,B)
  5. End

Si nos basamos en el archivo lo que harias manualmente sería: identificar el 'Begin' y en 'End', sacar lo que hay enmedio, separar por lineas de comando, y para cada linea de comando indentificar la operacion (en este caso 'Create' o 'Delete'), y para cada operacion evaluar el contenido.

Lo primero es identificar los bloques de acciones. Declaramos una lista global de etiquetas de trabajo:

Código C:
Ver original
  1. enum LTAGS {
  2.     TAG_BEGIN,
  3.     TAG_END,
  4.     TAG_CREATE,
  5.     TAG_DELETE,
  6.     TAG_COUNTER
  7. };
  8. static char *STAGS[TAG_COUNTER] = {
  9.     "Begin",
  10.     "End",
  11.     "Create",
  12.     "Delete"
  13. };
  14. #define TAG_UNDEFINED       -1

Ahora declaramos un flag de estado:

Código C:
Ver original
  1. unsigned char flag_reading_block = 0;

Esto nos indica si estamos dentro de un bloque 'Begin - End', lo inicio a 0 para indicar que no estoy dentro de ningun bloque. Si estamos dentro de un bloque podemos evaluar las acciones, si no pues se omiten o se avisa de un error en el formato (lo que sea). Para el funcionamiento cuando encuentre un comando 'Begin' cambiaré el flag a 1, y cuando encuentre 'End' le asignaré 0, no tiene mas complicacion.

Ahora ya podemos leer el archivo linea por linea:

Código C:
Ver original
  1. FILE *arx;
  2. char line[1024];
  3.  
  4. arx = fopen("test.txt", "r");
  5.  
  6. while(fgets(line, 1023, arx) != NULL) {
  7.     //tengo una linea de comando
  8. }

Ya tengo las lineas, pero debo evaluar que significan. Para eso tengo la lista de etiquetas que defini al principio. Me creo una funcion auxiliar para averiguar que etiqueta corresponde al comando de la linea:

Código C:
Ver original
  1. int get_tag(char *line) {
  2.     int q;
  3.  
  4.     for(q = 0; q < TAG_COUNTER; q++) {
  5.         if(!strncmp(line, STAGS[q], strlen(STAGS[q]))) {
  6.             return q;
  7.         }
  8.     }
  9.  
  10.     return TAG_UNDEFINED;
  11. }

Esta funcion 'get_tag' no hace nada mas que buscar el inicio del comando en la lista de etiquetas. Te repito que esto es un ejemplo simple, y por eso se puede simplificar de esta forma.

En principio segun el funcionamiento de get_tag es necesario trimar los espacios iniciales de la cadena de comandos (espacios, tabuladores, saltos de linea). En el archivo de comandos de ejemplo no tengo ni espacios ni tabuladores, con lo que no me hara falta trimar.

Ahora para cada linea se que operacion debo ejecutar, pues solo tengo que implementar un switch para diferenciar:

Código C:
Ver original
  1. switch(get_tag(line)) {
  2.     case TAG_BEGIN: {
  3.         if(!flag_reading_block) {
  4.             flag_reading_block = 1;
  5.         }
  6.     }
  7.     break;
  8.     case TAG_END: {
  9.         if(flag_reading_block) {
  10.             flag_reading_block = 0;
  11.         }
  12.     }
  13.     break;
  14.     case TAG_CREATE: {
  15.         if(flag_reading_block) {
  16.             exec_create(line);
  17.         }
  18.     }
  19.     break;
  20.     case TAG_DELETE: {
  21.         if(flag_reading_block) {
  22.             exec_delete(line);
  23.         }
  24.     }
  25.     break;
  26. }

No hay ningun misterio en eso, hasta aqui todo ok?

Ahora solo falta implementar la funcion exec_create y exec_delete, y todas las demas funciones para las acciones que quieras soportar. Implemento la de exec_create: sabes que la operacion Create es del tipo 'Create(datos)'. Esto significa que quieres recuperar solo lo que hay entre los parentesis. Haces un sscanf quitando el nombre de la accion y los parentesis y ya tienes los datos:

Código C:
Ver original
  1. void exec_create(char *line) {
  2.     char data[512];
  3.     int q;
  4.     char *pch;
  5.  
  6.     memset(data, 0, sizeof(data));
  7.     if(sscanf(line, "Create(%511[^)]", data) > 0) {
  8.         //ya tengo los datos
  9.     }
  10. }

Ahora en 'data' ya tienes los datos "1,2,3,4,5,A". Lo unico que te falta es tokenizar por comas y añadir al arbol.

Algo parecido harias para el 'Delete' y para las demas acciones que vayas a implementar.

Espero que te sea de ayuda
Saludos
vosk