SDK Multiplataforma en C logo

SDK Multiplataforma en C

Arrays

❮ Anterior
Siguiente ❯

Muéstrame tus diagramas de flujo y oculta tus tablas y seguiré desconcertado. Muéstrame tus tablas y, generalmente, no necesitaré tus diagramas, serán obvios. La representación es la esencia de la programación. Frederick P. Brooks, Jr. - The Mythical Man Month.


Funciones

ArrSt(type)*arrst_create (...)
ArrSt(type)*arrst_copy (...)
ArrSt(type)*arrst_read (...)
voidarrst_destroy (...)
voidarrst_destopt (...)
voidarrst_clear (...)
voidarrst_write (...)
uint32_tarrst_size (...)
type*arrst_get (...)
const type*arrst_get_const (...)
type*arrst_first (...)
const type*arrst_first_const (...)
type*arrst_last (...)
const type*arrst_last_const (...)
type*arrst_all (...)
const type*arrst_all_const (...)
type*arrst_new (...)
type*arrst_new0 (...)
type*arrst_new_n (...)
type*arrst_new_n0 (...)
type*arrst_prepend_n (...)
type*arrst_insert_n (...)
type*arrst_insert_n0 (...)
voidarrst_append (...)
voidarrst_prepend (...)
voidarrst_insert (...)
voidarrst_join (...)
voidarrst_delete (...)
voidarrst_pop (...)
voidarrst_sort (...)
voidarrst_sort_ex (...)
type*arrst_search (...)
const type*arrst_search_const (...)
type*arrst_bsearch (...)
const type*arrst_bsearch_const (...)
voidarrst_foreach (...)
voidarrst_foreach_const (...)
voidarrst_forback (...)
voidarrst_forback_const (...)
voidarrst_end (void)

El Array (o Vector) es un contenedor (o colección) de elementos que se almacenan en posiciones contiguas de memoria. Este hecho proporciona un serie de ventajas que hacen que sea la estructura de datos más utilizada y a la que debamos de recurrir en primera instancia. Estas pueden resumirse en:

  • Acceso directo O(1) a los elementos mediante aritmética de punteros, lo que hace innecesario el uso de iteradores o algoritmos para recuperar la información.
  • Uso eficiente de la caché. Cuando un elemento del array se lee, los elementos adyacentes probablemente se cargan en la caché debido a la localización espacial.
  • Muchos algoritmos (búsqueda, ordenamiento, etc.), requieren recorrer o manipular datos de manera secuencial.
  • Menor fragmentación de memoria. Al reservar espacio contiguo, los arrays tienden a causar menos fragmentación en comparación con estructuras que almacenan elementos en ubicaciones dispersas.

El lenguaje C proporciona una implementación elemental de arrays (Listado 1) que atesoran todas las ventajas que acabamos de describir, pero que adolecen de una gran carencia: son estáticos. Es decir, no pueden crecer o contraerse bajo demanda, hay que definir previamente el número de elementos, bien sea de forma estática (en el Stack) o dinámica (en el Heap).

Listado 1: Arrays en C.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
typedef struct _product_t Product;
struct _product_t
{
    type_t type;
    String *code;
    String *desc;
    Image *image;
    real32_t price;
};

// Stack memory
Product sprods[100];

// Heap memory
Product *dprods = heap_new_n(100, Product);
...
// Heap free
heap_delete_n(&dprods, 100, Product);

El tipo ArrSt implementado en NAppGUI es, en esencia, un array de C dinámico más una serie de métodos para manipularlo. Por dinámico entendemos que la estructura ajusta su tamaño a la cantidad real de elementos, conservando la premisa principal de que todos permanezcan juntos en memoria. Cuando se crea un Array, se reserva memoria para unos pocos registros (Figura 1). Posteriormente, podremos añadir nuevos elementos al final (lo típico) o insertarlos en cualquier posición aleatoria en el caso de que ya tengamos datos en el contenedor. En este último caso, el resto de elementos serán desplazados hacia la derecha. En el momento que se supere la cantidad de registros reservados, se duplicará el bloque dinámico interno para dar cabida a las nuevas posiciones. De igual forma es posible eliminar cualquier elemento de la colección, desplazando el resto hacia la izquierda para mantener la coherencia espacial de la estructura. Si el número de items decreciese a la mitad, el bloque de memoria se reducirá. De esta forma, durante el tiempo de vida del contenedor, la memoria se irá ajustando multiplicando o dividiendo por 2 el número de elementos reservados.

