Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Listas enlazadas en C.

Estas en el tema de Listas enlazadas en C. en el foro de C/C++ en Foros del Web. Hace un par de días vengo dando lista enlazadas en clase, justo después de haber acabado estructuras de datos. La verdad es que el concepto ...
  #1 (permalink)  
Antiguo 20/05/2006, 04:20
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Listas enlazadas en C.

Hace un par de días vengo dando lista enlazadas en clase, justo después de haber acabado estructuras de datos. La verdad es que el concepto lo entiendo y he logrado hacer una lista enlazada bastante simple que funciona. A pesar de haberlo conseguido tengo una duda, para que sirve "->"? Por ejemplo p->clave = i; Creo saber que es una forma de asignar valores pero mi profesora ha empezado a utilizarlo sin explicarnos qué es y para qué se usa. Aquí les dejo el programilla simple.

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


struct lista
{
int clave;
struct lista *sig;
};

void recorrer(struct lista *L, int *suma);

void main()
{
struct lista *L;
struct lista *p;
int i;
int suma;
L = NULL; /* Crea una lista vacia */

for (i=3;i>=1;i--)
{
/* Reserva memoria para un nodo */
p = (struct lista *) malloc(sizeof(struct lista));
p->clave = i;

p->sig = L;
L = p;
}
suma=0;
recorrer(L, &suma);
getchar();
}

void recorrer(struct lista *L, int *suma)
{
if (L != NULL)
{
printf("%d, ", L->clave);
*suma = *suma + L->clave;
recorrer(L->sig, suma);
}
}

Espero que alguien pueda aclararme mi duda de novato en esto de C. Un saludo.
  #2 (permalink)  
Antiguo 20/05/2006, 13:55
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años, 8 meses
Puntos: 2
El operador -> es un operador de acceso a mienbros de una estructura u objeto apuntado por un puntero.


Ejemplo:

typedef struct _Datos
{
int dato;
}Datos;

Datos valor = {10};
Dato *ref = &valor;

para acceder a un miembro de una estructura comunmente hacemos:

valor.dato = 01;

esto esta bien, pero si queremos hacerlo desde un puntero;

no podemos hacer ref.dato = 20;

por que ref no es una estructura es un puntero, primero tenemor que desrreferenciar:

(*ref).dato = 20;

como vez esto no luce nada bien, y ademas no es nada practico, es por eso que en estos casos se usa el operador de acceso por puntero "->".

ref->dato = 20;

eso es basicamente todo, con clases funciona de igualforma tanto con propiedades y funciones miembro.

Saludos
  #3 (permalink)  
Antiguo 20/05/2006, 14:53
Avatar de TolaWare
Colaborador
 
Fecha de Ingreso: julio-2005
Mensajes: 4.352
Antigüedad: 19 años, 5 meses
Puntos: 24
en forma resumida

hacer esto: p->valor = 3
es equivalente a hacer esto: (*p).valor=3

Saludos
__________________
http://blog.tolaware.com.ar -> Blog de Java, Ruby y Linux
  #4 (permalink)  
Antiguo 20/05/2006, 19:18
arm
 
Fecha de Ingreso: mayo-2006
Mensajes: 112
Antigüedad: 18 años, 7 meses
Puntos: 0
solo estas accediendo al miembro clave del la estructura lista, luego que accedes le asignas un valor.
__________________
-> La duda adecuada es un buen comienzo <-
  #5 (permalink)  
Antiguo 21/05/2006, 03:58
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Si me lo hubiera explicado así mi profesora lo habría visto claro mucho antes. Muchas gracias por resolverme un nueva duda.
  #6 (permalink)  
Antiguo 21/05/2006, 12:58
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años, 1 mes
Puntos: 52
Jajajaja. otra forma.
Si tienes una puntero a estructura y alojas memoria puedes usar:
p[0].dat=0;

Y si alojas memoria para varias puedes irle haciendo
p[1]....
p[2]....
y asi

pero si solo quieres saber el valor de la estructura apuntada directamente pues entonces si p->

Espero que te sirva.
Saludos
  #7 (permalink)  
Antiguo 21/05/2006, 13:55
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
La verdad es que me sirve todo lo de este foro... Entre mis dudas concretas que me resuelven y con mirar dudas de los demás usuarios y problemas que plantean se aprende mucho. Gracias
  #8 (permalink)  
Antiguo 22/05/2006, 12:08
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Volviendo de nuevo al mismo programa expuesto arriba, pero en este caso en vez de usar la funcion de forma recursiva para mostrar los elementos de la lista, el siguiente programa si recursividad. Qué diferencia habría entre éste programa:

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

struct lista
{
int clave;
struct lista *sig;
};



void main()
{
struct lista *L;
struct lista *p;
int i;
int suma;
L = NULL; /* Crea una lista vacia */

for (i=3;i>=1;i--)
{
/* Reserva memoria para un nodo */
p = (struct lista *) malloc(sizeof(struct lista));
p->clave = i; /* Introduce la informacion */

p->sig = L; /* reorganiza */
L = p; /* los enlaces */
}
p = L;
while (p != NULL)
{
printf("%d, ", p->clave);
suma = suma + p->clave;
p = p->sig;
}
getchar();
return;
}

y este otro programa que es exactamente el mismo pero sin declarar suma y sin la instrucción suma = suma + p->clave; ?

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

struct lista
{
int clave;
struct lista *sig;
};



void main()
{
struct lista *L;
struct lista *p;
int i;
L = NULL; /* Crea una lista vacia */

for (i=3;i>=1;i--)
{
/* Reserva memoria para un nodo */
p = (struct lista *) malloc(sizeof(struct lista));
p->clave = i; /* Introduce la informacion */

p->sig = L; /* reorganiza */
L = p; /* los enlaces */
}
p = L;
while (p != NULL)
{
printf("%d, ", p->clave);
p = p->sig;
}
getchar();
return;
}


Tiene algún próposito que desconozco esta intrucción? He probado sin declarar suma y la instrucción suma = suma + p->clave; y me compila perfectamente. Gracias por su ayuda. Un saludo.
  #9 (permalink)  
Antiguo 22/05/2006, 13:06
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años, 8 meses
Puntos: 2
tu no lo sabes??

suma es eso una variable que acumula la suma de todos los campos clave de tu lista.

En el ejemplo anterior lo haces recursiva, ahora lo haces con un while, en ambos casoso es lo mismo.

la funcion recursiva termina asta que la lista apunte al ultimo nodo(NULL), y el while termina con esa misma condicion, la diferencia esta en la ejcucion, las funciones recurcivas consumen muchos recursoso, a diferencia de los bucles.

lo de la variable suma, es que en realidad no intervienen en el funcionamiento pero tal vez se utilice en alguna otra parte. o se requiera como resultado.

Saludos.
  #10 (permalink)  
Antiguo 22/05/2006, 20:32
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años, 1 mes
Puntos: 52
No es buena idea usar recursividad. Es muy suseptible a errores y aparte como te dice Nivel7 no es plenamente eficiente.

Saludos
  #11 (permalink)  
Antiguo 23/05/2006, 04:10
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Sabía lo que hacía suma pero no tiene nada que ver con el funcionamiento del programa. En el enunciado de mi programa simplemente decía crear una lista enlazada de 3 elementos. Nada de sumar ni nada.... Solo era para asegurarme. Muchas gracias.
  #12 (permalink)  
Antiguo 28/05/2006, 05:42
 
Fecha de Ingreso: abril-2005
Mensajes: 8
Antigüedad: 19 años, 8 meses
Puntos: 0
Hola!, os envio un programita con lista simple el problema que me daba era al insertar el registro no se que pasa que me da violación del segmento, no creo que tenga importancia pero lo he programado en linux, con el editor emacs y el compilador gcc, lo digo por lo de reservar memoria que es más corto y no he de poner tipo* delante en lo del malloc, bueno aqui os lo dejo:

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

#define NUM_CONTROLES 9
#define MAXLON 30

struct Registro
{
int dorsal;
int num_control;
float tiempo_paso;
};
typedef struct Registro TipoRegistro;

struct Nodo
{
TipoRegistro info;
int dorsal;
float tiempos[NUM_CONTROLES];
struct Nodo *sig;
};
typedef struct Nodo TipoNodo;

struct Lista
{
TipoNodo *primero;
TipoNodo *ultimo;
int num;
};
typedef struct Lista TipoLista;

void LeerNodoCorredor( TipoNodo *n );
void CrearListaVacia( TipoLista *l );
void LeerCorredor( TipoRegistro *c);
void InsPorCola ( TipoLista *l, TipoNodo a );
void MostrarCorredor( TipoNodo c , TipoLista l);
void LeerNodoCorredor( TipoNodo *n );

int main( void )
{
TipoLista lista;
// TipoRegistro unCorredor; lo usare cuando me funcione
TipoNodo unNodoCorredor;
LeerNodoCorredor( &unNodoCorredor );

InsPorCola( &lista, unNodoCorredor );
//MostrarCorredor( unNodoCorredor ); lo arreglare cuando funcione InsPorCola



return 0;
}

void CrearListaVacia( TipoLista *l )
{
l->primero = NULL;
l->ultimo = NULL;
l->num = 0;

}

void LeerCorredor( TipoRegistro *c)
{
c->dorsal=1;
c->num_control = 7;
c->tiempo_paso = 2.0;

}

void LeerNodoCorredor( TipoNodo *n )

{
LeerCorredor(&n->info);
n->dorsal = 1;
n->tiempos[0]=2.0;

}

void InsPorCola ( TipoLista *l, TipoNodo a )
{
TipoNodo *nuevo;

nuevo = malloc( sizeof(TipoNodo) );

nuevo->info = a.info;
nuevo->dorsal = a.dorsal;
nuevo->tiempos[l->num] = a.info.tiempo_paso;
nuevo->sig = NULL;


if(l->ultimo==NULL)
{
l->primero = nuevo;
l->ultimo = nuevo;
}
else
{
l->ultimo->sig = nuevo;
l->ultimo = nuevo;
}
l->num++;
}

void MostrarCorredor( TipoNodo c , TipoLista l)
{

printf("%d ",c.dorsal);
printf("%d ",c.info.num_control);
printf("%f ",c.tiempo_paso[l.num]);

}

Última edición por kllb; 28/05/2006 a las 09:57
  #13 (permalink)  
Antiguo 28/05/2006, 09:02
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Creo que te estás haciendo un lío al declarar los structs.Si creas un struct Nodo y luego quieres declarar una variable del tipo struct nodo no debes hacer typedef struct Nodo TipoNodo; , lo correcto me parece que sería struct Nodo TipoNodo; sin el typedef.En la función insertar por cola declaras mal la variable nuevo(para crear un nuevo nodo). Lo correcto sería struct Nodo *nuevo;. La asignación de memoria con malloc creo que también está mal expresada. Para asignarle memoria al nuevo nodo deberías hacerlo así: nuevo=(struct Nodo*)malloc(sizeof(struct Nodo));
  #14 (permalink)  
Antiguo 28/05/2006, 09:05
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Te dejo un ejemplo de una lista enlazada bastante simple con las funciones de insertar por cabecera,por cola, e insertar en orden. Espero que te ayude a solucionar dudas. A mí me costó hacer el ejercicio(lo conseguí hace poquito ).

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


struct tnodo
{
int dato;
struct tnodo * siguiente;
};

void insertar_por_cabecera(struct tnodo * * lista, int valor)
{
struct tnodo * nuevo = (struct tnodo *) malloc(sizeof(struct tnodo));
nuevo->dato = valor;
nuevo->siguiente = *lista;
*lista = nuevo;
}

void insertar_por_cola(struct tnodo * *lista, int valor)
{
struct tnodo * actual;

// Creo el nodo nuevo
struct tnodo * nuevo = (struct tnodo *) malloc(sizeof(struct tnodo));
nuevo->dato = valor;
nuevo->siguiente = NULL;

if (*lista == NULL)
{
// Si la lista está vacía la creo
*lista = nuevo;
}
else
{
// Si no, recorro la lista hasta el final y
actual = *lista;
while (actual->siguiente != NULL)
{
actual = actual->siguiente;
}
// El último puntero lo asigno
actual->siguiente = nuevo;
}
}

