#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h> // por el size_t
#include <string.h>
#define CAP 100
#define SIN_MEM 0
#define DUPLICADO 2
#define TODO_OK 1
typedef struct
{
void * vec;
size_t cap; // seria la capacidad del vector
size_t tamElem;
int ce;
} vector;
typedef int (*Cmp)(const void*, const void *);
typedef void (*Accion)(void*);
bool crearVector(vector *v, size_t tamElem, size_t cap)
{
v-> vec = (void*) malloc( cap*tamElem); // se castea a void xq ya mi vector es de cualquier tipo , y tamElem es el tipo de dato
if(!v->vec) //pl->vec == NULL
return false;
v->ce=0;
v->cap = cap;
v->tamElem = tamElem;
return true;
}
void destruirVector(vector *v)
{
free(v->vec);
}
bool redimensionar(vector *v, size_t nuevacap)
{
void *nVec;
nVec = realloc(v->vec,nuevacap*v->tamElem); //tamElem es el tipo de dato
//recordar que realloc amplia en posiciones cercanas
// si no puede busca un nuevo espacio y por eso devuelve un puntero a la nueva posicion y por eso hacemos que devuelva a v->vec
if(!nVec)
return false;
v->vec = nVec;
v->cap = nuevacap;
return true;
}
//int vectorInsertarEnOrden( vector *pv, int elem, int (*cmp)(const void*, const void*)) se puede escribir asi la funcion o
int vectorInsertarEnOrden( vector *v, void* elem, Cmp cmp)
{
if(v->ce==v->cap)
{
if(!redimensionar(v,v->cap*2))
return SIN_MEM;
}
void*ult = v->vec + (v->ce-1)*v->tamElem; // como ya no es entero debo multiplicar x tamElem
void*i = v->vec;
while(i<=ult && cmp(elem,i)>0) // si no esta ordenado uso !=0 si esta ordenado uso >0
{
i+=v->tamElem; // avanzo de elemento
}
if(i < ult && cmp(elem,i)==0)
return DUPLICADO;
// yo puedo usar memmove para desplazar todos los elementos que necesite a la derecha.
// debo saber la cantidad de bytes a desplzar y la cantidad de elementos
// xq no uso memcpy y si memmove? Xq memmove copia todo a un buffer
// en el caso de memcpy yo se que no hay solapamiento por eso no usamos memmove. En este caso como estoy desplazando
// y hay solapamiento si o si necesito memmove
// memmove(dest,origen, tamaño) va a mover todos dependiendo el tam ( que es desde el ult hasta ini que quedo apuntando a
//la pos a insertar)
memmove(i+v->tamElem,i,ult-i+v->tamElem); // estoy moviendo todos los elementos
// si quiero mover elemento por elemento puedo hacer el for de antes
//for(void * j = ult ; j>=i; j-= v->tamElem)
// memcpy(j+v->tamElem; j; v->tam);
memcpy(i,elem,v->tamElem); // destino,orig, tamaño de bytes , el el elemento a insertar
v->ce++;
return TODO_OK;
}
bool vectorEliminarOrd(vector*v, void* elem, Cmp cmp)
{
void*ult = v->vec + (v->ce-1)*v->tamElem; // como ya no es entero debo multiplicar x tamElem
void*i = v->vec;
while(i<=ult && cmp(elem,i)>0) // si no esta ordenado uso !=0 si esta ordenado uso >0
{
i+=v->tamElem; // avanzo de elemento
}
if(i>ult || cmp(elem,i)<0) // pregunto si no lo encontre
return false;
// si llego aca es xq existia, entonces lo borro
memcpy(elem,i,v->tamElem); // copio xq puede ser que sea una estructura que busco algun dato
memmove(i,i+v->tamElem,ult-i+v->tamElem); // desplazo todos los elementos
v->ce--;
if(v->cap>=v->ce*4 ) // si esta menos de 1/4 del vector cargado lo reduzco a la mitad
redimensionar(v,v->cap/2); // es ideal que los umbrales sean distintos xq si pongo que sean iguales, voy a tener problemas ( luz con sensor de luz)
return true;
}
void vectorRecorrer(const vector *v, Accion accion)
{
void*ult = v->vec + (v->ce-1)*v->tamElem;
for(void*i= v->vec; i<=ult; i+=v->tamElem)
accion(i);
}
int vectorInsertarAlFinal( vector * v, const void * elem)
{
if( v->ce == v->cap)
{
if(!redimensionar(v,v->cap*2))
return SIN_MEM;
}
void * posIns = v->vec + v->ce*v->tamElem;
memcpy(posIns, elem, v->tamElem);
v->ce++;
return TODO_OK;
}
void mostrarEntero(void* ent)
{
printf("\n%d",*(int*)ent);
}
void mostrarFlotante(void* flo)
{
printf("\n%f",*(float*)flo);
}
bool vectorBuscarOrdenado( const vector *v, void* elem, Cmp cmp) // mando solo el elemento que voy a buscar, si yo busco por legajo no mando toda la estrcutura sino solo el legajo
{
void*ult = v->vec + (v->ce-1)*v->tamElem; // como ya no es entero debo multiplicar x tamElem
void*i = v->vec;
while(i<=ult && cmp(elem,i)>0) // si no esta ordenado uso !=0 si esta ordenado uso >0
{
i+=v->tamElem; // avanzo de elemento
}
if(i>ult || cmp(elem,i)<0) // pregunto si no lo encontre
return false;
memcpy(elem,i,v->tamElem); // devuelvo todos los datos del vector.
return true;
}
void * buscarMenor( void* ini, void *fin, size_t tamElem, Cmp cmp)
{
void *m = ini;
for(void*j=ini + tamElem; j<=fin; j+=tamElem)
{
if(cmp(j,m)<0)
m=j;
}
return m;
}
void intercambiarGen(void* a, void*b, size_t tamElem)
{
void*aTemp = malloc(tamElem);
memcpy(aTemp,a,tamElem);
memcpy(a,b,tamElem);
memcpy(b,aTemp,tamElem);
free(aTemp);
}
void vectorOrdenar(vector *v, Cmp cmp) // Ordenamiento por seleccion
{
void *ult = v->vec +(v->ce-1)*v->tamElem;
void *m;
for(void*i=v->vec; i<ult; i+=v->tamElem)
{
m = buscarMenor(i,ult,v->tamElem,cmp);
intercambiarGen(m,i,v->tamElem);
}
}
int cmpEntero(const void *a,const void*b)
{
// const int * int1 = a;
// const int * int2 = b;
//return *int1 - *int2;
return (*(int*)a) - (*(int*)b);
}
int cmpFlotante(const void *a,const void*b)
{
return (*(float*)a) - (*(float*)b);
}
int main ()
{
// los punteros a funcion son como enlaces dinamicos, no esta definido al momento de la compilacion a que funciones saltar, en cambio en una funcion si se sabe
vector v;
float var =2.3;
void * a = &var;
crearVector(&v,sizeof(float),8); // como no estamos en poo es obligatorio crearlo
vectorInsertarEnOrden(&v, a,cmpFlotante); // no va a insertar al final y luego ordenar. Va insertando en orden. Debo tener la lista ordenada.
var=1.4;
vectorInsertarEnOrden(&v, a,cmpFlotante);// vectorInsertarEnOrden(&v, 1);
var=9.4;
vectorInsertarEnOrden(&v, a,cmpFlotante);
var=7.3;
vectorInsertarEnOrden(&v, a,cmpFlotante);
vectorRecorrer(&v,mostrarFlotante);
var = 10.3;
vectorInsertarAlFinal(&v,a);
var = 7.3;
vectorEliminarOrd(&v,a,cmpFlotante);
printf("\n");
vectorRecorrer(&v,mostrarFlotante);
destruirVector(&v);
return 1;
}