Ajuste de una estructura array al número de elementos que tiene almacenados.
Figura 1: Los Array adaptarán su memoria interna al número real de elementos.

1. Crear arrays

En (Listado 2) tenemos un sencillo ejemplo de como crear un array de tipo Product (Figura 2). Al añadir un nuevo elemento mediante arrst_new(), se devolverá un puntero al área de memoria reservada para él. Es muy importante tener en cuenta que el contenido de dicha memoria es indeterminado, por lo que deberemos inicializar todos los campos con valores coherentes. De igual forma, al destruir el array, deberemos proveer de un destructor (i_remove()) para liberar correctamente la memoria que pueda haber reservado nuestro objeto. La memoria que ocupa el objeto en sí es gestionada por el contenedor y no debemos preocuparnos por ella.

Listado 2: Crear y destruir arrays.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
static void i_remove(Product *prod)
{
    str_destroy(&prod->code);
    str_destroy(&prod->desc);
    image_destroy(&prod->image);
}

ArrSt(Product) *products = arrst_create(Product);
Product *prod = arrst_new(products, Product);
prod->type = ekHDD;
prod->code = str_c("GTK-1050");
prod->desc = str_c("Gigabyte GeForce GTX 1050 OC 2Gb GDDR5");
prod->image = load_image("card.png");
prod->price = 573.34;
...
arrst_destroy(&products, i_remove, Product);
Bytes en memoria representando un array de objetos.
Figura 2: Array de objetos tipo Product.

2. Acceso a elementos y recorrido

  • Utiliza arrst_size para obtener el número de elementos.
  • Utiliza arrst_get para obtener un elemento.
  • Utiliza arrst_all para obtener todos los elementos.
  • Utiliza arrst_foreach para recorrer los elementos.

Como hemos comentando al inicio, acceder a un elemento del array no es más que obtener un puntero a su dirección de memoria, calculada a partir de una base y un desplazamiento. Esto nos permite obtener un elemento aleatorio mediante su índice u obtener la dirección inicial (arrst_all) y utilizar la aritmética de punteros para recorrer todos los elementos (Listado 3). Esto es lo que hace la macro arrst_foreach, iterar de una forma más elegante.

Listado 3: Acceso y recorrido de un array.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
uint32_t i, n = arrst_size(products, Product);
for (i = 0; i < n; ++i)
{
    const Product *prod = arrst_get_const(products, i, Product);

    // Do something
    ...
}

const Product *prod = arrst_all_const(products, Product);
for(i = 0; i < n; ++i, ++prod)
{
    // Do something
    ...
}

arrst_foreach(prod, products, Product)
    // Do something
    ...
arrst_end()

// In reverse order
arrst_forback(prod, products, Product)
    // Do something
    ...
arrst_end()

3. Copia de arrays

Utiliza arrst_copy para copiar un array.

En el caso que queremos realizar un copia exacta de un array, deberemos proveer un método de copia que permita inicializar correctamente todos los campos de un objeto a partir de otro ya existente (Listado 4). Realizar una copia exacta del bloque de memoria del objeto original no será seguro en caso que existan campos alojados dinámicamente (String, Image).

Listado 4: Copiando un array Product.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
static void i_copy(Product *dest, const Product *src)
{
    dest->type = src->type;
    dest->code = str_copy(src->code);
    dest->desc = str_copy(src->desc);
    dest->image = image_copy(src->image);
    dest->price = src->price;
}

