Problemas con punteros a clases (C++)

Agrupa todas las consultas sobre los lenguajes de programacion como C, C++, Python, Java ...

Problemas con punteros a clases (C++)

Notapor endaramiz » Mar Ene 20, 2009 5:55 pm

Como C++ lo que más problemas me da, por ahora, son los punteros a clases, memoria dinámica... He decidido intentar hacer un programa para practicar. Lo que intenta hacer es que cada vez que introduces un número, crea un nodo que lo pone al final de una lista. Y los saca por pantalla cuando introduces algo que no sea un int.
El problema que tengo creo que está en la función "inicia". Es como si no hiciese nada. Lo que tengo entendido que hace esta función, es crear una clase en la dirección de memoria que le señala el puntero ¿no? pero al salir de la función es como si no hubiese hecho nada. Se supone que si trabaja en una dirección de memoria, si que se queda guardado ¿no? :S
El caso es que solo pasa con esa función. si lo inicio en el main directamente, no hay ningún problema.
Código: Seleccionar todo
#include <iostream>
using namespace std;

class nodo {
    public:
        nodo() {
            siguiente = NULL;
        }
        int valor;
        nodo *siguiente;
};

void inicia(nodo *n, int x) {
    n = new nodo();
    n->valor = x;
    cerr << "c0:" << n->valor;
}

void apilar(nodo *n, int x) {
    if (n == NULL) inicia(n, x);
    else {
        nodo *i;
        i = n;
        while (i->siguiente) i = i->siguiente;
        nodo *aux;
        aux = new nodo();
        aux->valor = x;
        i->siguiente = aux;
    }
    cerr << "c1:" << n->valor;
}

void elimina(nodo *n) {
    nodo *i;
    i = n;
    while (i) {
        nodo *aux;
        aux = i;
        i = i->siguiente;
        delete aux;
    }
}

void escribe(nodo *n) {
    cout << endl;
    nodo *i;
    i = n;
    while (i) {
        cout << i->valor << ' ';
        i = i->siguiente;
    }
    cout << endl;
}

int main() {
    nodo *lista;
    lista = NULL;

    //lista = new nodo(); se se descomenta esto,
    //lista->valor = 5; funciona bien.
   
    int n;
    while (cin >> n) {
        apilar(lista, n);
        cerr << "c2:" << lista->valor;
    }
   
    escribe(lista);
    elimina(lista);
}


¿Mis suposiciones son ciertas? ¿Por qué falla?

Me he ido guiando con un documento de la web c con clase pero no quiero complicarme tanto.

Saludos y gracias de antemano.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor Juan Carlos » Vie Ene 23, 2009 3:37 am

Hola, la funcion "apilar" funciona casi bien. El problema es que tu funcion espera como parametro un "puntero a nodo" y desde la funcion main se llama a dicha funcion y se le pasa como argumento un "puntero a nodo".

Pero cual es el problema?

Los lenguajes como C o C++ pasa por los parametros "por valor", o sea que hacen una copia de los parametros. De esta manera, el puntero "lista" que hay en la funcion main, es copiado y luego es usado en la funcion "apilar".

La solucion?

Una opcion es trabajar con "punteros a punteros a nodos", sin embargo la sintaxis se vuelve bastante confusa.

He aqui el codigo

Código: Seleccionar todo
#include <iostream>
using namespace std;

class nodo {
    public:
        nodo() {
            siguiente = NULL;
        }
        int valor;
        nodo *siguiente;
};

void inicia(nodo **n, int x) {
    *n = new nodo();
    (*n)->valor = x;
    cerr << "c0:" << (*n)->valor;
}

void apilar(nodo **n, int x) {
    if (*n == NULL) inicia(n, x);
    else {
        nodo **i;
        i = n;
        while ((*i)->siguiente) i = &(*i)->siguiente;
        nodo *aux;
        aux = new nodo();
        aux->valor = x;
        (*i)->siguiente = aux;
    }
    cerr << "c1:" << (*n)->valor;
}

void elimina(nodo *n) {
    nodo *i;
    i = n;
    while (i) {
        nodo *aux;
        aux = i;
        i = i->siguiente;
        delete aux;
    }
}

void escribe(nodo *n) {
    cout << endl;
    nodo *i;
    i = n;
    while (i) {
        cout << i->valor << ' ';
        i = i->siguiente;
    }
    cout << endl;
}

int main() {
    nodo *lista;
    lista = NULL;

    //lista = new nodo(); se se descomenta esto,
    //lista->valor = 5; funciona bien.

    int n;

    while (cin >> n) {
        apilar(&lista, n);
        cerr << "c2:" << lista->valor;

    }

    escribe(lista);
    elimina(lista);

}


Las funciones "escribe" y "elimina" no las he observado detenidamente asi que no se si funcionan correctamente.

Saludos

Nota: los punteros siempre dan problemas, te recomiendo el libro de Bruce Eckel, Thinking in C++. Muy buen libro, disponible en internet de forma gratuita.
Juan Carlos
 
Mensajes: 97
Registrado: Sab Jul 07, 2007 1:05 pm

Notapor endaramiz » Vie Ene 23, 2009 8:08 pm

Gracias! si se que queda todo un poco más confuso, pero creo que he entendido el ejemplo y su funcionamiento. Le echaré un vistazo al libro para profundizar más en el tema.

Igualmente esto es para practicar y aprender. En "la vida real" lo haría de otra forma. Por ejemplo, metiendo las funciones en una clase que es lo que hace en el tutorial.

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona


Volver a Sobre lenguajes de programación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado