l-system01.c

   1  /**
   2  * l-system01.c
   3  *
   4  * @author Luis Alejandro Bernal Romero
   5  *
   6  * Este programa lee un archivo escrito en l-system y lo
   7  * interpreta. Para representar gráficamente la salida puede usar los
   8  * programas xdraw o draw_svg, el primero para xwindow y el otro para
   9  * svga:
  10  *
  11  *  ./l-system01 hilbert.l | ./xdraw
  12  *
  13  * ó
  14  *
  15  *  ./l-system01 hilbert.l | ./draw_svga
  16  *
  17  * Este programa se compila con la siguiente línea de comando:
  18  *
  19  *  gcc -Wall -pedantic -o l-system01 l-system01.c
  20  *
  21  * Por hacer:
  22  *
  23  * - Dar más soporte a otras características de l-system como:
  24  *
  25  *   Sintáxis contextual, las producciones del tipo <a>l<b> -> fzs
  26  *
  27  *   Producciones con probabilidades.
  28  *
  29  *   Otras que no recuerdo. Hay que mirar le libro "The Algorithmic
  30  *   Beauty of Plants" de Przemyslaw Prusinkiewicz y Aritid
  31  *   Lindenmayer.
  32  *
  33  *
  34  */
  35 
  36 #include <stdio.h>
  37 #include <ctype.h>
  38 #include <stdlib.h>
  39 #include <string.h>
  40 
  41 #define MAX_CAD 100
  42 #define MAX_PROD 10
  43 #define MAX_CAD_RESUL 100000
  44 
  45 
  46 struct produccion
  47 {
  48   char par_izq; /* Parte izquierda de la produccion. */
  49   char par_der[MAX_CAD+1]; /* Parte derecha de la produccion. */
  50 };
  51 
  52 int es_numero_entero(char cad[])
  53 {
  54   for(; *cad !='\0'; cad++)
  55     {
  56       if(!isdigit(*cad))
  57         return 0;
  58     }
  59   return 1;
  60 }
  61 
  62 int es_numero_flotante(char cad[])
  63 {
  64   if(!isdigit(*cad))
  65     return 0;
  66   for(; isdigit(*cad); cad++)
  67     ;
  68   if(*cad == '.')
  69     {
  70       cad++;
  71       if(!isdigit(*cad))
  72         return 0;
  73       for(; isdigit(*cad); cad++)
  74         ;
  75     }
  76   if(*cad == 'e' || *cad == 'E')
  77     {
  78       cad++;
  79       if(!isdigit(*cad))
  80         return 0;
  81       for(; isdigit(*cad); cad++)
  82         ;
  83     }
  84   if(*cad != '\0')
  85     return 0;
  86   return 1;
  87 }
  88 
  89 int buscar_prod(struct produccion producciones[], int num_prod, char ch)
  90 {
  91   int i;
  92   
  93   for( i = 0; i < num_prod; i++)
  94     {
  95       if(producciones[i].par_izq == ch)
  96         return i;
  97     }
  98   return -1;
  99 }
 100 
 101 int main(int argc, char *argv[])
 102 {
 103   FILE *fp      = stdin;
 104   char  cad[MAX_CAD + 1], /*  Cadena en la que se lee cada linea de entrada. */
 105     cad_resul[MAX_CAD_RESUL + 1], /*  Cadena resultado. */
 106     cad_resul2[MAX_CAD_RESUL + 1]; /*  Cadena resultado. */
 107   char  *ap1, *ap2, *ap_temp;   /* Apuntadores a las cadenas de
 108                                    resultados, con esto el algoritmo
 109                                    es mas rapido. */
 110   int   num_itera;       /* Numero de iteraciones. */
 111   double        grado; /* Grados en que se dobla.*/
 112   struct produccion producciones[MAX_PROD];  /* Arreglo de estructuras. */
 113   int   num_prod;       /* Contador del numero de producciones. */
 114   int   i;      /* Iteraciones.*/
 115   int   j,              /* Recorre la cadena resultado anterior. */
 116     k;          /* Recorre la cadena resultado actual. */
 117   int   pos_prod;       /* Posicion en la que se encuentra una
 118                            produccion en el arreglo de producciones.*/
 119   
 120   /* Parametros. */
 121   char *nom_prog; /* Nombre del programa. */
 122   int verboso = 0;      /* Indica modo verboso o no. */
 123 
 124   nom_prog = argv[0];
 125   argc--;
 126   argv++;
 127 
 128   /* Procesar opciones. */
 129   for(;argc > 0 && argv[0][0] == '-'; argc--, argv++)
 130     {
 131       switch(argv[0][1])
 132         {
 133         case 'v': verboso = 1;
 134           break;
 135         case 'h': printf("uso: %s [-v] [-h] [archivo]\n", nom_prog);
 136           exit(0);
 137         }
 138     }
 139 
 140   if(argc >= 1)
 141     {
 142       fp = fopen(argv[0], "r");
 143       if(fp == NULL)
 144         {
 145           printf("Error al abrir el archivo \"%s\"\n", argv[0]);
 146           return 1;
 147         }
 148     }
 149 
 150   /* Leer el numero de iteraciones. */
 151   if(!fgets(cad, MAX_CAD, fp))
 152     {
 153       printf("Error: Falta el numero de iteraciones\n");
 154       return 2;
 155     }
 156   cad[strlen(cad)-1] = '\0';
 157   if(!es_numero_entero(cad))
 158     {
 159       printf("Error: Faltan el numero de iteraciones, no es un numero\n");
 160       return 3;
 161     }
 162   num_itera = atoi(cad);
 163 
 164   /* Leer los grados. */
 165   if(!fgets(cad, MAX_CAD, fp))
 166     {
 167       printf("Error: Faltan los grados\n");
 168       return 2;
 169     }
 170   cad[strlen(cad)-1] = '\0';
 171   if(!es_numero_flotante(cad))
 172     {
 173       printf("Error: Faltan los grados, no es un numero\n");
 174       return 3;
 175     }
 176   sscanf(cad, "%lf", &grado);
 177 
 178   /* Leer produccion inicial. */
 179   if(!fgets(cad_resul, MAX_CAD, fp))
 180     {
 181       printf("Error: Falta la produccion inicial\n");
 182       return 2;
 183     }
 184   cad_resul[strlen(cad_resul)-1] = '\0';
 185 
 186   /* Leer las producciones. */
 187   for(num_prod = 0; fgets(cad, MAX_CAD, fp); num_prod++)
 188     {
 189       cad[strlen(cad)-1] = '\0';
 190       producciones[num_prod].par_izq = cad[0];
 191       strcpy(producciones[num_prod].par_der, &cad[3]);
 192       /*                printf("%c->\"%s\"\n", producciones[num_prod].par_izq, producciones[num_prod].par_der); */
 193     }
 194 
 195   /* Reescritura. */
 196   ap1 = cad_resul;
 197   ap2 = cad_resul2;
 198   printf("%f\n", grado);
 199   if(verboso)
 200     {
 201       i = 0;
 202       printf("%2d %s\n", i, cad_resul);
 203     }
 204   for(i = 1; i <= num_itera; i++)
 205     {
 206       if(i >= num_itera && verboso)
 207         printf("%2d ", i);
 208       for(j = 0, k = 0; ap1[j] != '\0'; j++)
 209         {
 210           if((pos_prod = buscar_prod(producciones, num_prod, ap1[j])) >= 0)
 211             {
 212               /*
 213                 printf("%d %c->%s:%d\n",
 214                 pos_prod,
 215                 producciones[pos_prod].par_izq,
 216                 producciones[pos_prod].par_der,
 217                 strlen(producciones[pos_prod].par_der));
 218               */
 219               if( i < num_itera)
 220                 {
 221                   strcpy(&ap2[k], producciones[pos_prod].par_der);
 222                   k += strlen( producciones[pos_prod].par_der);
 223                 }
 224               else
 225                 {
 226                   fputs(producciones[pos_prod].par_der, stdout);
 227                   /*                                    putchar('\n'); */
 228                 }
 229             }
 230           else
 231             {
 232               if( i < num_itera )
 233                 {
 234                   ap2[k] = ap1[j];
 235                   k++;
 236                 }
 237               else putchar(ap1[j]);
 238             }
 239         }
 240       if( i <  num_itera)
 241         ap2[k] = '\0';
 242       else putchar('\n');
 243       
 244       if(verboso && i < num_itera) 
 245         printf("%2d %s\n", i, ap2);
 246 
 247       /* Intercambiar cadenas. */
 248       ap_temp = ap1;
 249       ap1 = ap2;
 250       ap2 = ap_temp;
 251       
 252       /*                printf("%03d %s\n", i, ap1); */
 253     }
 254 
 255   fclose(fp);
 256   return 0;
 257 }

CategoryLenguajeC | CategoryProgramacion

LenguajeC/Programas/l-system/l-system01/l-system01.c (last edited 2008-04-20 14:37:53 by localhost)