ArrSt(Product) *nproducts = arrst_copy(products, i_copy, Product);
...
arrst_destroy(&nproducts, i_remove, Product);

4. Serialización de arrays

  • Utiliza arrst_read para leer un array desde un Stream.
  • Utiliza arrst_write para escribir un array a un Stream.

Serializar es transformar un objeto de memoria en un flujo de bytes (Stream) con el fin de enviarlos a cierto destino a través de un canal de salida. De-serializar es el proceso inverso, leer un flujo de bytes desde un canal de entrada y re-crear en memoria el objeto original. En el caso de los arrays la operación se reduce a (de)serializar cada uno de sus elementos, tal como vemos en (Listado 5).

Listado 5: Serialización de un array.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void i_read(Stream *stm, Product *prod)
{
    prod->type = stm_read_enum(stm, type_t);
    prod->code = str_read(stm);
    prod->desc = str_read(stm);
    prod->image = image_read(stm);
    prod->price = stm_read_r32(stm);
}

static void i_write(Stream *stm, const Product *prod)
{
    stm_write_enum(stm, prod->type, type_t);
    str_write(stm, prod->code);
    str_write(stm, prod->desc);
    image_write(stm, prod->image);
    stm_write_r32(stm, prod->price);
}

ArrSt(Product) *products = arrst_read(istream, i_read, Product);
...
arrst_write(ostream, products, i_write, Product);
arrst_destroy(&products, i_remove, Product);

5. Ordenar y buscar en arrays

  • Utiliza arrst_sort para ordenar un array.
  • Utiliza arrst_search para buscar un elemento de forma lineal O(1).
  • Utiliza arrst_bsearch para buscar un elemento de forma binaria O(logn).

La forma habitual de utilizar arrays será ir añadiendo elementos al final mediante arrst_new para después iterar sobre el conjunto. Este orden "natural" será suficiente en la mayoría de casos, pero es posible que necesitemos organizar los elementos siguiendo otro criterio para:

  • Presentar la información ordenada por uno o varios campos de la estructura.
  • Optimizar búsquedas. Para localizar un determinado elemento, no hay más remedio que recorrer todo el array, con coste lineal O(n). Pero podemos resolver la búsqueda en tiempo logarítmico O(logn) si el array está ordenado, incrementando drásticamente el rendimiento especialmente en conjuntos grandes (Figura 3).
  • Ilustración de una búsqueda dicotómica en un conjunto de 1000 elementos.
    Figura 3: En un máximo de 10 pasos encontraremos un elemento entre mil (20 pasos para un millón).

5.1. Comparadores y claves

Ordenar y buscar son dos conceptos muy relacionados donde entran en juego las claves y los comparadores.

  • Clave: Conjunto de campos de un objeto, normalmente solo uno, que lo identifican de forma única dentro de un contenedor (código, id, referencia + talla, etc). Deben ser lo más compactas y rápidas de procesar posible (p.e. número entero mejor que string).
  • Comparador: Función que establece una relación de orden entre dos elementos del mismo tipo comparando sus claves, por ejemplo i_compare() en (Listado 6). Se utilizan para ordenar elementos en contenedores.
  • Comparador de clave: Compara un elemento con una clave, utilizando la misma relación de orden que el comparador de elementos. Se utilizan para buscar, donde solo sería necesario aportar la clave. En (Listado 7) tenemos un ejemplo de búsqueda donde utilizamos una cadena de texto como clave, ya que es suficiente para identificar al objeto.

Listado 6: Ordenar un array mediante un comparador.
1
2
3
4
5
6
static int i_compare(const Product *p1, const Product *p2)
{
    return str_scmp(p1->code, p2->code);
}

arrst_sort(products, i_compare, Product);

En el caso de los arrays, las búsquedas podrán optimizarse mediante arrst_bsearch() si el array ha sido previamente ordenado. Si no estuviese ordenado, no tendremos más remedio que utilizar la búsqueda secuencial arrst_search() mucho más lenta.

Listado 7: Búsqueda de un elemento mediante un comparador de clave.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
static int i_compare_key(const Product *p1, const char_t *key)
{
    return str_cmp(p1->code, key);
}

// Element position
uint32_t pos1, pos2;

// Slow O(n)
Product *prod1 = arrst_search(products, i_compare_key, "G3900", &pos1, Product, char_t);

// Fast O(logn)
Product *prod2 = arrst_bsearch(products, i_compare_key, "G3900", &pos2, Product, char_t);

6. Insertar y eliminar en arrays

Utiliza arrst_insert_n para insertar elementos.

Utiliza arrst_delete para eliminar un elemento.

Utiliza arrst_clear para eliminar todos los elementos.

No suele ser habitual añadir y/o eliminar elementos desde posiciones arbitrarias del array, pero es posible hacerlo si llegase el caso (Listado 8).

Listado 8: Insertar o eliminar elementos.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// New element at 6th position
Product *prod = arrst_insert_n(products, 6, 1, Product);
prod->type = ekHDD;
prod->code = str_c("GTK-1050");
prod->desc = str_c("Gigabyte GeForce GTX 1050 OC 2Gb GDDR5");
prod->image = load_image("card.png");
prod->price = 573.34;

// Remove 8th element
arrst_delete(products, 8, i_remove, Product);

// Remove all (without destroy the array)
arrst_clear(products, i_remove, Product);

7. Declaración de tipos en arrays

  • Utiliza DeclSt para declarar tipos de struct y enum.

Para trabajar correctamente con tipos de usuario, es necesario declarar la macro (DeclSt(Product), DeclSt(type_t)). Esto definirá funciones personalizadas que realizarán comprobación de tipos en tiempo de compilación, lo cual nos ayudará a mantener la corrección de nuestro código (Listado 9). En el caso de los tipos básicos no es necesario realizar esta declaración, como tampoco proveer un destructor, ya que estos tipos básicos no generan memoria dinámica.

Listado 9: Declaración de tipos.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
typedef enum _type_t type_t;
typedef struct _product_t Product;
DeclSt(type_t);
DeclSt(Product);

ArrSt(uint32_t) *ints = arrst_create(uint32_t);
ArrSt(type_t) *types = arrst_create(type_t);
ArrSt(Product) *products = arrst_create(Product);
...
// No destructor required
arrst_destroy(&ints, NULL, uint32_t);
arrst_destroy(&types, NULL, type_t);
// Destructor required
arrst_destroy(&products, i_remove, Product);

8. Limitaciones de arrays

Si bien es cierto que ArrSt es una estructura óptima a nivel de rendimiento y facilidad de uso, existen casos en los que deberemos tener especial cuidado:

  • Objetos opacos: Si la definición del tipo no es pública, el contenedor no puede calcular el espacio necesario para cada elemento, por lo que solo podremos trabajar con punteros a los mismos. Ver Arrays (punteros).
  • Objetos compartidos: Si otras estructuras del modelo mantienen punteros a los elementos del contenedor, tendremos problemas del tipo Segmentation Fault debido al cambio de las direcciones de memoria al reubicar el bloque interno del contenedor (Figura 4). En estos casos, también deberemos utilizar arrays de punteros.
  • Muchas inserciones y borrados: Utilizar arrays puede no ser óptimo en casos que estén constantemente añadiendo o eliminando elementos en posiciones arbitrarias. Cada operación implica mover bloques de memoria presumiblemente grandes para mantener la coherencia espacial del contenedor. Utilizar conjuntos Sets.
  • Error de violación de segmento al reubicar el bloque de memoria que almacena el array.
    Figura 4: Peligro al mantener punteros a los elementos del array.
❮ Anterior
Siguiente ❯

arrst_create ()

Crea un array vacío.

ArrSt(type)*
arrst_create(type);
type

Tipo de objeto.

Retorna

El nuevo array.

Observaciones

Ver Crear arrays.


arrst_copy ()

Crea una copia de un array.

ArrSt(type)*
arrst_copy(const ArrSt(type) *array,
           FPtr_scopy func_copy,
           type);
