Taller
>> Taller >> Arrays Dinámicos en Fenix by Danko >> Cap. 3, Trabajando con arrays dinámicos.

Vamos a hacer un ejemplo de lo que podría ser una forma para trabajar con arrays dinámicos de enteros cómoda e intuitivamente. Éste método lo uso a modo de ejemplo, pero seguramente se pueden desarrollar métodos más apropiados. Para empezar necesitaremos crear un bloque type:

      type i_array
..........pointer el;     // éste será el puntero donde almacenemos el puntero devuelto por alloc
..........len;     // longitud del array, para poder hacer por ejemplo un for (i=0;i
..........st = 0;     // para controlar si ya se ha reservado memoria para el array
......END

Ahora crearemos unas funciones para trabajar con este tipo de datos que hemos creado.

      PROCESS i_dim(i_array pointer var, int elements);
      BEGIN
          var.el = alloc(elements*4);     // reservamos memoria para los elementos (*4 porque sizeof(int)=4)
          var.len = elements;
          memset(var.el,0,elements*4);     // inicializamos los elementos a 0
      END

Como veis, este proceso no tiene ningún misterio. Hemos tenido que usar un parámetro de tipo i_array pointer para poder pasar las variables de tipo i_array por referencia.

Ahora la rutina para redimensionar:

      PROCESS i_redim(i_array pointer var, int elements);
      BEGIN
          var.el = realloc(elements*4);     // como se ha explicado antes...
          var.len = elements;
      END

Que tampoco tiene nada de especial...

Si queremos evitar algunos errores (por ejemplo que se reserve memoria cuando ya ha sido reservada, o que se redimensione sin haber reservado) haremos uso de la variable st del tipo i_array.

Los procesos quedarían así:

      PROCESS i_dim(i_array pointer var, int elements);
......BEGIN
          IF (!(var.st))     // si var.st==0 (no se ha reservado memoria todavía)
              var.el=alloc(elements*4);
              var.len=elements;
              var.st=1;     // establecemos a 1 el valor de st
          ELSE
              i_redim(var,elements);     // redimensionamos el array (de modo que ahora podemos usar i_dim para redimensionar
          END

          memset(var.el,0,elements*4);     // inicializamos a 0
      END

      PROCESS i_redim(i_array pointer var, int elements);
......BEGIN
          IF (var.st)     // si var.st<>0 (se ha reservado memoria)
              var.el=realloc(var.el,elements*4);
              var.len=elements;
          ELSE     // si no
              i_dim(var,elements);     // reservamos memoria por primera vez
          END

      END

Como ves ahora podemos hacer uso tanto de i_dim como de i_redim para redimensionar el array una vez que ya ha sido creado, sin embargo hay una pequeña diferencia entre un método u otro. Si usamos i_dim para redimensionar también estaremos inicializando todos los valores a 0. Esto se ha hecho así a propósito ya que a veces nos interesará mantener los valores (usaremos i_redim) y otras veces no. Por otro lado, no hay diferencia entre crear el array con i_dim o con i_redim (tan sólo que en operaciones muy, muy largas el segundo sería algo más lento ya que tiene que hacer una comprobación más).

      PROCESS i_erase(i_array pointer var);
......BEGIN
          free(var.el); var.len=0; var.st=0;     // liberamos y "reseteamos" la variable de tipo i_array
      END

Un posible programa de ejemplo utilizando todo esto sería:

      GLOBAL
          i_array mi_array;
      BEGIN
              i_dim(mi_array,4);     // creamos un array de 4 elementos
          mi_array.el[0]=write(0,0,0,0, "Primer elemento del array");
          mi_array.el[1]=write(0,0,10,0, "Segundo elemento del array");
          mi_array.el[2]=write(0,0,20,0, "Tercer elemento del array");
          mi_array.el[3]=write(0,0,30,0, "Cuarto elemento del array");
          REPEAT FRAME; UNTIL(key(_enter))
          borra_textos();
          i_dim(mi_array,2);     // creamos un array de 4 elementos
          mi_array.el[0]=write(0,0,0,0, "He borrado todo el texto");
          mi_array.el[0]=write(0,10,0,0, "sin saber cuanto texto había :D");
          REPEAT FRAME; UNTIL(key(_esc))
          i_erase(mi_array);     // liberamos
      END

      PROCESS borra_textos();
......PRIVATE
          conta;
......BEGIN
          FOR (conta=0;conta
              delete_text(mi_array.el[conta]);
          END

      END

Y esto es todo por ahora. Si quieres puedes implementar las funciones necesarias y el bloque type para trabajar con arrays que no sean de enteros, pero ten en cuenta los bytes que ocupa cada uno (sizeof(word)=2, sizeof(byte)=1,etc). Espero que por lo menos a alguno os haya sido útil, ya sé que no está muy bien explicado pero se hace lo que se puede. Si tienes cualquier duda: amd_danko_k7@terra.es.