Problema con listas enlazadas.

Iniciado por samur88, 28 Noviembre 2010, 18:26 PM

0 Miembros y 1 Visitante están viendo este tema.

samur88

Hola, tengo el siguiente problema que me trae totalmente loco con el tema de las listas enlazadas en C.

El caso es que tengo el siguiente código:


#include <stdio.h>
#include <stdlib.h>

typedef struct elementslist {
         int data;
         struct elementslist *next;
        }element;

element *first,*nodo,*nodo2;

void insertarnodo(element *nodo, int dato){
                nodo = (element*) malloc(sizeof(element));
                nodo->data = dato;
                nodo->next = NULL;
                first = nodo;
     }

main(){
first = NULL;
insertarnodo(nodo,5);
printf("%d\n",nodo->data);
}


Este código me compila pero cuando lo ejecuto se me cierra y no imprime el valor de la lista.
Luego tengo este otro que si me funciona pero no se si esta mal o bien programado, el caso es que me gustaría saber por que el primero no me funciona y el segundo si, ya que al tratarse de variables globales no tengo por que retornar ningún nodo como en el segundo.


#include <stdio.h>
#include <stdlib.h>

typedef struct elementslist {
         int data;
         struct elementslist *next;
        }element;

element *first,*nodo,*nodo2;

element *insertarnodo(element *nodo, int dato){
                nodo = (element*) malloc(sizeof(element));
                nodo->data = dato;
                nodo->next = NULL;
                first = nodo;
                return nodo;
     }

main(){
first = NULL;
nodo = insertarnodo(nodo,5);
printf("%d\n",nodo->data);
}


Un saludo a todos.

Beakman

El error que salta en el primer código es de fallo de segmentación.
Porque la variable nodo que tenes en la función no es la misma. Cuando haces esto:
Código (c++) [Seleccionar]

void insertarnodo(element *nodo, int dato)

Al nodo que tenes entre paréntesis le estas cargando datos, pero el nodo original sigue conteniendo basura.
tendría que ser asi:
Código (c++) [Seleccionar]

#include <stdio.h>
#include <stdlib.h>

typedef struct elementslist
{
int data;
struct elementslist *next;
}element;

//element *first,*nodo,*nodo2;
element *primero,*nodo;

void insertarnodo(element *nodo_aux, int dato)
{
//nodo = (element*) malloc(sizeof(element));
nodo_aux->data = dato;
nodo_aux->next = NULL;
primero = nodo;
}

int main()
{
primero = NULL;
nodo = (element*) malloc( sizeof( element ) );
insertarnodo(nodo,5);

printf("%d\n",nodo->data);

free(nodo);
return 0;
}


Aca te explica bien ese error, casi al final.

samur88

Muchísimas gracias por la respuesta, ahora ya lo tengo todo claro, era por la localidad de las variables en las funciones de hay que mi segundo codigo funcione y este no, ya que el segundo devolveria un puntero a la zona de declaracion que declare en la función.

Tengo una duda, tanto en el código que me has pasado como en el segundo, no puedo recorrer la lista de la siguiente forma, podrías ayudarme:


ultimo = primero;
while (ultimo->next != NULL){
     printf("%d",ultimo->data);
     ultimo = ultimo->next;
     }

Me compila y me ejecuta pero no me imprime los valores de la lista.
Un saludo y gracias de nuevo.

Beakman

De nada.
No te muestra los valores porque salta otro fallo de segmentación.
Código (c++) [Seleccionar]

element *ultimo = primero;
do
{
printf("\n%d\n",ultimo->data);
ultimo = ultimo->next;
//}while (ultimo->next != NULL); //esto tira fallo de segmentacion
}while (ultimo != NULL );

samur88

Muchas gracias por la respuesta ^^ el codigo que me pusiste funciono a la perfección, pero no veo donde se encuentra el error de segmentación en el que yo puse, puedes explicármelo?
Un saludo.

Beakman

de nada.
si.
En realidad tu código no tira fallo de segmentación, no entra al ciclo directamente:
Código (c++) [Seleccionar]

ultimo = primero;
/*
No entra porque next SI esta apuntando a NULL
*/
while (ultimo->next != NULL)
{
    printf("%d",ultimo->data);
    ultimo = ultimo->next;
}


Lo que quise decir es que si lo pones al revés, para intentar que muestre "algo" por pantalla, asi:
Código (c++) [Seleccionar]

element *ultimo = primero;
do
{
printf("\n%d\n",ultimo->data);
ultimo = ultimo->next;
}while (ultimo->next != NULL);

Ahi si tira un fallo de segmentación porque llega un momento en el que "ultimo" es igual a NULL y vos estás preguntando si "ultimo->next..." cuando "ultimo"  ya no tiene nada, porque es NULL.
No se si se entiende bien.

samur88

Gracias qily, una cosita que no entiendo muy bien, ultimo contendría NULL, eso quiere decir que ultimo-next no existiria, ¿no? sería algo así como que ya que las dos variables de "ultimo" serian Null por lo tanto ultimo-next no estaría.
¿Algo así me quieres decir?
Por cierto, me puedes mandar algún enlace donde expliquen bien todos los fallos de segmentación, es que en la otra pagina me han quedado clara algunas cosas, pero esto de los bucles no muy claras.
Un saludo.

Beakman

Citar
...ultimo contendría NULL, eso quiere decir que ultimo-next no existiria, ¿no? sería algo así como que ya que las dos variables de "ultimo" serian Null por lo tanto ultimo-next no estaría.
¿Algo así me quieres decir?
Claro, como no existe y estas queriendo sacar de donde no hay te tira error.

Los fallos de segmentación aparecen cuando querés entrar a un sector de memoria que no esta permitido o no existe
En wikibooks te dan algunos ejemplos.
Busca mas info de punteros con diferentes cosas, estructuras, objetos, etc. Y proba los codigos.
Y los problemas que tienen otros con los fallos de segmentación.  :)

samur88

Muchas gracias por todo qily, mirare mas ejemplos y preguntare las dudas que tenga en el foro ^.^.
Saludos y gracias de nuevo.

EddyC

Hola que tal , mira te voy a dejar otra manera de cargar la lista la cual se maneja con punteros dobles te dejo las funciones , ami nunca me trajeron problemas , las probas y cualquier duda me decis .



//ESTRUCTURAS :

typedef struct
{ // ingresas la info aca
}t_info ;

typedef struct s_nodo
{t_info data;
struct s_nodo *sig;
}t_nodo;

typedef t_nodo * t_lista   // lo que hago aca es declarar a "T_LISTA" como un t_nodo *

//FUNCIONES

int insertarenlista(t_lista *p,t_info *d)
{t_nodo *nue;
nue=(t_nodo *)malloc(sizeof(t_nodo));
if(!nue)
    return 0;  // sin memoria
nue->sig= *p;
nue->data= *d;
*p = nue;
return 1;     // todo bien
}


int sacardelista(t_lista *p,t_info *d)
{t_lista aux;
if(!p)
return 0;   // si lista vacia devuelve 0
aux=*p;
*d=aux->data;
*p=aux->sig;
free(aux);
return 1;        // todo bien
}