array

El array original.

func_copy

Función que debe copiar los campos de cada objeto.

type

Tipo de objeto.

Retorna

La copia del array original.

Observaciones

La función de copia debe asignar memoria a los campos que lo requieran, pero NO al objeto en sí mismo. Si pasamos NULL, se realizará una copia byte a byte del objeto original, lo que puede suponer un riesgo de integridad si los elementos del array contienen objetos String o de otro tipo que necesiten memoria dinámica. Ver Copia de arrays.


arrst_read ()

Crea un array leyendo su contenido de un Streams.

ArrSt(type)*
arrst_read(Stream *stream,
           FPtr_read_init func_read,
           type);
stream

Un stream de lectura.

func_read

Función para inicializar un objeto a partir de los datos obtenidos de un stream. Esta función no debe reservar memoria para el propio objeto (el contenedor ya lo hace).

type

Tipo de objeto.

Retorna

El array leído.

Observaciones

Ver Serialización de arrays.


arrst_destroy ()

Destruye un array y todos sus elementos.

void
arrst_destroy(ArrSt(type) **array,
              FPtr_remove func_remove,
              type);
array

El array. Será puesto a NULL tras la destrucción.

func_remove

Función que debe liberar la memoria asociada a los campos del objeto, pero no el objeto en si mismo. Si es NULL se liberará solo el array y no el contenido interno de los elementos.

type

Tipo de objeto.

Observaciones

Ver Crear arrays.


arrst_destopt ()

Destruye un array y todos sus elementos, siempre y cuando el objeto array no sea NULL.

void
arrst_destopt(ArrSt(type) **array,
              FPtr_remove func_remove,
              type);
array

El array.

func_remove

Ver arrst_destroy.

type

Tipo de objeto.


arrst_clear ()

Borra el contenido del array, sin destruir el contenedor que quedará con cero elementos.

void
arrst_clear(ArrSt(type) *array,
            FPtr_remove func_remove,
            type);
array

El array.

func_remove

Función 'remove'. Ver arrst_destroy.

type

Tipo de objeto.


arrst_write ()

Escribe un array en un Streams.

void
arrst_write(Stream *stream,
            const ArrSt(type) *array,
            FPtr_write func_write,
            type);
stream

Un stream de escritura.

array

El array.

func_write

Función que escribe el contenido de un elemento en un stream.

type

Tipo de objeto.

Observaciones

Ver Serialización de arrays.


arrst_size ()

Obtiene el número de elementos en un array.

uint32_t
arrst_size(const ArrSt(type) *array,
           type);
array

El array.

type

Tipo de objeto.

Retorna

Número de elementos.


arrst_get ()

Obtiene un puntero al elemento en la posición pos.

type*
arrst_get(ArrSt(type) *array,
          const uint32_t pos,
          type);
array

El array.

pos

Posición o índice del elemento.

type

Tipo de objeto.

Retorna

Puntero al elemento.


arrst_get_const ()

Obtiene un puntero const al elemento en la posición pos.

const type*
arrst_get_const(const ArrSt(type) *array,
                const uint32_t pos,
                type);
array

El array.

pos

Posición o índice del elemento.

type

Tipo de objeto.

Retorna

Puntero al elemento.


arrst_first ()

Obtiene un puntero al primer elemento del array.

