Problema basico con listas en C

Iniciado por HardForo, 13 Abril 2016, 23:23 PM

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

HardForo

Buenas,

   Estoy tratando de recordar algo de C y punteros y tengo un problema demas de basico con listas:  sino la creo primero no me funciona el push()


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

struct Node {
int value;
struct Node* next;
};


Node* new_node(int value){
Node * n = (Node *) malloc(sizeof(Node));
n->value = value;
n->next = NULL;
return n;
}


void print_list(Node* head)
{
Node *prev;

prev =  head;
while (prev)
{
printf("%d\n", prev->value);
prev = prev->next;
}
}


/*
Mock de lista circular
*/
Node* lista_circular()
{
Node *x,*y,*z,*head;

x = new_node(1); head = x;
y = new_node(2); x->next = y;
z = new_node(3); y->next = z;
z->next = x;

return x;
}

/*
Mock de lista lineal
*/
Node* lista_lineal()
{
Node *x,*y,*z;

x = new_node(1);
y = new_node(2); x->next = y;
z = new_node(3); y->next = z;

return x;
}


/////////////////////////////////////////////////////
//
//  OPERACIONES


/*
Cuenta nodos
*/
int count(Node *lista)
{
int c = 0;
Node *e;

e = lista;
while (e){
c++;
e = e->next;
}

return c;
}


/*
Insertar al final de la lista

Solo tiene sentido si la lista es lineal *
*/
void push(Node* lista, int value)
{
Node *e,*prev,*n;
int v;

// camino hasta el final de la lista (poco eficiente, mejor tener puntero al final)
e = lista;
while (e){
prev = e;
e = e->next;
}

// creo nodo
n = new_node(value);

if (lista == NULL)
{
lista = n;
//printf("Elem: %d\n",lista->value);
//printf("Elementos: %d\n",count(lista));
}
else
// inserto al final
prev->next = n;
}


int main() { 


Node *lista = NULL;

//lista = lista_lineal();
push(lista,20);
push(lista,40);

print_list(lista);
printf("Elementos: %d\n",count(lista));
}


Me ayudan ?
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

¿Cómo metes cosas en una caja que no existe?

Tú mismo lo has dicho, hay que crearlo primero.

HardForo

Amigo @ivancea96: 

     Es que al hacer el push() creo un nodo (alloco memoria, seteo el siguiente a NULL, ..)  y luego pregunto si la lista esta vacia (lista == NULL) y si es asi hago que apunte a ese nodo recien creado:

        // creo nodo
n = new_node(value);


if (lista == NULL)
{
// creo la lista
lista = n;
        }


Por eso no entiendo porque no me funciona (en que la estoy embarrando)   :-[
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

Oh, no leí el push.

En ese caso, pon "lista = push(lista, _)". En push retornas la lista nueva en caso de que haya sido creada, así que necesitarás asignarla.

MAFUS

Respuesta rápida:
Los parámetros de una función son una copia local del argumento de llamada.
Respuesta algo menos rápida:
Debes pasar un puntero a lista como argumento de la función.
Te doy media solución:
void push(lista **head, int value);

A partir de aquí me detengo y te invito a pensar porqué debe ser así.

HardForo

#5
@MAFUS: estaba pensando justamente que es que esta pasando por valor y no por referencia pero luego me puse a pensar....... pero si es un puntero o no ?

Voy a probar lo que me dices (que lo habia pensado) pero no entiendo el fundamento.


@ivancea96:
gracias por responder, ni idea que se supone hace (_) pero me da error:

Citarerror: '_' was not declared in this scope
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

El _ era para que pusieras ahí lo que quisieras. El número que le pasas al push. Puse '_' porque no afectaba a la explicación xd

HardForo

#7
@MAFUS:

Bueno...... he reflexionado y entendido lo que me dices (el problema es que intento modificar un puntero en el caso de que no exista la linea pero pasa por valor) pero no logro hacerlo funcionar....  :-(

Serias tan amable de mostrarme como se hace ?  no soy estudiante, ni siquiera soy del area de "sistemas", es solo un hobbie pero me esta sacando chispas.

Gracias desde ya
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

MAFUS

Está un poco modificado pues defino un puntero directamente, pero los argumentos de push y pop esperan un puntero a puntero.

Como pusiste un ejemplo con push supuse que era una pila, así que el ejemplo implementa una pila.


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

typedef struct nodo_t {
    int valor;
    struct nodo_t* siguiente;
} nodo, *pila;

pila nueva_pila() {
    return NULL;
}

void push(pila *l, int n) {
    nodo *nuevo = malloc(sizeof(nodo));
    nuevo->valor = n;
    nuevo->siguiente = *l;
    *l = nuevo;
}

int pop(pila *l, int *dato) {
    int exito = 0;
    *dato = 0;
    nodo* a_borrar;
    if(*l) {
        *dato = (*l)->valor;
        a_borrar = *l;
        *l = (*l)->siguiente;
        free(a_borrar);
        exito = 1;
    }
    return exito;
}
   
int main() {
    pila mi_pila;
    int valor;
    int exito;
   
    mi_pila = nueva_pila();
    push(&mi_pila, 3);
    push(&mi_pila, 5);
    exito = pop(&mi_pila, &valor);
    if(exito) printf("%i\n", valor);
    exito = pop(&mi_pila, &valor);
    if(exito) printf("%i\n", valor);
    exito = pop(&mi_pila, &valor);
    if(exito) printf("%i\n", valor);
   
    return 0;
}

HardForo

@MAFUS:  te agradezco mucho, tus ejemplos son los mejores (ya habia visto otros tuyos con punteros aqui) y me sirven para aprender.

Te puedo consultar que haces aqui ?

typedef struct nodo_t {
    int valor;
    struct nodo_t* siguiente;
} nodo, *pila;


No entiendo la parte en que llamas al struct nodo_t como nodo pero tambien puntero a pila y ni siquiera sabria como buscar eso que haces que no se como se llama  :xD

Tu ejemplo corre perfectamente y lo estoy estudiando en mas detalle.


PD: no estaba implementando una pila pero definí un push en vez de un insertar porque era de las operaciones mas simples posibles para probar con que me podia encontrar ya que habia visto este tema en Pascal pero como que los punteros pasan por referencia.
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *