Tipo de dato abstracto Pila a void V

Tipo de dato abstracto Pila a void V

Con éste artículo vamos a terminar la serie de publicaciones dedicadas a el tipo de dato abstracto pila con punteros a void, es decir, una pila genérica. Haciendo un poco de retrospectiva, comenzamos hace ya algunos días con la descripción de las cabeceras de las funciones y procedimientos en el fichero .h, describimos los constructores, destructores y algunas funciones auxiliares, seguimos con los procedimientos de insertar un elemento en la pila y sacar un elemento de la pila. Y concluimos con el procedimiento para duplicar una pila.

Para los que estén interesados en descargarse completo éste código y usarlo en sus propios desarrollos, en mi repositorio de github, podéis encontrarlo.

Hecha ésta introducción, vamos a pasar a describir el procedimiento que nos ocupa. Como siempre, comenzamos por el código; después lo iré describiendo:

pila p_copy ( pila p ) {
	
	pila b;
	struct p_ele *corr, *nuevo, *corrp;
	
	if ( !*p ) {
		fprintf ( stderr, "p_copy: La pila no existe.\n" );
		exit (1);
	}
	
	 b = p_nueva ( (( struct tpila*)p)->tam );
	 if ( !p_vacia ( p ) ) {
		 nuevo = ( struct p_ele * ) malloc ( sizeof ( struct p_ele ));
		 if ( !nuevo ) {
			fprintf ( stderr, "p_copy: no hay memoria suficiente.\n" );
			exit (1);
		 }
		 nuevo->val  = (void *) malloc ( struct tpila* )p)->tam);
		 if ( !nuevo->val ) {
			fprintf ( stderr, "p_copy: no hay memoria suficiente.\n" );
			exit (1);
		 }
		 
		 memcpy ( nuevo->val, ((struct tpila *)p)->p->val, ((struct tpila *)p)->tam );
		 ((struct tpila *)b)->p = corr = nuevo;
		 corrp = ((struct tpila *)p)->p->sig;
		 
		 while ( corrp ) {
			nuevo = ( struct p_ele* ) malloc ( sizeof ( struct p_ele ));
			if ( !nuevo ){
				fprintf ( stderr, "p_copy: no hay memoria suficiente.\n" );
				exit (1);
			}
			memcpy ( nuevo->val, corrp->val, ((struct tpila* )p)->tam );
			corr = corr->sig =  nuevo;
			corrp = corrp->sig;
		}
		 
		 corrp->sig = NULL;
		 
	 }
		 
	 return b; 
	
	
}

Seguramente ésta será la función más compleja de cuantas hemos visto hasta hora en el tipo de datos abstracto Pila con punteros a void.

Usaremos varias variables auxiliares que nos serán imprescindibles como podemos apreciar en el código. Coomo siempre comenzamos con una precondición: ¿la pila que queremos duplicar está creada?.

En caso afirmativo, las siguientes líneas de código están dedicadas a crear el primer nodo de la pila, comprobar si hay memoria suficiente, reservar memoria para el dato que contendrá éste nodo, realizar la misma comprobación de si hay o no disponible memoria y, por último, utilizar el procedimiento memcpy para copiar el dato que deseamos almacenar.

Hasta ahora parece todo muy sencillo, ¿verdad?. Continuamos.

Las siguientes líneas de código iran añadiendo, a cada vuelta de bucle while, los nodos que quedan de la pila. Se comienza reservando memoria para el nodo -y comprobando con una estructura if si hay memoria disponible-. A continuación se reserva memoria para el dato que queremos almacenar, que como hemos venido haciendo hasta ahora no sabemos cuál es ni cuanta memoria necesita ( este dato lo tenemos almacenado en el parámetro tam ), y actualizamos el valor del dato copiándolo con el procedimiento memcpy.

Nos queda únicamente actualizar los punteros de la estructura. Cuando se ha terminado el ciclo while, simplemente se devuelve la pila duplicada con un return.

No quiero terminar éste artículo poniéndome a disposición de mis lectores para la aclaración de cualquier duda. Tenéis abierta la sección de comentarios, tanto en éste blog como en la página de facebook para que me deis vuestra opinión, hagáis vuestras contribuciones o dejéis código alternativo.

No Comments

Post a Comment