type*
arrst_first(ArrSt(type) *array,
            type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero al elemento.


arrst_first_const ()

Obtiene un puntero const al primer elemento del array.

const type*
arrst_first_const(const ArrSt(type) *array,
                  type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero al elemento.


arrst_last ()

Obtiene un puntero al último elemento del array.

type*
arrst_last(ArrSt(type) *array,
           type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero al elemento.


arrst_last_const ()

Obtiene un puntero const al último elemento del array.

const type*
arrst_last_const(const ArrSt(type) *array,
                 type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero al elemento.


arrst_all ()

Obtiene un puntero a la memoria interna del array, que da acceso directo a todos los elementos.

type*
arrst_all(ArrSt(type) *array,
          type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero base. Incrementándolo uno a uno iteraremos sobre los elementos.

Observaciones

Utiliza arrst_foreach para iterar sobre los elementos de forma más segura y elegante.


arrst_all_const ()

Obtiene un puntero const a la memoria interna del array, que da acceso directo a todos los elementos.

const type*
arrst_all_const(const ArrSt(type) *array,
                type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero base. Incrementándolo uno a uno iteraremos sobre los elementos.

Observaciones

Utiliza arrst_foreach_const para iterar sobre los elementos de forma más segura y elegante.


arrst_new ()

Reserva espacio para un elemento al final del array.

type*
arrst_new(ArrSt(type) *array,
          type);
1
2
3
// arrst_new avoids the copy
Product *product = arrst_new(array, Product);
i_init_product(product, ...);
array

El array.

type

Tipo de objeto.

Retorna

Puntero al elemento añadido.

Observaciones

Es ligeramente más rápido que arrst_append, especialmente con elementos grandes, ya que evita copiar el contenido del objeto. El contenido inicial de la memoria es indeterminado.


arrst_new0 ()

Reserva espacio para un elemento al final del array y lo inicializa a 0.

type*
arrst_new0(ArrSt(type) *array,
           type);
array

El array.

type

Tipo de objeto.

Retorna

Puntero al elemento añadido.

Observaciones

Igual que arrst_new pero inicializando toda la memoria a 0.


arrst_new_n ()

Reserva espacio para varios elementos al final del array.

type*
arrst_new_n(ArrSt(type) *array,
            const uint32_t n,
            type);
array

El array.

n

Número de elementos a añadir.

type

Tipo de objeto.

Retorna

Puntero al primer elemento añadido.

Observaciones

Igual que arrst_new pero reservando varios elementos en la misma llamada. El contenido inicial de la memoria es indeterminado.


arrst_new_n0 ()

Reserva espacio para varios elementos al final del array, e inicializa la memoria a 0.

type*
arrst_new_n0(ArrSt(type) *array,
             const uint32_t n,
             type);
array

El array.

n

Número de elementos a añadir.

type

Tipo de objeto.

Retorna

Puntero al primer elemento añadido.

Observaciones

Igual que arrst_new_n pero pero inicializando toda la memoria a 0.


arrst_prepend_n ()

Reserva espacio para varios elemento al principio del array. El resto de elementos serán desplazados a la derecha.

type*
arrst_prepend_n(ArrSt(type) *array,
                const uint32_t n,
                type);
array

El array.

n

Número de elementos a insertar.

type

Tipo de objeto.

Retorna

Puntero al primer elemento insertado.

Observaciones

El contenido inicial de la memoria es indeterminado.


arrst_insert_n ()

Reserva espacio para varios elementos en una posición arbitraria del array.

type*
arrst_insert_n(ArrSt(type) *array,
               const uint32_t pos,
               const uint32_t n,
               type);
array

El array.

pos

Posición donde será insertado. El actual elemento en pos y siguientes serán desplazados a la derecha.

n

Número de elementos a insertar.

type

Tipo de objeto.

Retorna

Puntero al primer elemento insertado.

Observaciones

El contenido inicial de la memoria es indeterminado.


arrst_insert_n0 ()

Reserva espacio para varios elementos en una posición arbitraria del array, e inicializa la memoria a 0.

type*
arrst_insert_n0(ArrSt(type) *array,
                const uint32_t pos,
                const uint32_t n,
                type);
array

El array.

pos

Posición donde será insertado. El actual elemento en pos y siguientes serán desplazados a la derecha.

n

Número de elementos a insertar.

type

Tipo de objeto.

Retorna

Puntero al primer elemento insertado.

Observaciones

Igual que arrst_insert_n pero pero inicializando toda la memoria a 0.


arrst_append ()

Añade un elemento al final del array.

void
arrst_append(ArrSt(type) *array,
             type value,
             type);
array

El array.

value

Elemento a añadir.

type

Tipo de objeto.

Observaciones

Utilizar arrst_new si es posible.


arrst_prepend ()

Inserta un elemento al inicio del array. El resto de elementos serán desplazados a la derecha.

void
arrst_prepend(ArrSt(type) *array,
              type value,
              type);
array

El array.

value

Elemento a insertar.

type

Tipo de objeto.

Observaciones

Utilizar arrst_prepend_n si es posible.


arrst_insert ()

Inserta un elemento en una posición arbitraria del array.

void
arrst_insert(ArrSt(type) *array,
             const uint32_t pos,
             type value,
             type);
array

El array.

pos

Posición donde será insertado. El actual elemento en pos y siguientes serán desplazados a la derecha.

value

Elemento a insertar.

type

Tipo de objeto.

Observaciones

Utilizar arrst_insert_n si es posible.


arrst_join ()

Une dos vectores. Añade todos los elementos de src al final de dest.

void
arrst_join(ArrSt(type) *dest,
           const ArrSt(type) *src,
           FPtr_scopy func_copy,
           type);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ArrSt(Product) *products = create_products(...);
ArrSt(Product) *new_products = new_products(...);

// Join without 'copy' func. Dynamic 'Product' fields will be reused.
arrst_join(products, new_products, NULL, Product);
arrst_destroy(&new_products, NULL, Product);
...
arrst_destroy(&products, i_remove, Product);

// Join with 'copy' func. Dynamic 'Product' fields will be duplicate.
arrst_join(products, new_products, i_copy, Product);
arrst_destroy(&new_products, i_remove, Product);
...
arrst_destroy(&products, i_remove, Product);
dest

El array destino.

src

El array cuyos elementos serán añadidos a dest.

func_copy

Función de copia del objeto.

type

Tipo de objeto.

Observaciones

La función de copia debe crear memoria dinámica para los campos que lo requieran, pero NO para el objeto en sí mismo. Ver arrst_copy. Si es NULL se realizará una copia byte a byte del elemento.


arrst_delete ()

Elimina un elemento del array.

void
arrst_delete(ArrSt(type) *array,
             const uint32_t pos,
             FPtr_remove func_remove,
             type);
array

El array.

pos

Posición del elemento a borrar. El actual elemento en pos+1 y siguientes serán desplazados a la izquierda.

func_remove

Función 'remove'. Ver arrst_destroy.

type

Tipo de objeto.


arrst_pop ()

Elimina el último elemento del array.

void
arrst_pop(ArrSt(type) *array,
          FPtr_remove func_remove,
          type);
array

El array.

func_remove

Función 'remove'. Ver arrst_destroy.

type

Tipo de objeto.


arrst_sort ()

Ordena los elementos del array utilizando Quicksort.

void
arrst_sort(ArrSt(type) *array,
           FPtr_compare func_compare,
           type);
array

El array.

func_compare

Función para comparar dos elementos.

type

Tipo de objeto.

Observaciones

Ver Ordenar y buscar en arrays.


arrst_sort_ex ()

Ordena los elementos del array utilizando Quicksort y datos adicionales.

void
arrst_sort_ex(ArrSt(type) *array,
              FPtr_compare_ex func_compare,
              type,
              dtype);
array

El array.

func_compare

Función para comparar dos elementos utilizando un dato adicional.

type

Tipo de objeto.

dtype

Tipo de dato en la función de comparación.

Observaciones

Ver Ordenar y buscar en arrays.


arrst_search ()

Busca un elemento en el array de forma lineal O(n).

type*
arrst_search(ArrSt(type) *array,
             FPtr_compare func_compare,
             const ktype *key,
             uint32_t *pos,
             type,
             ktype);
array

El array.

func_compare

Función de comparación. El primer parámetro es el elemento, el segundo la clave de búsqueda.

key

Clave a buscar. Puntero a un tipo de dato que puede ser diferente al tipo de elemento del array.

pos

Posición del elemento en el array (si existe), o UINT32_MAX si no existe. Puede ser NULL.

type

Tipo de objeto.

ktype

Tipo de clave.

Retorna

Puntero al primer elemento que coincida con el criterio de búsqueda o NULL si no existe ninguno.

Observaciones

Ver Ordenar y buscar en arrays.


arrst_search_const ()

Versión const de arrst_search.

const type*
arrst_search_const(const ArrSt(type) *array,
                   FPtr_compare func_compare,
                   const ktype *key,
                   uint32_t *pos,
                   type,
                   ktype);
array

El array.

func_compare

Función de comparación.

key

Clave a buscar. Puntero a un tipo de dato que puede ser diferente al tipo de elemento del array.

pos

Posición del elemento en el array.

type

Tipo de objeto.

ktype

Tipo de clave.

Retorna

Puntero al elemento.


arrst_bsearch ()

Busca un elemento en el array de forma logarítmica O(logn).

type*
arrst_bsearch(ArrSt(type) *array,
              FPtr_compare func_compare,
              const ktype *key,
              uint32_t *pos,
              type,
              ktype);
array

El array.

func_compare

Función de comparación. El primer parámetro es el elemento, el segundo la clave de búsqueda.

key

Clave a buscar. Puntero a un tipo de dato que puede ser diferente al tipo de elemento del array.

pos

Posición del elemento en el array (si existe), o posición que debería ocupar si no existe. Puede ser NULL.

type

Tipo de objeto.

ktype

Tipo de clave.

Retorna

Puntero al primer elemento que coincida con el criterio de búsqueda o NULL si no existe ninguno.

Observaciones

El array debe estar ordenado según el mismo criterio que la búsqueda. De no ser así el resultado es impredecible. Ver Ordenar y buscar en arrays.


arrst_bsearch_const ()

Versión const de arrst_bsearch.

const type*
arrst_bsearch_const(const ArrSt(type) *array,
                    FPtr_compare func_compare,
                    const ktype *key,
                    uint32_t *pos,
                    type,
                    ktype);
array

El array.

func_compare

Función de comparación.

key

Clave a buscar.

pos

Posición del elemento en el array.

type

Tipo de objeto.

ktype

Tipo de clave.

Retorna

Puntero al elemento.


arrst_foreach ()

Itera sobre todos los elementos del array. Usa arrst_end para cerrar el bucle.

void
arrst_foreach(type *elem,
              ArrSt(type) *array,
              type);
1
2
3
arrst_foreach(product, array, Product)
    bstd_printf("Index:%d, Id:%d\n", product_i, product->id);
arrst_end()
elem

Nombre de la variable 'elemento' dentro del bucle. Añadiendo el sufijo '_i' obtenemos el índice.

array

El array.

type

Tipo de objeto.


arrst_foreach_const ()

Versión const de arrst_foreach.

void
arrst_foreach_const(const type *elem,
                    const ArrSt(type) *array,
                    type);
elem

Elemento.

array

El array.

type

Tipo de objeto.


arrst_forback ()

Itera sobre todos los elementos del array hacia atrás, desde el último al primero. Usa arrst_end para cerrar el bucle.

void
arrst_forback(type *elem,
              ArrSt(type) *array,
              type);
1
2
3
4
// Now in reverse order
arrst_forback(product, array, Product)
    bstd_printf("Index:%d, Id:%d\n", product_i, product->id);
arrst_end()
elem

Nombre de la variable 'elemento' dentro del bucle. Añadiendo el sufijo '_i' obtenemos el índice.

array

El array.

type

Tipo de objeto.


arrst_forback_const ()

Versión const de arrst_forback.

void
arrst_forback_const(const type *elem,
                    const ArrSt(type) *array,
                    type);
elem

Elemento.

array

El array.

type

Tipo de objeto.


arrst_end ()

Cierra el bucle abierto por arrst_foreach, arrst_foreach_const, arrst_forback o arrst_forback_const.

void
arrst_end(void);
❮ Anterior
Siguiente ❯