domingo, 2 de setiembre de 2007

/punteros por referencia en C/C++



Tanto C++, C#, Java, Delphi estaba olvidada de ciertos detalles de C (los que me vi obligada a refrescar). No es ningun cool trick, pero son esos detalles tontos que pueden llevarnos a depurar un buen rato, sobre todo si no tenemos un buen día o estamos cansados.
Esto es un apunte rápido que se basa en un ejemplo real, concreto, y por ende, espero que sea mas claro, que comento porque son errores (o distracciones) mas comunes de lo que uno pensaría. Quizás escribiéndolo no lo olvide, y quizás para quienes se encuentren enfrentando estos lenguajes, los ayude.

Para el árbol mencionado en este post, debía leer el árbol por niveles y cargar los hermanos que cumplieran cierto criterio.


La función es esta:

Lista* menorHermano(Arbol* arbol)
{
Lista* listaNros = listaVacia();
int cantHijos = arbolCantHijos(arbol);

recorreArbol(arbol,cantHijos,listaNros);

return (listaNros);
}
El cabezal de menorHermano estaba fijo, debía retornar una lista formada por los nodos de los diferentes niveles del arbol.

También estaba fijo el cabezal de la función Lista* listaAgregar(int dato, Lista* cola), es más, de Lista solo tenía el .o, y el .h.
Esa era la única biblioteca de la que disponía y debía usar.

La función listaAgregar realiza un insert front, y es llamada dentro de la función recursiva que recorre el árbol. La función recursiva es:
static void recorreArbol(Arbol* arbol, int cantHijos, Lista* &l)

Mi error estuvo en olvidar en pasar por referencia la Lista: el parámetro l que es el que apunta a la lista formada, o que se va formando en cada llamada recursiva.
Ese olvido provocó que al llamar recursivamente la función, el puntero al primer elemento de la lista, no se actualizara. El puntero al primer elemento de la lista siempre tenía el mismo valor, con el cual se llama a recorrerArbol por primera vez (NULL en mi caso).


Finalizado el recorrido quería leer la lista, y resulta que no tenía elementos, y claro, imposible, las inserciones se 'perdieron', porque el puntero al primer elemento nunca se actualizó.

Para evitar eso, debí pasar el puntero a la lista por referencia, ya que al insertar un elemento en la misma, y por tratarse de un insert front, la dirección del primer nodo cambia inserción tras inserción. Y si el puntero no se pasa por referencia, no se modifica.

En C:
static void recorreArbol(Arbol* arbol, int cantHijos, Lista**l)
Se invoca:
recorreArbol(arbol,cantHijos,&l)

En C++:
static void recorreArbol(Arbol* arbol, int cantHijos, Lista**l)
Se invoca:
recorreArbol(arbol,cantHijos,l)












1 comentario:

Belrion. dijo...

Muchisimas gracias por tu ayuda, estoy haciendo una practica de comando ls recursivo para linux y me fallaba el pasar por referencia el puntero de lista.

Gracias y feliz navidad.