Arrays (punteros)
Funciones
ArrPt(type)* | arrpt_create (...) |
ArrPt(type)* | arrpt_copy (...) |
ArrPt(type)* | arrpt_read (...) |
void | arrpt_destroy (...) |
void | arrpt_destopt (...) |
void | arrpt_clear (...) |
void | arrpt_write (...) |
uint32_t | arrpt_size (...) |
type* | arrpt_get (...) |
const type* | arrpt_get_const (...) |
type* | arrpt_first (...) |
const type* | arrpt_first_const (...) |
type* | arrpt_last (...) |
const type* | arrpt_last_const (...) |
type** | arrpt_all (...) |
const type** | arrpt_all_const (...) |
void | arrpt_append (...) |
void | arrpt_prepend (...) |
void | arrpt_insert (...) |
type** | arrpt_insert_n (...) |
void | arrpt_join (...) |
void | arrpt_delete (...) |
void | arrpt_pop (...) |
void | arrpt_sort (...) |
void | arrpt_sort_ex (...) |
uint32_t | arrpt_find (...) |
type* | arrpt_search (...) |
const type* | arrpt_search_const (...) |
type* | arrpt_bsearch (...) |
const type* | arrpt_bsearch_const (...) |
void | arrpt_foreach (...) |
void | arrpt_foreach_const (...) |
void | arrpt_forback (...) |
void | arrpt_forback_const (...) |
void | arrpt_end (void) |
Estos contenedores son una especialización de los array, donde se almacenarán punteros a los objetos y no lo objetos en sí mismos (Figura 1). Aunque, en general, sirve todo lo visto en Arrays hay ciertas particularidades que debemos tener en cuenta:
- Hay que crear y liberar memoria dinámica para cada objeto.
- El acceso puede ser más lento, ya que hay que desreferenciar un puntero por cada elemento.
- Mantener el array (insertar, eliminar, ordenar) puede ser más rápido ya que hay que mover menos memoria, sobre todo en el caso de manejar estructuras grandes o arrays de muchos elementos.
- Se puede alojar el valor
NULL
en cualquier posición. - Es más seguro si otras partes de la aplicación mantienen punteros a los elementos del contenedor.
- Es la única opción para trabajar con objetos opacos.
1. Crear arrays de punteros
- Utiliza arrpt_create para crear un array.
- Utiliza arrpt_destroy para destruir un array y sus elementos.
- Utiliza arrpt_append para añadir un nuevo puntero al array.
- Utiliza DeclPt para declarar tipos de puntero a
struct
.
En (Listado 1) vemos como crear y destruir arrays de punteros de Product
. La principal diferencia con respecto a los arrays de objetos, radica en la gestión de la memoria dinámica de cada elemento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
static void i_destroy(Product **product) { str_destroy(&(*product)->code); str_destroy(&(*product)->desc); image_destroy(&(*product)->image); heap_delete(product, Product); } ArrPt(Product) *products = arrpt_create(Product); Product *prod = heap_new(Product); arrpt_append(products, prod, Product); // Will modify the stored object 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; ... arrpt_destroy(&products, i_destroy, Product); |
2. Copia de arrays de punteros
Utiliza arrpt_copy para copiar un array.
La copia funciona de forma similar que en Copia de arrays, con la diferencia de que debemos reservar dinámicamente espacio para el objeto en sí (Listado 2).
Product
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
static Product *i_copy(const Product *src) { Product *dest = heap_new(Product); 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; return dest; } ArrSt(Product) *nproducts = arrpt_copy(products, i_copy, Product); ... arrpt_destroy(&nproducts, i_destroy, Product); |
arrpt_create ()
Crea un array de punteros vacío.
ArrPt(type)* arrpt_create(type);
type | Tipo de objeto. |
Retorna
El nuevo array.
arrpt_copy ()
Crea una copia de un array de punteros.
ArrPt(type)* arrpt_copy(const ArrPt(type) *array, FPtr_copy func_copy, type);
array | El array original. |
func_copy | Función de copia del objeto. |
type | Tipo de objeto. |
Retorna
La copia del array original.
Observaciones
La función de copia debe crear un objeto dinámico y asignar memoria para los campos internos que lo requieran. Si pasamos NULL
, se realizará una copia de los punteros originales, lo que puede suponer un riesgo de integridad ya que un mismo objeto puede ser destruido dos veces si no ponemos especial cuidado. Ver Copia de arrays de punteros.
arrpt_read ()
Crea un array leyendo su contenido de un Streams (de-serialización).
ArrPt(type)* arrpt_read(Stream *stream, FPtr_read func_read, type);
stream | Un stream de lectura. |
func_read | Constructor para crear un objeto a partir de los datos obtenidos de un stream. |
type | Tipo de objeto. |
Retorna
El array leído.
arrpt_destroy ()
Destruye un array y todos sus elementos.
void arrpt_destroy(ArrPt(type) **array, FPtr_destroy func_destroy, type);
array | El array. Será puesto a |
func_destroy | Función para destruir un elemento del array. Si es |
type | Tipo de objeto. |
arrpt_destopt ()
Destruye un array y todos sus elementos, siempre y cuando el objeto array no sea NULL
.
void arrpt_destopt(ArrSt(type) **array, FPtr_destroy func_destroy, type);
array | El array. |
func_destroy | Ver arrpt_destroy. |
type | Tipo de objeto. |
arrpt_clear ()
Borra el contenido del array, sin destruir el contenedor que quedará con cero elementos.
void arrpt_clear(ArrPt(type) *array, FPtr_destroy func_destroy, type);
array | El array. |
func_destroy | Destructor del elemento. Puede ser |
type | Tipo de objeto. |
arrpt_write ()
Escribe un array en un Streams (serialización).
void arrpt_write(Stream *stream, const ArrPt(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. |
arrpt_size ()
Obtiene el número de elementos en un array.
uint32_t arrpt_size(const ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Número de elementos.
arrpt_get ()
Obtiene un puntero al elemento en la posición pos
.
type* arrpt_get(ArrPt(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.
arrpt_get_const ()
Obtiene un puntero const al elemento en la posición pos
.
const type* arrpt_get_const(const ArrPt(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.
arrpt_first ()
Obtiene un puntero al primer elemento del array.
type* arrpt_first(ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Puntero al elemento.
arrpt_first_const ()
Obtiene un puntero const al primer elemento del array.
const type* arrpt_first_const(const ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Puntero al elemento.
arrpt_last ()
Obtiene un puntero al último elemento del array.
type* arrpt_last(ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Puntero al elemento.
arrpt_last_const ()
Obtiene un puntero const al último elemento del array.
const type* arrpt_last_const(const ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Puntero al elemento.
arrpt_all ()
Obtiene un puntero a la memoria interna del array, que da acceso a todos los elementos.
type** arrpt_all(ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Puntero base. Incrementándolo uno a uno iteraremos sobre los elementos.
Observaciones
Utiliza arrpt_foreach para iterar sobre los elementos de forma más segura y elegante.
arrpt_all_const ()
Obtiene un puntero const a la memoria interna del array, que da acceso a todos los elementos.
const type** arrpt_all_const(const ArrPt(type) *array, type);
array | El array. |
type | Tipo de objeto. |
Retorna
Puntero base. Incrementándolo uno a uno iteraremos sobre los elementos.
Observaciones
Utiliza arrpt_foreach_const para iterar sobre los elementos de forma más segura y elegante.
arrpt_append ()
Añade un puntero al final del array.
void arrpt_append(ArrPt(type) *array, type *value, type);
array | El array. |
value | Puntero al elemento a añadir. |
type | Tipo de objeto. |
arrpt_prepend ()
Inserta un puntero al inicio del array. El resto de elementos serán desplazados a la derecha.
void arrpt_prepend(ArrPt(type) *array, type *value, type);
array | El array. |
value | Puntero al elemento a insertar. |
type | Tipo de objeto. |
arrpt_insert ()
Inserta un puntero en una posición arbitraria del array.
void arrpt_insert(ArrPt(type) *array, const uint32_t pos, type *value, type);
array | El array. |
pos | Posición donde será insertado. El actual elemento en |
value | Puntero al elemento a insertar. |
type | Tipo de objeto. |
arrpt_insert_n ()
Inserta varios punteros en una posición arbitraria del array.
type** arrpt_insert_n(ArrPt(type) *array, const uint32_t pos, const uint32_t n, type);
array | El array. |
pos | Posición donde será insertado el primer elemento. El actual elemento en |
n | Número de elementos a insertar. |
type | Tipo de objeto. |
Retorna
Puntero al primer puntero insertado.
Observaciones
Los punteros insertados serán inicializados a NULL
.
arrpt_join ()
Une dos vectores. Añade todos los elementos de src
al final de dest
.
void arrpt_join(ArrPt(type) *dest, const ArrPt(type) *src, FPtr_copy func_copy, type);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
ArrPt(Product) *products = create_products(...); ArrPt(Product) *new_products = new_products(...); // Join without 'copy' func. Dynamic 'Product' objects will be reused. arrpt_join(products, new_products, NULL, Product); arrpt_destroy(&new_products, NULL, Product); ... arrpt_destroy(&products, i_destroy, Product); // Join with 'copy' func. Dynamic 'Product' objects will be duplicate. arrpt_join(products, new_products, i_copy, Product); arrpt_destroy(&new_products, i_destroy, Product); ... arrpt_destroy(&products, i_destroy, Product); |
dest | El array destino. |
src | El array cuyos elementos serán añadidos a |
func_copy | Función de copia del objeto. |
type | Tipo de objeto. |
Observaciones
La función de copia debe crear memoria dinámica tanto para el objeto como para los campos que lo requieran. Si es NULL
se solo se añadirá una copia del puntero original a dest
.
arrpt_delete ()
Elimina un puntero del array.
void arrpt_delete(ArrPt(type) *array, const uint32_t pos, FPtr_destroy func_destroy, type);
array | El array. |
pos | Posición del elemento a borrar. El actual elemento en |
func_destroy | Destructor del elemento. Puede ser |
type | Tipo de objeto. |
arrpt_pop ()
Elimina el último puntero del array.
void arrpt_pop(ArrPt(type) *array, FPtr_destroy func_destroy, type);
array | El array. |
func_destroy | Destructor del elemento. Puede ser |
type | Tipo de objeto. |
arrpt_sort ()
Ordena los elementos del array utilizando Quicksort.
void arrpt_sort(ArrPt(type) *array, FPtr_compare func_compare, type);
array | El array. |
func_compare | Función para comparar dos elementos. Ordenar y buscar en arrays. |
type | Tipo de objeto. |
arrpt_sort_ex ()
Ordena los elementos del array utilizando Quicksort y datos adicionales.
void arrpt_sort_ex(ArrPt(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. |
arrpt_find ()
Busca un determinado puntero en el array.
uint32_t arrpt_find(const ArrPt(type) *array, type *elem, type);
array | El array. |
elem | Puntero a buscar. |
type | Tipo de objeto. |
Retorna
La posición del puntero si existe, o UINT32_MAX si no.
arrpt_search ()
Busca un elemento en el array de forma lineal O(n)
.
type* arrpt_search(ArrPt(type) *array, FPtr_compare func_compare, 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. Ordenar y buscar en arrays. |
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 |
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.
arrpt_search_const ()
Versión const de arrpt_search.
const type* arrpt_search_const(const ArrPt(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
Elemento.
arrpt_bsearch ()
Busca un elemento en el array de forma logarítmica O(logn)
.
type* arrpt_bsearch(ArrPt(type) *array, FPtr_compare func_compare, 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. Ordenar y buscar en arrays. |
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 |
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.
arrpt_bsearch_const ()
Versión const de arrpt_bsearch.
const type* arrpt_bsearch_const(const ArrPt(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
Elemento.
arrpt_foreach ()
Itera sobre todos los elementos del array. Usa arrpt_end
para cerrar el bucle.
void arrpt_foreach(type *elem, ArrPt(type) *array, type);
1 2 3 |
arrpt_foreach(product, array, Product) bstd_printf("Index:%d, Id:%d\n", product_i, product->id); arrpt_end() |
elem | Nombre de la variable 'elemento' dentro del bucle. Añadiendo el sufijo |
array | El array. |
type | Tipo de objeto. |
arrpt_foreach_const ()
Versión const de arrpt_foreach.
void arrpt_foreach_const(const type *elem, const ArrPt(type) *array, type);
elem | Elemento. |
array | El array. |
type | Tipo de objeto. |
arrpt_forback ()
Itera sobre todos los elementos del array hacia atrás, desde el último al primero. Usa arrpt_end
para cerrar el bucle.
void arrpt_forback(type *elem, ArrPt(type) *array, type);
1 2 3 4 |
// Now in reverse order arrpt_forback(product, array, Product) bstd_printf("Index:%d, Id:%d\n", product_i, product->id); arrpt_end() |
elem | Nombre de la variable 'elemento' dentro del bucle. Añadiendo el sufijo |
array | El array. |
type | Tipo de objeto. |
arrpt_forback_const ()
Versión const
de arrpt_forback.
void arrpt_forback_const(const type *elem, const ArrPt(type) *array, type);
elem | Elemento. |
array | El array. |
type | Tipo de objeto. |
arrpt_end ()
Cierra el bucle abierto por arrpt_foreach, arrpt_foreach_const, arrpt_forback o arrpt_forback_const.
void
arrpt_end(void);