void insertar_en_orden(struct tnodo * *lista, int valor)
{
struct tnodo * actual;

// Creo el nodo nuevo
struct tnodo * nuevo = (struct tnodo *) malloc(sizeof(struct tnodo));
nuevo->dato = valor;
nuevo->siguiente = NULL;

if (*lista == NULL)
{
// Si la lista está vacía la creo
*lista = nuevo;
}
else
{
actual = *lista;
// Si es el menor de la lista
if (actual->dato > valor)
{
nuevo->siguiente = actual;
*lista = nuevo;
}
else
{
// Si no, recorro la lista hasta el final o donde debo insertarlo y
while (actual->siguiente != NULL && valor >= actual->siguiente->dato)
{
actual = actual->siguiente;
}
// Asigno los punteros
nuevo->siguiente = actual->siguiente;
actual->siguiente = nuevo;
}
}
}

void borrar_lista(struct tnodo * *lista)
{
struct tnodo * nodo;

while (*lista != NULL)
{
nodo = *lista;
*lista = nodo->siguiente;
free(nodo);
}
}

void mostrar(struct tnodo * lista)
{
struct tnodo * actual = lista;

printf("Lista:\n");
while (actual != NULL)
{
printf("%d\t", actual->dato);
actual = actual->siguiente;
}
printf("\n");
}

main()
{
struct tnodo * lista1 = NULL;
struct tnodo * lista2 = NULL;
struct tnodo * lista3 = NULL;

insertar_por_cabecera(&lista1, 1);
insertar_por_cabecera(&lista1, 3);
insertar_por_cabecera(&lista1, 2);
mostrar(lista1);
borrar_lista(&lista1);

insertar_por_cola(&lista2, 1);
insertar_por_cola(&lista2, 3);
insertar_por_cola(&lista2, 2);
mostrar(lista2);
borrar_lista(&lista2);

insertar_en_orden(&lista3, 3);
insertar_en_orden(&lista3, 1);
insertar_en_orden(&lista3, 2);
mostrar(lista3);
borrar_lista(&lista3);

getchar();
}

Para más dudas hay aquí más gente que sabe muchísimo más que yo. Un saludo.
  #15 (permalink)  
Antiguo 28/05/2006, 09:38
 
Fecha de Ingreso: abril-2005
Mensajes: 8
Antigüedad: 19 años, 8 meses
Puntos: 0
Gracias por la sugerencia, voy a mirar como lo haces detenidamente.
Pero lo de nuevo=(struct Nodo*)malloc(sizeof(struct Nodo)); no es necesario poner el struct Nodo* porque en linux,(emacs,gcc), se las apaña solo y lo pone bien asi, por lo que nuevo=malloc(sizeof(struct Nodo)); funciona bien,
no puedo quitarlo porque sino no me ira (no lo he probado sin)


Te cojo la idea: Voy a repasar por si lo que me he rallado con lo del typedef.
Gracias por la ayuda prestada, examinaré paso por paso el ejercicio con la ayuda de tu ejemplo para ver si lo arreglo.

Nota:una aclaración de porque lo hago así, lo del typedef struct ... lo hago para no tener que escribir lo de struct ..., y asi poniendo lo que he declarado me evito ponerlo tan largo, y me quito el **en las funciones que dan miedo.
  #16 (permalink)  
Antiguo 28/05/2006, 10:41
 
Fecha de Ingreso: mayo-2006
Mensajes: 40
Antigüedad: 18 años, 7 meses
Puntos: 0
Eso de poner
Código:
struct Nodo *nuevo = (struct Nodo *)malloc(sizeof(struct Nodo));
o
Código:
struct Nodo *nuevo = malloc(sizeof(struct Nodo));
depende de los niveles que tenga tu compilador cuando trata los avisos (warnings) y los errores. En muchos compiladores cuando les pones el nivel mas alto al verificar los errores que puedas tener en tu codigo la construccion struct Nodo *nuevo = malloc(sizeof(struct Nodo)); simplemente no la pasan y la tratan como si de un error se tratara y no te genera el ejecutable. Si le bajas el numero de nivel esta construccion puede que solo te de un warning pero si te genera el programa o puede que simplemente no te diga nada al respecto. Seguramente esos compiladores que mencionas por defecto tienen un nivel no muy estricto en la comprobacion de este tipo de construcciones y por eso no te arroja ningun aviso. Lo que pasa es que cuando usas malloc este te devuelve un apuntador a void por lo cual lo puedes asignar a una variable que apunte a cualquier cosa y es muy propenso a que puedas a cometer un error si te descuidas, y si este es el caso, solo vas a detectar los errores cuando estes ejecutando el programa, pero muchas veces puede que tu programa funcione bien algunas veces y otras no, lo cual hace muy dificil detectar en el codigo donde esta el error.
  #17 (permalink)  
Antiguo 29/05/2006, 01:28
Avatar de yournightmare86  
Fecha de Ingreso: abril-2006
Ubicación: Madrid
Mensajes: 875
Antigüedad: 18 años, 8 meses
Puntos: 9
Bueno no me dí cuenta de que programabas en ese entorno. Así que lo conocerás mejor que yo. No conozco ese entorno supongo que cambiarán cosas.
  #18 (permalink)  
Antiguo 29/05/2006, 06:35
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años, 8 meses
Puntos: 17
Cita:
Iniciado por kllb
Gracias por la sugerencia, voy a mirar como lo haces detenidamente.
Pero lo de nuevo=(struct Nodo*)malloc(sizeof(struct Nodo)); no es necesario poner el struct Nodo* porque en linux,(emacs,gcc), se las apaña solo y lo pone bien asi, por lo que nuevo=malloc(sizeof(struct Nodo)); funciona bien,
no puedo quitarlo porque sino no me ira (no lo he probado sin)
Como te han explicado algo más arriba, no tiene nada que ver que sea GNU/Linux, gcc, emacs o lo que sea.

Simplemente, puedes compilarlo porque C tiene tipado "flojo", y te convierte implícitamente el void * en struct Nodo *.

Pero lo correcto es escribir el (struct Nodo *)
  #19 (permalink)  
Antiguo 29/05/2006, 06:37
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años, 8 meses
Puntos: 17
Cita:
Iniciado por yournightmare86
Creo que te estás haciendo un lío al declarar los structs.Si creas un struct Nodo y luego quieres declarar una variable del tipo struct nodo no debes hacer typedef struct Nodo TipoNodo; , lo correcto me parece que sería struct Nodo TipoNodo; sin el typedef.En la función insertar por cola declaras mal la variable nuevo(para crear un nuevo nodo). Lo correcto sería struct Nodo *nuevo;. La asignación de memoria con malloc creo que también está mal expresada. Para asignarle memoria al nuevo nodo deberías hacerlo así: nuevo=(struct Nodo*)malloc(sizeof(struct Nodo));
Yo casi nunca uso typedefs, escribo todo lo correspondiente, para cuando lea el código, saber inmediatamente qué pretendo hacer.

Ahora bien, si se complica mucho (aunque este no es el caso) sí, es bueno usarlo para evitar errores al escribir, poder cambiar algo rápidamente en todos los sitios, etc.
  #20 (permalink)  
Antiguo 29/05/2006, 09:11
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años, 1 mes
Puntos: 52
Cita:
Ahora bien, si se complica mucho (aunque este no es el caso) sí, es bueno usarlo para evitar errores al escribir, poder cambiar algo rápidamente en todos los sitios, etc.
Preferible que sean errores de escritura a bugs invisibles
Saludos
  #21 (permalink)  
Antiguo 29/05/2006, 10:45
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años, 8 meses
Puntos: 17
Cita:
Iniciado por Instru
Preferible que sean errores de escritura a bugs invisibles
Saludos
Sí, cierto, pero cuando empiezas a jugar con los punteros a función...

Código:
(struct Nodo * mipuntero*)(char * data, (struct Nodo *function)(int))
Escribirse eso bastantes veces harta xD, y no es más que un puntero a una función que devuelve un struct Nodo*, y sus parámetros son un char* y otro puntero a función que devuelve structu Nodo* y toma como parámetro un int.
  #22 (permalink)  
Antiguo 29/05/2006, 19:15
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años, 8 meses
Puntos: 2
Tu programa esta casi perfecto...........

Primero con respecto a los typedef.

