Son fallos básicos de punteros pero a los que se pierde rápidamente la pista cuándo no se está acostumbrado. Con práctica los irás solucionando.
Tienes razón al escribir
void push(listaPTR listp, int value)
pues necesitas variar la dirección contenida en lista si esta apunta a NULL, pero fallas cuándo escribes
por el hecho de que ahora
e apunta a la dirección de
listp.
*** Dando una vuelta de tuerca al tratamiento de la memoria en C ***
listp debe considerarse una variable local de la función
push por lo que obtener su dirección no hará que apuntes a la lista original sino a una parte de la pila de la función a la que estás.
Lo que debes obtener es el valor que hay guardado en
listp que será la dirección en la que se guarda la lista.
Sé que es complicado dicho así, pero si lo llegas a entender se acabarán los problemas con los punteros. Como regla nemotécnica piensa en que vas a sacar un asterisco a tu puntero. Algo así:
Tu tienes
**listaPTRDentro tienes
*listaComo ves hay que quitarse un asterisco de encima para obtener
*lista.
En el código
haces un puntero a node. Es lo mismo que hacer
ya que
node * es lo mismo que
lista.
Ahora viene cuando sacamos un asterisco
**listaPTR. Para ello, durante la asignación cogemos ese asterisco, lo sacamos de
**listaPTR y lo dejamos a su izquierda. En código queda así:
Ahora los dos objetos son del mismo tipo y se respeta la igualdad.
Bien. Pasemos a los argumentos de llamada de la función
push.
Hemos creado nuestra lista, l, y su tipo es
*lista pero el argumento espera que le entreguemos la dirección de memoria donde se guarda ésta. Otra vez podemos hacer uso de una regla nemotécnica: debemos pensar que queremos incluir un asterisco a esa variable y para ello cogemos y, ni cortos ni perezosos, se lo escribimos a mano con el símbolo & a su izquierda. De hecho & parece como si quisiéramos escribir un asterisco de forma rápida y sin levantar el lápiz del papel.
En código queda así:
Así
*lista con un asterisco más digievoluciona a
**listaPTR.
Tu código funcional quedaría de la siguiente forma:
#include <stdlib.h>
#include <stdio.h>
typedef struct nodo_t {
int value;
struct nodo_t* next;
} node, *lista, **listaPTR;
lista new_node(int value){
node
* n
= (node
*) malloc(sizeof(node
)); n->value = value;
n->next = NULL;
return n;
}
lista new_lista(){
return NULL;
}
void print_list(lista head){
node *prev;
prev = head;
while (prev)
{
prev = prev->next;
}
}
void push(listaPTR list, int value)
{
node *e,*prev,*n;
int v; /* v no se usa */
// camino hasta el final de la list (poco eficiente, mejor tener puntero al final)
e = *list;
while (e){
prev = e;
e = e->next;
}
// creo nodo
n = new_node(value);
if (*list == NULL)
{
*list = n;
//printf("Elem: %d\n",list->value);
//printf("Elementos: %d\n",count(list));
}
else
// inserto al final
prev->next = n;
}
int main() {
lista l = new_lista();
push(&l,20);
push(&l,40);
print_list(l);
}