[C con Clase] duda con lista en C
Steven Davidson
srd4121 en njit.edu
Lun Feb 2 05:20:57 CET 2009
Hola Armando,
Armando B. VERA wrote:
> SOBRE ESTRUCTURAS DINÁMICAS DE DATOS "EDD"
>
> Parte del siguiente codigo lo extraje del material EDD
>
> de www.conclase.net
>
Veamos el código fuente y las preguntas que planteas.
> ----------------------------------------------------------
>
> typedef struct _nodo {
>
> int valor;
>
> struct _nodo *siguiente;
>
> } tipoNodo;
>
> typedef tipoNodo *pNodo;
>
> typedef tipoNodo *Lista;
>
> /* Funciones con listas: */
>
> void Insertar(Lista *l, int v);
>
> /* ¿aquí "Lista *l" es lo mismo que "tipoNodo **l" ? */
>
Sí.
> void Insertar(Lista *lista, int v)
>
> {
>
> pNodo nuevo, anterior;
>
> /* Crear un nodo nuevo */
>
> nuevo = (pNodo)malloc(sizeof(tipoNodo));
>
> nuevo->valor = v;
>
> /* Si la lista está vacía */
>
> if(ListaVacia(*lista) || (*lista)->valor > v) {
>
> /* Añadimos la lista a continuación del nuevo nodo */
>
> nuevo->siguiente = *lista;
>
> /* Ahora, el comienzo de nuestra lista es en nuevo nodo */
>
> *lista = nuevo;
>
> }
>
> else {
>
> /* Buscar el nodo de valor menor a v */
>
> anterior = *lista;
>
> /* la pregunta es porque entonces aquí la asignación "anterior =*lista"
>
> no sería posible ya que una es "tipoNodo *anterior" y la otra es
>
> "tipoNodo **lista"
>
Las declaraciones que comentas son correctas, pero no estamos asignando
un puntero a otro, sino que primeramente accedemos al valor apuntado por
'lista' y luego lo asignamos a 'anterior'. La expresión es la siguiente:
anterior = *lista;
Esto es lo mismo que hacer esto:
anterior = lista[0];
Como puedes ver, accedemos al valor apuntado por 'lista' y por tanto
estamos asignando un valor de tipo 'tipoNodo *' a otro de 'tipoNodo *'.
> */
>
[CORTE]
>
> * --------------------------------------------------------------------
> * Estoy tratando de hacer algo parecido y no encuentro el error.
> * Este es mi codigo
> *
> * --------------------------------------------------------------------
> * /* ************************** palabra.c
> ******************************* */
> *
> * /* La idea es que cada letra sea un nodo y se pueda escribir
> cadenas (palabras) de forma dinámica, sin saber la longitud de la
> misma. */
> *
> * #include <stdio.h>
> * #include <stdlib.h>
> *
> *
> * typedef struct letra{
> * char letra;
> * struct letra *sigLetra;
> * } tipoLetra;
> *
> *
> * typedef tipoLetra *pLetra;
> * typedef tipoLetra *palabra;
> *
> *
> * void insertarLetra(palabra *p, char l);
> *
> * int main() {
> * char c;
> * palabra pal=NULL;
> *
> * while((c=getchar())!='\n' || c!='\0') {
Esta condición debería basarse en && y no en ||.
> * insertarLetra(&pal,c);
> * }
> *
> * while(pal) {
> * printf("%d",pal->letra);
Con esto, muestras el código ASCII de cada "letra". No sé si esto es lo
que quieres hacer.
> * pal=pal->sigLetra;
Esto no es NADA aconsejable. Recuerda que 'pal' es la "cabeza" de la
lista dinámicamente enlazada. Esto significa que es el principal enlace
a todos los nodos y por tanto a toda la memoria dinámicamente
adjudicada. Sin este enlace no podemos liberar la memoria de la lista.
Deberías usar una variable auxiliar. Por ejemplo,
pLetra anterior;
for( anterior = *pal; anterior != NULL; anterior = anterior->sigLetra )
printf( "%d", anterior->letra );
> * }
Tienes que retornar un valor entero para 'main()'. Además, necesitas
liberar la memoria que has ido adjudicando para la lista.
> *
> * }
> *
> * void insertarLetra(palabra *pal, char l){
> * pLetra nueva;
> * pLetra anterior;
> *
> * anterior=*pal; //aquí es la duda
> *
Esto es correcto, pero ten presente que al principio, la lista está
vacía. Por lo tanto, debes tener en cuenta esta condición. De lo
contrario, puedes estar accediendo a 'NULL', que provocaría un error en
tiempo de ejecución.
> * nueva=(pLetra)malloc(sizeof(tipoLetra));
> * nueva->letra=l;
Necesitas asignar un valor para 'nueva->sigLetra'. Como estás asignando
nodos al final de la lista, necesitarás "apuntar a nada"; esto sería,
nueva->sigLetra = NULL;
> *
> * while(anterior->sigLetra!=NULL) {
Esto es correcto, sólo si 'anterior' no es un puntero nulo. Esto
implicaría que la lista está inicialmente vacía. Debes implementar este
caso particular.
> * anterior=anterior->sigLetra;
> * }
> * anterior->sigLetra=nueva;
> * }
> *
Espero haber aclarado las dudas.
Steven
Más información sobre la lista de distribución Cconclase