C te da la libertad de usarlo como estructuras al estilo C, o crear seudonimos como si fuesen tipos.

y la forma mas tradicional es:

typedef struct _Nodo
{
}TipoNodo;

Pero al final eres libre de usar tu estilo.

En relacion a malloc por mucho que C, te permita usarlo sin casting explicito, es bueno hacerlo para mostrar lo que quieres hacer realmente.(Como si se comentara el codigo).


En relacion a tu programa tienes 2 o 3 errorsillos.

el primero es este:

nuevo->tiempo_paso[l->num] = a.info.tiempo_paso;

estas asiendo una asignacion de un miembro de Registro a un miembro de nodo, ademas de que EL TipoNodo no tienen un miembro tiempo_paso, el miembro array es tiempos.

Yo lo modifique a :

nuevo->tiempos[l->num] = a.info.tiempo_paso; para poderlo compilar.
no se si este correcto ono, de pende del proposito.
eso lo corriges tú.

EL segundo error esta aqui:

nuevo->tiempos[l->num] = a.info.tiempo_paso;
el miembro de tipoNodo tiempos es un array de un determinado numero de indices en este caso 9, la propiedad de lista num, no esta inicializado, por tanto puede tener un numero mayor a nueve y esto te proboca un error de acceso.
lo que yo hice fue usar la funcion CrearListaVacia.

CrearListaVacia(&lista );
Con esto me aseguro de que la propiedad num de lista es 0.
(Para que implementas esta funcion si no la usas???).

Hay un 3er error:
En MostrarCorredor:
printf("%f ",c.tiempos[l.num]);
se supone que esta funcion la usaras despues de haber insertado.
Entonces la propiedad num de lista se habra incrementado a un nodo vacio.

por tanto c.tiempos(l.num] tiene un valor cualquiera, que no es el que esperas(Supongo).

YO hice:
printf("%f ",c.tiempos[l.num-1]);

Pero esto dependera de tus requerimientos.

Bueno eso es lo pude ver, en tu codigo.

Saludos.
  #23 (permalink)  
Antiguo 01/06/2006, 05:57
 
Fecha de Ingreso: abril-2005
Mensajes: 8
Antigüedad: 19 años, 8 meses
Puntos: 0
Gracias, a todos por la ayuda, al final lo he cambiado un poco me lié con los tipos supongo. Os dejo mi ejercicio final. Con todo lo que había que hacer. Una cosa este es una lista simple que tiene puntero a cabeza. No como antes que sólo había puntero a cabeza.

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

#define NUM_CONTROLES 9
struct Registro
{
int dorsal;
int num_control;
float tiempo_paso;

};
typedef struct Registro TipoRegistro;

struct Nodo
{
int dorsal;
float tiempos[NUM_CONTROLES];
struct Nodo *sig;
};
typedef struct Nodo TipoNodo;

struct Lista
{
struct Nodo *primero;
struct Nodo *ultimo;
int num;
};
typedef struct Lista TipoLista;

//prototipos
void LeerFichero(TipoLista *l);
void IniciarLista(TipoLista *l);
void Mostrar(TipoLista *l);
void MostrarLosCorredoresMeta(TipoLista *l);
void MostrarTramoMenorMeta(TipoLista *l);
void MostrarMenu(void);
void BorrarLista( TipoLista *l);
int main( void )
{
int opcion;
TipoLista lista;
IniciarLista( &lista );
LeerFichero( &lista );

while(opcion!=4)
{
MostrarMenu();
printf("Dime la opcion:\n");
scanf("%d",&opcion);

switch(opcion)
{
case 1: Mostrar(&lista);
break;
case 2:
MostrarLosCorredoresMeta(&lista);
break;
case 3:
MostrarTramoMenorMeta(&lista);
break;
case 4:
puts("Gracias por usar el programa");
BorrarLista( &lista );
break;
default:
puts("Te has equivocado, escoge una opcion del 1 al 4");
break;
}
}
return 0;
}

