simongraffe

Lectura etiquetas en una secuencia de texto

May 15th, 2021 (edited)
802
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. struct circBuffer
  7. {
  8.   size_t  maxLen;
  9.   size_t  pos;
  10.   size_t  ini;
  11.   char   *data;
  12. };
  13.  
  14. struct processor
  15. {
  16.   char  *tag;
  17.   char   leftBracket;      // '<';
  18.   char   rightBracket;     // '>';
  19.   char   endOfTag;         // '/';
  20.   bool   tagEnabled;
  21.   struct circBuffer
  22.         *buffer;
  23. };
  24. // allocCircBuffer reserva espacio para un buffer circular
  25. struct circBuffer *allocCircBuffer(size_t maxLen)
  26. {
  27.     struct circBuffer *circBuffer = malloc(sizeof *circBuffer);
  28.  
  29.     circBuffer->data = malloc(sizeof *circBuffer->data * maxLen);
  30.     circBuffer->maxLen = maxLen;
  31.     circBuffer->pos = 0;
  32.     circBuffer->ini = 0;
  33.     return circBuffer;
  34. }
  35.  
  36. // enqueue inserta un nuevo caracter en el buffer circular
  37. void enqueue(struct circBuffer *buf, int c)
  38. {
  39.   // Insertamos el caracter en la posición pos
  40.   // e incrementamos p mod maxLen para que quede dentro del arreglo
  41.   buf->data[buf->pos++] = c;
  42.   buf->pos = buf->pos % buf->maxLen;
  43. }
  44.  
  45. // dequeue elimina un caracter del buffer circular
  46. char dequeue(struct circBuffer *buf)
  47. {
  48.   if ( buf->ini == buf->pos ) // buffer vacío
  49.     return 0;
  50.   else
  51.   {
  52.     // El primer caracter está en la posición min (inicio)
  53.     // incrementamos ini mod maxLen para que quede dentro del arreglo
  54.     char c   = buf->data[buf->ini++];
  55.     buf->ini = buf->ini % buf->maxLen;
  56.     return c;
  57.   }
  58. }
  59.  
  60. // clearQueue "borra" el buffer circular
  61. void clearQueue(struct circBuffer *buf)
  62. {
  63.   // simplemente igualamos el inicio del buffer con
  64.   // la próxima posición por usar
  65.     buf->ini = buf->pos;
  66. }
  67.  
  68. // checkForDisableTag chequea si el tag contiene '/'
  69. bool checkForDisableTag(struct processor *proc)
  70. {
  71.   bool disableTag = false;
  72.   int c;
  73.         // Para saber si es el tag de eliminación (/texto)
  74.     // solo tenemos que revisar si el prox char es '/' (endOfTag)
  75.   if ( (c = getchar() ) != EOF)
  76.     if ( c == proc->endOfTag )
  77.     {
  78.       enqueue(proc->buffer, c);
  79.       disableTag = true;
  80.     }
  81.     else
  82.       // No es '/', devolvemos a la entrada estándar
  83.       // para que el buffer lo lea de nuevo
  84.       ungetc(c, stdin);
  85.  
  86.   return disableTag;
  87. }
  88.  
  89. // checkForValidTag verifica que el texto completo
  90. // del tag está en la entrada
  91. bool checkForValidTag(struct processor *proc)
  92. {
  93.   bool validTag = true;
  94.   int  counter = 0;
  95.   int  c;
  96.   char d;
  97.  
  98.   while ( (d = proc->tag[counter++]) !=0
  99.              &&  (c = getchar()) != EOF )
  100.     // Para saber si el tag es válido
  101.     // lo comparamos con el tag almacenado
  102.   {
  103.     enqueue(proc->buffer, c);
  104.     if ( d != c )
  105.     {
  106.       validTag = false;
  107.       break;
  108.     }
  109.   }
  110.   return validTag;
  111. }
  112.  
  113. // processTag verifica si la entrada tiene el formato del tag
  114. void processTag(struct processor * proc)
  115. {
  116.   // copia en el buffer los caracteres que va leyendo,
  117.   // y si identifica un tag, borra el tag del buffer y
  118.   // cambia el estado del processor
  119.  
  120.   bool disableTag = checkForDisableTag(proc);
  121.   bool validTag = checkForValidTag(proc);
  122.  
  123.   int c;
  124.  
  125.   if ( validTag )
  126.     // el tag es válido, pero tenemos que asegurar
  127.     //  de que cierra con > (rightBracket)
  128.     if ( (c = getchar()) != EOF )
  129.     {
  130.       enqueue(proc->buffer, c);
  131.       if ( c != proc->rightBracket )
  132.         validTag = false;
  133.     }
  134.  
  135.     if ( validTag )
  136.     // el tag es completamente válido, lo borramos del
  137.     // buffer circular
  138.   {
  139.     clearQueue(proc->buffer);
  140.     proc->tagEnabled = disableTag ? false : true;
  141.   }
  142. }
  143.  
  144. // nextChar suministra el siguiente caracter de la entrada
  145. // que cumple con la etiqueta
  146. char nextChar(struct processor * proc)
  147. {
  148.     int c;
  149.  
  150.     if ( (c = dequeue(proc->buffer)) == 0 )
  151.     // No hay nada en el buffer circular,
  152.     // pasamos a leer la entrada estándar
  153.     while ( (c = getchar()) != EOF )
  154.     {
  155.         if ( c == proc->leftBracket )
  156.       // encontramos el inicio de una etiqueta
  157.         {  
  158.         enqueue(proc->buffer, c);
  159.         processTag(proc);
  160.         // En el buffer circular quedan los
  161.         // próximos caracteres por emitir
  162.         if ( (c = dequeue(proc->buffer)) != 0 )
  163.             if ( proc->tagEnabled ) break;
  164.       }
  165.         else
  166.         // no es inicio de etiqueta, texto normal
  167.         if ( proc->tagEnabled ) break;
  168.     }
  169.    
  170.   return c == EOF ? 0: c;
  171. }
  172.  
  173. // allocProcessor reserva espacio para un processor
  174. struct processor *allocProcessor(char leftBracket,
  175.         char endOfTag, char * tag, char rightBracket)
  176. {
  177.  
  178.   struct processor
  179.   *processor              = malloc(sizeof *processor);
  180.   processor->leftBracket  = leftBracket;
  181.   processor->endOfTag     = endOfTag;
  182.   processor->tag          = tag;
  183.   processor->rightBracket = rightBracket;
  184.   processor->tagEnabled   = false;
  185.   // + 3: etiqueta + "</>"
  186.   processor->buffer       = allocCircBuffer(strlen(tag) + 3);
  187.   return processor;
  188. }
  189.  
  190. int main(void)
  191. {
  192.   char c;
  193.     struct processor *processor =
  194.           allocProcessor('<', '/', "texto", '>');
  195.  
  196.     while ( (c = nextChar(processor)) != 0 )
  197.         printf("%c", c);
  198.  
  199.     return 0;
  200. }
  201.  
RAW Paste Data