Ver Mensaje Individual
  #4 (permalink)  
Antiguo 19/10/2012, 15:28
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Cambiar Array de tamaño y contenido

Ok, perdona no habia entendido tu duda;

Tienes que relocalizar la memoria de tu lista para adaptarla al nuevo numero de elementos (es igual añadir elementos que quitarlos), en cualquier caso no mezcles tipos (si tienes una lista de int no esperes relocalizar la memoria con tipos float si quieres conservar los datos antiguos, si quieres olvidarte de ellos y generar una lista nueva no hay problema en relocalizar memoria para diferentes tipos).

Antes de nada ten en cuenta que la declaracion que usas 'float variable[] = {1,2,3};' crea una especie de variable dinamica controlada por la aplicacion, es decir que al finalizar se encarga la aplicacion de eliminar la memoria bloqueada para esa variable. En el caso que te ocupa, ya que vas a relocalizar memoria no te interesa que la aplicacion se encargue de liberarla, asi evitas los memory leaks o como se llame (los s.o. actuales recuperan esa memoria al finalizar el proceso de la aplicacion, pero ya que se hace es mejor hacerlo bien).

Para ello tendras que hacerlo tal como colgué en mi post anterior, con un malloc y una longitud. Aquí entra otra variable que tendras que arrastrarla durante toda la aplicacion: necesitas algo que guarde el numero de elementos (puedes hacerlo hardcoded, pero no es elegante), de forma que deberas comenzar con algo asi:

Código:
    float *arrayFl1, *ptr;
    int elementos, q;
    
    elementos = 6;
    arrayFl1 = malloc(elementos*sizeof(float));
    arrayFl1[0] = 0.172;
    arrayFl1[1] = -0.0717;
    arrayFl1[2] = 0.2285;
    arrayFl1[3] = 0.176;
    arrayFl1[4] = -0.068;
    arrayFl1[5] = 0.228;
    
    ptr = arrayFl1;
Ahora tienes la lista en dos punteros que a efectos finales son completamente identicos, cualquier cosa que modifiques sobre 'arrayFl1' se modificará tambien para 'ptr' y lo mismo del revés, porque realmente ambos son punteros a un mismo bloque de memoria; de forma que segun mi parecer uno de los dos sobra, no tiene ninguna ventaja tener los dos ok?

Ahora viene lo que te interesa, como expandes la lista? Primero declaras una nueva variable donde guardarás el resultado de la relocalizacion de memoria (puedes declararla junto con las otros float* porque será del mismo tipo, luego incrementas el contador de elementos, haces un realloc de la lista (cualquier de los dos punteros sirve como puntero al bloque de memoria) asignando el retorno al nuevo puntero, luego asignas a 'arrayFl1' el nuevo puntero y ya puedes añadir el nuevo elemento, algo asi:

Código:
    //declaras arriba la nueva variable
    float *arrayFl1, *ptr, *mem;

    elementos++;
    mem = realloc(arrayFl1, sizeof(float)*elementos);
    arrayFl1 = mem;
    arrayFl1[elementos-1] = 1.2345;
Ya tienes una lista de 7 elementos. Recuerda que al finalizar tienes que liberar el bloque de memoria con 'free(arrayFl1);'

A lo mejor te estas preguntando por que usar una nueva variable *mem para la relocalizacion si puedes asignar directamente el resultado al puntero antiguo?

Código:
    arrayFl1 = realloc(arrayFl1, sizeof(float)*elementos);
Solo hay un caso en que eso no es bueno hacer, y es como siempre el caso de error: si realloc retorna NULL no podras llamar a free para liberar el bloque de arrayFl1, por eso se asigna a un puntero 'de asistencia' y las comprovaciones de error se hacen sobre ese:

Código:
    if(!(mem = realloc(arrayFl1, sizeof(float)*elementos))) {
        //condicion de error, libera arrayFl1 y finaliza aplicacion
    }
Ten en cuenta que aunque no asignes el nuevo bloque relocalizado al viejo puntero es posible que desde el viejo puedes trabajar con el nuevo como si nada, pero esto solo es una casualidad que se puede dar a causa de la localizacion del nuevo bloque de memoria, pero no es lo normal ni lo correcto, siempre debes reasignar el bloque relocalizado al puntero que estabas usando; cuando se hace la relocalizacion si no se puede ampliar el bloque antiguo, se crea uno de nuevo ampliado y se libera el viejo, por eso solo es necesario un free al final para liberar cualquier relocalizacion que hayas echo.

Y otra cosa, lo mismo se aplica para quitar elementos; pero ten siempre presente que el numero de elmentos por si solo no indica nada, tiene que multiplicarse por el tamaño del tipo que estas usando o de lo contrario podría tener resultados no esperados. Si quieres quitar el ultimo elemento simplemente decrimentas el contador y relocalizas de nuevo, automaticamente el ultimo elemento queda fuera de la lista. Para quitar elementos intermedios primero tendras que usar algun truco o llamalo algoritmo para mover los elementos posteriores al elemento objetivo hasta dejarlos en la posicion de su elemento anterior, de forma que te quedará una ultima posicion eliminable, relocalizas la memoria y ya lo tienes.

Saludos
vosk