void LeerFichero(TipoLista *l)
{
FILE *fp;
TipoRegistro unCorredor;
TipoNodo *aux,*nuevo;
int encontrado;
int i;

fp = fopen("marato_i_mitja.dat","rb");
if (fp == NULL) {
printf("ERROR: El fichero no se ha podido abrir\n");
exit(1);
}

fread(&unCorredor, sizeof(TipoRegistro),1,fp);
while( !feof(fp) )
{
// printf( "Dorsal del corredor: %d\n", unCorredor.dorsal );
//Vamos a ver si el corredor está ya en la lista:
encontrado = 0;
aux = l->primero;
while( aux != NULL && !encontrado )
{
if( aux->dorsal == unCorredor.dorsal )
{
aux->tiempos[unCorredor.num_control-1] = unCorredor.tiempo_paso;
encontrado = 1; //SI QUE ESTA
}
aux = aux -> sig;
}

if( !encontrado ) //NO ESTA
{
//crear un nuevo nodo e insertarlo

nuevo = malloc( sizeof(TipoNodo) );
for (i=0; i<NUM_CONTROLES; i++)
nuevo->tiempos[i] = -1;

nuevo->dorsal = unCorredor.dorsal;
nuevo->tiempos[unCorredor.num_control-1] = unCorredor.tiempo_paso;
nuevo->sig = NULL;
if( l->ultimo!=NULL )
{
l->ultimo->sig = nuevo;
l->ultimo = nuevo;
}
else
{
l->primero = nuevo;
l->ultimo = nuevo;
}
l->num++;

}
fread(&unCorredor, sizeof(TipoRegistro),1,fp);
}//fin while
fclose(fp);
}//leerfichero

void IniciarLista(TipoLista *l)
{
l->primero = NULL;
l->ultimo = NULL;
l->num = 0;

}

void Mostrar(TipoLista *l)
{
int i;
TipoNodo *aux;
aux = l->primero;

while( aux!=NULL )
{
printf("%4d: ", aux->dorsal);
for(i=0; i<NUM_CONTROLES; i++)
{
printf("%5.2f ",aux->tiempos[i]);
}
printf("\n");
aux = aux->sig;
}
}

void MostrarLosCorredoresMeta(TipoLista *l)
{
TipoNodo *aux;
aux= l->primero;
int cantidad=0;
while( aux != NULL )
{
if(aux->tiempos[NUM_CONTROLES-1] != -1)
{
printf("%d\n", aux->dorsal);
cantidad++;
}
aux = aux->sig;
}

printf("\nEl total de corredores que han alcanzado la meta es ---> %d\n", cantidad);
}


void MostrarTramoMenorMeta(TipoLista *l)
{
TipoNodo *aux;
aux=l->primero;
//float menor;
int tramo,mejor;
int menortiempo;
int i;
int dorsalrapido;

while( aux!=NULL )
{
if(aux->tiempos[NUM_CONTROLES-1]!=-1)
{

dorsalrapido=aux->dorsal;
for(i=0;i<NUM_CONTROLES-1;i++)
{
tramo = aux->tiempos[i+1] - aux->tiempos[i];
if(tramo>menortiempo)
{
menortiempo = tramo;
mejor = i;
dorsalrapido = aux->dorsal;
}
printf("El corredor es %d\n",dorsalrapido);
printf("\nEl tramo recorrido en menos tiempo es %d", mejor);
}

}
aux = aux->sig;

}
printf("El corredor más rápido es %d\n",dorsalrapido);
printf("\nEl tramo recorrido en menos tiempo es %d", mejor);
}

void MostrarMenu(void)
{
printf("\n");
printf("---------------------------------------MENU----------------------------");
printf("\n1-Mostrar el contenido de la lista ");
printf("\n2-Mostrar la cantidad de corredores \nque han llegado a la meta ");
printf("\n3-Mostrar El menor tiempo de los corredores que han llegado a la meta");
printf("\n4-Salir");
printf("-----------------------------------------------------------------------\n");

}
void BorrarLista( TipoLista *l)
{
TipoNodo *aux;
if(l->primero == l->ultimo)
{
free(l->primero);
l->primero = NULL;
l->ultimo = NULL;
}
else
{
for(aux=l->primero;aux->sig!=l->ultimo;aux=aux->sig);
aux->sig = NULL;
free(l->ultimo);
l->ultimo = aux;
}
}
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 17:57.