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

Archivos y Listas enlazadas simples en C

Estas en el tema de Archivos y Listas enlazadas simples en C en el foro de C/C++ en Foros del Web. Hola gente. Hace poco que estoy en esto de C y estaba tratando de usar archivos y llenar un fichero con datos que estan en ...
  #1 (permalink)  
Antiguo 21/07/2016, 16:18
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Exclamación Archivos y Listas enlazadas simples en C

Hola gente. Hace poco que estoy en esto de C y estaba tratando de usar archivos y llenar un fichero con datos que estan en una Lista enlazada simple.
Por mucho que intente y lei, no logre encontrar la solucion. Lo mas cerca que he estado es lo que voy a subir.. Desde ya, gracias!

Código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* CONTROL DE MEMORIA
	Persona *aux;
	if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
*/
typedef struct TipoFecha{
	int dia;
	int mes;
	int anio;
}TFecha;

typedef struct TipoAmigo{
	char apellido[20];
	char nombre[20];
	char email[30];
	char celular[15];
	TFecha fecNac;
	char flag;
}Amigo;

typedef struct ElementoLista{
	Amigo  dato;
	struct Persona *sig;
}Persona;

typedef struct ListaIdentificar {
    Persona *inicio;
    Persona *fin;
    int cantidad;
}Lista;


int guardarArchivo(FILE *f,Lista *l);
int mostrarArchivo(FILE *f);


void inicializacion (Lista *l);
int insInicioLista (Lista *l,Amigo p);
int insEnListaVacia (Lista *l,Amigo p);


int agregarAmigo(Lista *l);
Amigo pedirAmigo();
int estaAmigo(Lista *l,Amigo p);
int ordenar(Lista *l);
		
int estaAmigo(Lista *l,Amigo p);


void mostrarDatos(Lista *l);
void mostrarAmigo(Amigo p);


void main(){
	Lista *lista;
	if ((lista = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
	
	inicializacion(lista);
	int pos,control;
    do{
    	if (lista->cantidad==0){
        	agregarAmigo(lista);
    	}else if(lista->cantidad==1){
    		agregarAmigo(lista);
		}else{
			agregarAmigo(lista);
		}
		printf("\n\n");
		printf("Seguir agregando?\n");
		scanf("%i",&control);
        if (control==1){
        	ordenar(lista);
        	mostrarDatos(lista);
        	printf("\n\n\n\t");
        	system("pause");
		}else{
			printf("\n\n\t");
			printf("Gracias por utilizar este programa.\n");
		}
	}while (control==1);
	/*-------------------PRUEBA DE ARCHIVO-----------*/
	printf("Vengooo\n");
	FILE *f1,*f2;
	printf("Sigooooo\n");
	//if(existeArchivo("agenda1")==0){
		f1 = fopen ("agenda1.txt", "w+b");
//		f2 = fopen ("fichero2.dat", "wb");
		if(guardarArchivo(f1,lista)==-1){
			printf("\nNo se pudo guardar.");
		}else{
			printf("Archivo Guardado con Exito.");
			mostrarArchivo(f1);
		}
		fclose(f1);
}



void inicializacion (Lista *l){
	l->fin=NULL;
	l->inicio=NULL;
	l->cantidad=0;
}


int agregarAmigo(Lista *l){
	Amigo persona=pedirAmigo();
	int encontrado=estaAmigo(l,persona);
	if (encontrado==-1){
		return encontrado;
	}else if(l->cantidad==0){
		insEnListaVacia(l,persona);
	}else{
		insInicioLista(l,persona);
	}
}


Amigo pedirAmigo(){
	Amigo aux;
	do{
		printf("\nIngrese el apellido de su amigo.\n");
		fflush(stdin);
        gets(aux.apellido);
        printf("\nEs %s",aux.apellido);
	}while (strlen(aux.apellido)>20);
		do{
		printf("\nIngrese el nombre de su amigo.\n");
		fflush(stdin);
        gets(aux.nombre);
	}while (strlen(aux.nombre)>20);
		do{
		printf("\nIngrese el email de su amigo.\n");
		fflush(stdin);
        gets(aux.email);
	}while (strlen(aux.email)>30);
		do{
		printf("\nIngrese el celular de su amigo.\n");
		fflush(stdin);
        gets(aux.celular);
	}while (strlen(aux.celular)>15);
	printf("\nFecha de cumpleaños de su amigo.");
	do{	
		printf("\nIngrese el anio de nacimiento: ");
		scanf("%i",&aux.fecNac.anio);
	}while ((aux.fecNac.anio>2016)||(aux.fecNac.anio<1900));
	do{	
		printf("\nIngrese el mes de nacimiento: ");
		scanf("%i",&aux.fecNac.mes);
	}while ((aux.fecNac.mes>12)||(aux.fecNac.mes<1));
	do{	
		printf("\nIngrese el dia de nacimiento: ");
		scanf("%i",&aux.fecNac.dia);
	}while ((aux.fecNac.dia>31)||(aux.fecNac.dia<1));
	aux.flag=' ';
	return aux;
}


int estaAmigo(Lista *l,Amigo p){
	int i=1;
	Persona *aux;
	if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
	if(l->cantidad==0){
		return 0;
	}else {
		aux=l->inicio;
		while (i<=l->cantidad){
			if(strcmpi(aux->dato.apellido,p.apellido)!=0){
				i++;
				aux=aux->sig;
			}else if(strcmpi(aux->dato.nombre,p.nombre)!=0){
			i++;
			aux=aux->sig;
			}else if(strcmpi(aux->dato.email,p.email)!=0){
			i++;
			aux=aux->sig;
			}else if(strcmpi(aux->dato.celular,p.celular)!=0){
			i++;
			aux=aux->sig;
			}else if(aux->dato.fecNac.anio!=p.fecNac.anio){
			i++;
			aux=aux->sig;
			}else if(aux->dato.fecNac.mes!=p.fecNac.mes){
			i++;
			aux=aux->sig;
			}else if(aux->dato.fecNac.dia!=p.fecNac.dia){
				i++;
				aux=aux->sig;
			}else{
				return -1;
			}
		}
	}
	return 0;
}


int insEnListaVacia (Lista *l,Amigo p){
	Persona *aux;
	if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
	aux->dato=p;
	aux->sig=NULL;
	l->inicio=aux;
	l->fin=aux;
	l->cantidad++;
} 


int insInicioLista (Lista *l,Amigo p){
	Persona *aux;
	if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
	aux->dato=p;
	aux->sig=l->inicio;
	l->inicio=aux;
	l->cantidad++;
}


void mostrarAmigo(Amigo p){
	printf("\nLos datos del amigo es: \n");
	printf("El apellido de su amigo: %s\n",p.apellido);
	printf("El nombre de su amigo: %s\n",p.nombre);
	printf("El email de su amigo: %s\n",p.email);
	printf("El celular de su amigo: %s\n",p.celular);
	printf("Fecha de cumpleaños de su amigo. %i/%i/%i\n",p.fecNac.dia,p.fecNac.mes,p.fecNac.anio);
}


void mostrarDatos(Lista *l){
	Persona *aux;
	int i=1;
	if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
	aux=l->inicio;
	while (i<=l->cantidad){
		mostrarAmigo(aux->dato);
		aux=aux->sig;
		i++;
	}
}


int ordenar(Lista *l){
	int pos=1;
	Amigo cam;
	if(l->cantidad==1){
		return 0;
	}else{
		Persona *aux,*aux2,*min;
		if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        	return -1;
		}
		if ((aux2 = (Persona *) malloc (sizeof (Persona))) == NULL){
        	return -1;
		}
		if ((min = (Persona *) malloc (sizeof (Persona))) == NULL){
        	return -1;
		}
		min=l->inicio;
		while(pos<l->cantidad){
			aux=min;
			aux2=min->sig;
			while(aux2!=NULL){
				if((strcmpi(aux->dato.apellido,aux2->dato.apellido))>0){	//se comparan apellidos
					aux=aux2;											//se compara el nombre 
				}else if(((strcmpi(aux->dato.apellido,aux2->dato.apellido))==0)&&((strcmpi(aux->dato.nombre,aux2->dato.nombre))>0)){ 
					aux=aux2;
				}
				aux2=aux2->sig;		
			}
			cam=min->dato;
			min->dato=aux->dato;
			aux->dato=cam;
			min=min->sig;
			pos++;
		}
		return 0;
	}
}


int guardarArchivo(FILE *f,Lista *l){
	Persona *aux;
	Amigo a;
	int i=1;
	if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
        return -1;
	}
	aux=l->inicio;
	while(aux!=NULL){
		a=aux->dato;
		fwrite((Amigo *)&a,i*sizeof(Amigo),i,f);
        aux=aux->sig;
        i++;
    }
	return 0;
}


int mostrarArchivo(FILE *f){
	Amigo aux;
	int numReg = ftell(f)/sizeof(Amigo),i;
	for(i=0;i<numReg;i++){
		fseek (f, i, SEEK_SET);
		fread (&aux,sizeof(Amigo),1, f);
		mostrarAmigo(aux);
	}
}
  #2 (permalink)  
Antiguo 22/07/2016, 03:37
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 5 años, 2 meses
Puntos: 204
Respuesta: Archivos y Listas enlazadas simples en C

Código C:
Ver original
  1. typedef struct ElementoLista{
  2.   Amigo  dato;
  3.   struct Persona *sig; // <<--- AQUI!!!
  4. }Persona;

En este punto, Persona no ha sido declarado, luego el compilador no sabe tratarlo. La solución es esta:

Código C++:
Ver original
  1. typedef struct ElementoLista{
  2.   Amigo  dato;
  3.   struct ElementoLista *sig;
  4. }Persona;

Más cosas:

Código C:
Ver original
  1. Lista *lista;
  2. if ((lista = (Persona *) malloc (sizeof (Persona))) == NULL){

Lista no es lo mismo que Persona. Ese malloc está mal invocado:

Código C:
Ver original
  1. Lista *lista;
  2. if ((lista = (Lista*) malloc (sizeof (Lista ))) == NULL){

Seguimos:

Código C:
Ver original
  1. void mostrarDatos(Lista *l){
  2.   Persona *aux;
  3.   int i=1;
  4.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  5.         return -1; // <<--- AQUI!!!
  6.   }

Si la función es void, es decir, no retorna nada... ¿por qué pones "return -1"?.

Por otro lado, si seguimos revisando esa función nos encontramos con lo siguiente:

Código C:
Ver original
  1. if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  2.       return -1;
  3. }
  4. aux=l->inicio;

Es decir, reservas memoria para aux y seguidamente haces una asignación en aux, por lo que pierdes la reserva que acabas de hacer. Si aux lo usas para iterar sobre la lista no hace falta que hagas ninguna reserva, ya que su única función es apuntar a posiciones de memoria de l, posiciones de memoria que dicho sea de paso ya existen.

Por otro lado se supone que el último elemento de una lista enlazada ha de ser un puntero nulo. Por este motivo no es necesario usar la variable i. Simplemente basta con iterar hasta que aux sea NULL. Algo así:

Código C:
Ver original
  1. void mostrarDatos(Lista *l){
  2.   Persona *aux = l->inicio;
  3.   while (aux){
  4.     mostrarAmigo(aux->dato);
  5.     aux=aux->sig;
  6.   }
  7. }

Nota: Estos dos últimos prolemas se repitne en otras funciones, como estaAmigo.

Revisando, ya puestos, estaAmigo tenemos:

Código C:
Ver original
  1. int estaAmigo(Lista *l,Amigo p){
  2.   int i=1;
  3.   Persona *aux;
  4.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  5.         return -1;
  6.   }
  7.   if(l->cantidad==0){
  8.     return 0;
  9.   }else {
  10.     aux=l->inicio;
  11.     while (i<=l->cantidad){
  12.     // ...

Que aplicando los cambios anteriores queda así (una forma de hacerlo):

Código C:
Ver original
  1. int estaAmigo(Lista *l,Amigo p){
  2.   int existe = 0;
  3.   for(Persona *aux=l->inicio; aux && !existe; aux=aux->sig)
  4.   {
  5.     existe = (strcmpi(aux->dato.apellido,p.apellido)==0);
  6.     existe &= (strcmpi(aux->dato.nombre,p.nombre)==0);
  7.     existe &= (strcmpi(aux->dato.email,p.email)==0);
  8.     existe &= (strcmpi(aux->dato.celular,p.celular)==0);
  9.     existe &= (aux->dato.fecNac.anio==p.fecNac.anio);
  10.     existe &= (aux->dato.fecNac.mes==p.fecNac.mes);
  11.     existe &= (aux->dato.fecNac.dia==p.fecNac.dia);
  12.   }
  13.  
  14.   return existe;
  15. }

Entre otras cosas, la función estaAmigo se entiende que debería devolver 0 o 1, ya que el elemento o está o no está... no tiene sentido que retornes -1 o cosas raras.

Más detalles:

Código C:
Ver original
  1. int insEnListaVacia (Lista *l,Amigo p){
  2.   Persona *aux;
  3.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  4.         return -1;
  5.   }
  6.   aux->dato=p;
  7.   aux->sig=NULL;
  8.   l->inicio=aux;
  9.   l->fin=aux;
  10.   l->cantidad++;
  11. }
  12.  
  13.  
  14. int insInicioLista (Lista *l,Amigo p){
  15.   Persona *aux;
  16.   if ((aux = (Persona *) malloc (sizeof (Persona))) == NULL){
  17.         return -1;
  18.   }
  19.   aux->dato=p;
  20.   aux->sig=l->inicio;
  21.   l->inicio=aux;
  22.   l->cantidad++;
  23. }

¿Por qué dos funciones individuales que hacen prácticamente lo mismo? ¿Por qué si tienen como valor de retorno un int no hay ningún return si todo ha ido bien? Realmente las dos funciones hacen exactamente lo mismo aunque no lo parezca. La más genérica es la segunda (si la lista está vacía, entonces l->inicio va a ser NULL:

Código C:
Ver original
  1. // Nota que a la función le da igual que haya o no elementos en la lista.
  2. int insertarInicio(Lista*l, Amigo p)
  3. {
  4.   int toReturn = 0; // 0 = error
  5.  
  6.   Persona *aux = (Persona *) malloc (sizeof (Persona)));
  7.   if ((aux != NULL)
  8.   {
  9.     aux->dato=p;
  10.     aux->sig=l->inicio;
  11.     l->inicio=aux;
  12.     l->cantidad++;
  13.  
  14.     // Por si acaso la lista está vacía
  15.     if( !l->fin ) l->fin = aux;
  16.  
  17.     toReturn = 1; // 1 = ok
  18.   }
  19.  
  20.   return toReturn;
  21. }

Y bueno, referente a esta función:

Código C:
Ver original
  1. void inicializacion (Lista *l){
  2.   l->fin=NULL;
  3.   l->inicio=NULL;
  4.   l->cantidad=0;
  5. }

Decirte que sobra si pasas a crear la lista con calloc en vez de con malloc. calloc setea todos los valores de la memoria reservada a cero, lo cual es ideal para incializar estructuras con punteros y cadenas. También puedes usar memset para inicializar una región de memoria cualquiera. La ventaja de cualquiera de estas dos alternativas es que si, por ejemplo, modificas la estructura para añadir o quitar elementos las funciones se adaptarán al nuevo tamaño sin tener que tocar código:

Código C:
Ver original
  1. int main(){
  2.   Lista *lista;
  3.   if ((lista = (Lista *) calloc (1,sizeof(Lista))) == NULL){
  4.         return -1;
  5.   }
  6.  
  7.   // Ahora esto sobra
  8.   //inicializacion(lista);

Y bueno, para rematar comentarte que hay que tener especial cuidado con la memoria dinámica... cada malloc / calloc ha de tener su correspondiente free para liberar la memoria correspondiente y en tu código las llamadas a free brillan por su ausencia.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #3 (permalink)  
Antiguo 22/07/2016, 06:39
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Respuesta: Archivos y Listas enlazadas simples en C

eferion Muchas gracias por tu respuesta.. Por revisar el codigo y encontrar TANTOS errores.. Me diste una mano impresionante. Voy a tener en cuenta tus consejos..
Una pregunta, cuando vos decis de usar la funcion "free".. Yo en las funciones no las uso porque las variables locales desaparecen al terminar la invocacion de la funcion.. Eso esta bien?
Tendria que usarlo en el main?. No entendi esa parte, mis disculpas por la ignorancia..

Despues el tema del guardado y creacion del archivo.. No termino de entender..
Si yo no creo el archivo dentro de la carpeta donde esta el .exe.. No funciona, pero deberia crearlo solo.. (a mi entender)
Despues, solo guarda uno de los elementos en el archivo y no tengo idea de por que!?

Gracias eferion y disculpas por llenarte de preguntas..
  #4 (permalink)  
Antiguo 22/07/2016, 07:29
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 5 años, 2 meses
Puntos: 204
Respuesta: Archivos y Listas enlazadas simples en C

Cita:
Iniciado por matiri90 Ver Mensaje
Una pregunta, cuando vos decis de usar la funcion "free".. Yo en las funciones no las uso porque las variables locales desaparecen al terminar la invocacion de la funcion.. Eso esta bien?
Código C:
Ver original
  1. void func()
  2. {
  3.   int var;
  4.   char* ptr;
  5.   ptr = malloc(10);
  6.   char* ptr2 = ptr;
  7. }

En el código anterior:
  • var es una variable local y, como tal, será eliminada cuando el código abandone la función
  • ptr es una variable local, por lo que al abandonar la función también será eliminada
  • ptr2 es una variable local, por lo que al abandonar la función también será eliminada.
Si la memoria dinámica se liberase sola... ¿Cual de los dos punteros debería hacerlo? ¿ptr? ¿ptr2? ¿por qué?

La reserva de memoria no es local. Es una petición que le haces al sistema operativo para que te asigne una zona de memoria del tamaño pedido para tu uso exclusivo... tu te has encargado de pedirla y tu eres el responsable de liberarla cuando ya no la necesites. Si no lo haces entonces tu programa acaba teniendo fugas de memoria. Haz una búsqueda en Internet y encontrarás numerosa documentación al respecto.


Cita:
Iniciado por matiri90 Ver Mensaje
Tendria que usarlo en el main?. No entendi esa parte, mis disculpas por la ignorancia..
En un programa debería haber una equivalencia entre creaciones y liberaciones. Si no es así tu programa perderá memoria. Piensa que si haces una reserva de memoria dinámica y "pierdes" las referencias a dicha memoria no la podrás usar para nada ni tampoco liberar. Si es cierto que los sistemas operativos modernos liberan esa memoria automáticamente cuando el programa que las ha pedido se cierra... pero mientras el programa está operativo esa memoria se ocupa de forma innecesaria.

Cita:
Iniciado por matiri90 Ver Mensaje
Despues el tema del guardado y creacion del archivo.. No termino de entender..
Si yo no creo el archivo dentro de la carpeta donde esta el .exe.. No funciona, pero deberia crearlo solo.. (a mi entender)
Despues, solo guarda uno de los elementos en el archivo y no tengo idea de por que!?
Yo te recomendaría dar un buen repaso al programa, simplificarlo y evitar código duplicado en la medida de lo posible... una vez hecho eso vuelve por el foro, pon el programa actualizado y pregunta tus dudas... piensa que una vez tocas tu programa de forma local, el código que aparece en el foro pasa a estar obsoleto.

No obstante te informo que si no le pones una ruta exacta al fichero éste se creará a partir de la ruta de trabajo del ejecutable... que no tiene por qué coincidir con la ubicación del ejecutable. Esto puede provocar que el programa intente escribir en una ruta no válida y falle. Prueba a usar rutas absolutas en vez de rutas relativas. También debes tener en cuenta el tema de los permisos de acceso.

Por cierto, el depurador de código es una herramienta imprescindible para programar, te recomiendo aprender a usarlo.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #5 (permalink)  
Antiguo 22/07/2016, 07:57
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Respuesta: Archivos y Listas enlazadas simples en C

Ahi arregle la funcion "mostrarArchivo", que funciona..
Lo que si, tengo error de que si le paso una lista con 2 elementos, en el archivo al hacer..

Cita:
int numeroRegistros = ftell(f)/sizeof(Amigo);
Devuelve 5.. Cosa que deberia devolver 2, ya que agregaria 2 elementos.
No se cual es el error, puede que este reservando mal el lugar para el archivo..
Entonces al mostrar, me muestra los 2 correctos, pero despues lo demas me muestra basura..

Cita:
int mostrarArchivo(FILE *f){
Amigo aux;
int numReg = ftell(f)/sizeof(Amigo),i;
for(i=0;i<numReg;i++){
fseek (f, i*sizeof(Amigo), SEEK_SET);
fread (&aux,sizeof(Amigo),1, f);
mostrarAmigo(aux);
}
}
Abajo dejo las demas funciones

Cita:
int guardarArchivo(FILE *f,Lista *l){
Persona *aux=l->inicio;
Amigo a;
int i=1;
while(aux){
a=aux->dato;
fwrite((Amigo *)&a,i*sizeof(Amigo),i,f);
aux=aux->sig;
i++;
}
return 0;
}
  #6 (permalink)  
Antiguo 26/07/2016, 03:36
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 5 años, 2 meses
Puntos: 204
Respuesta: Archivos y Listas enlazadas simples en C

Código C:
Ver original
  1. int mostrarArchivo(FILE *f){
  2.   Amigo aux;
  3.   int numReg = ftell(f)/sizeof(Amigo),i;
  4.   for(i=0;i<numReg;i++){
  5.     fseek (f, i*sizeof(Amigo), SEEK_SET);
  6.     fread (&aux,sizeof(Amigo),1, f);
  7.     mostrarAmigo(aux);
  8.   }
  9. }

Recorrer un fichero es mucho más sencillo que eso. Los ficheros tienen flags, como eof, para indicar el estado del mismo... para imprimir el contenido de un fichero basta con recorrerlo hasta que el flag eof esté activo:

Código C:
Ver original
  1. int mostrarArchivo(FILE *f){
  2.   Amigo aux;
  3.   int seguir = 1;
  4.   do
  5.   {
  6.     fread (&aux,sizeof(Amigo),1, f);
  7.     if( seguir = !feof(f) )
  8.       mostrarAmigo(aux);
  9.   } while(seguir);
  10. }

Nota que el flag eof se consulta después de realizar la lectura... esto es porque ese flag no se activa hasta que no se realiza una lectura fallida (entiéndase por fallida que se sobrepasa de alguna forma el final del fichero).

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #7 (permalink)  
Antiguo 28/07/2016, 14:24
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Respuesta: Archivos y Listas enlazadas simples en C

Gracias eferion por responder!.
Estuve haciendo el programa, tratando de mejorar un poco el codigo..
Todos los consejos son aceptados!. Gracias!

Código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ANCHO_PANTALLA 80			//Maximo de caracteres en la pantalla
#define Max 26						//Arreglo Indice Apellido

typedef struct TipoFecha{
	int dia;
	int mes;
	int anio;
}TFecha;

typedef struct TipoAmigo{
	char apellido[17];
	char nombre[17];
	char email[20];
	char celular[12];
	TFecha fecNac;
	char flag;
}Amigo;

typedef struct ElementoLista{
  Amigo  dato;
  struct ElementoLista *sig;
}Persona;

typedef struct ListaIdentificar {
    Persona *inicio;
    Persona *fin;
    int cantidad;
}Lista;

typedef struct {
	char letra;
	int pos;
	int cantidad;
}Indice;


//MENU PRINCIPAL
int menu(char *nombreArchivo,char *nombreArchivoIndice, Lista *lista);
//devuelve la opcion elegido
int mostrarMenu();

//Guarda contacto en el archivo
void guardarContacto(Amigo persona, char *nombreArchivo);



								//----Guarda los datos en el archivo
								
								
								
int actualizarArchivo(char *nombreArchivo,Lista *lista);
//Pasa los datos de la lista al archivo
int listaArchivo(Lista *lista, char *nombreArchivo);
//Pasa los datos del archivo a la lista
void archivoLista(char *NombreArchivo, Lista *lista);
//Une 2 listas y las ordena
void unirListas(Lista *lista,Lista *aux);
//Borra los datos y libera la memoria
void destruir(Lista *lista);
//Suprime un dato de la lista
int suprimirInicio (Lista *lista); //de acuerdo al campo flag=='*'
//devuelve el tamaño del archivo
int tamanioArchivo(char *nombreArchivo);
//Muestra los datos guardados en el archivo
void mostrarAgenda(char *nombreArchivo);



int suprimirAmigo(Lista *lista,Amigo p);
		//REGISTRAR EN EL LOGFILE

/*
						-------FUNCIONES MANEJO DE LISTA DINAMICA (Area de Intercambio)
*/
//Inserta un dato al inicio de la lista en la memoria dinamica
int insertarInicio (Lista *lista,Amigo p);
//devuelve los datos de un amigo que llena el usuario
Amigo pedirAmigo();
//Pide la fecha y la devuelve
TFecha ingresarFecha(Amigo aux);
//agrega un amigo a la lista
int agregarAmigo(Lista *lista,char *nombreArchivo);
//revisa la lista para ver si encuentra datos
int estaAmigoLista(Lista *l,Amigo p);
//revisa el archivo para ver si encuentra datos
int estaAmigoArchivo(char *nombreArchivo,Amigo p);
//actualiza el archivo. Agrega datos de la lista y ordena el archivo
//ordena la lista por apellido y nombre
int ordenar(Lista *l);


						//Funciones de Muestra
//Muestra un titulo con los datos de amigo (tipo Tabla)
void tipoTabla();
//Muestra un titulo con los datos de indice (tipo Tabla)
void tipoTablaIndice();
//Muestra los datos de la Lista
void mostrarDatos(Lista *lista);
//Muestra los datos de un amigo
void mostrarAmigo(Amigo p);
//Muestra un titulo en el medio
void mostrarTituloMenu(char *titulo);
//Muestra un mensaje de error
void mostrarMensajeCentro(char *msj);
//Muestra los datos del archivo indice
void mostrarArchivoIndice(char* nombreArchivoIndice);
//Muestra los datos de un elem del archivo indice
void mostrarLetra(Indice indice);


//Muestra los apellidos que comiencen con una letra "x"
//dados una posicion y la cantidad a mostrar, se mueve en el archivo principal y muestra los datos
void mostrarArchivoApellido(char *nombreArchivo,int pos,int cant);
/*Listar amigos cuyo apellido comienza con una determinada letra.*/
void MostrarApellidoInicial(char *nombreArchivo,char *nombreArchivoIndice,char c);
//Inicializa el arreglo indice
void inicializar(Indice indice[]);
//Pasa del arreglo al arch
void arregloArchivoIndice(char *nombreArchivoIndice,Indice indice[]);
//Guarda un dato en el archivo INDICE
void guardarIndice(char *nombreArchivoIndice,Indice ind);
/*
Listar amigos que cumplen años un determinado mes: el mes será ingresado por
el usuario. Mostrar los registros en formato tabla.
*/
//falta
void MostrarCumpleMes(Lista *lista,int mes);


int main(){
	char nombreArchivo[12]= "agenda.bin";
	char nombreArchivoIndice[12]= "indice.bin";
	Lista *lista;
	if ((lista = (Lista *) calloc (1,sizeof(Lista))) == NULL){
	    return -1;
	}
	menu (nombreArchivo,nombreArchivoIndice,lista);
	return 0;
}



int mostrarMenu(){
	int opc;
	do{
		mostrarTituloMenu("MENU GENERAL");
		printf("\n1) Agregar Amigo al Area de transacciones.");
		printf("\n2) Mostrar Area de transacciones.");
		printf("\n3) Actualizar Archivo agenda.");
		printf("\n4) Mostrar Archivo agenda.");
		printf("\n5) Mostrar contactos con la inicial ""x"" en el apellido.");
		printf("\n6) Mostrar contactos que cumplan anios determinado mes.");
		printf("\n7) Buscar contacto.");
		printf("\n8) Borrar contacto.");
		printf("\n9) Eliminar Archivos.");
		printf("\n10) Salir.");
		printf("\n\nElige una opcion: ");
		scanf("%d",&opc);
	}while (opc<1 || opc>10);
	return opc;
}

void mostrarTituloMenu(char *titulo){
	system("cls");
    printf("%*s\n\n\n", ANCHO_PANTALLA/2 + strlen(titulo)/2, titulo);
}

void mostrarMensajeCentro(char *msj){
    printf("\n\n\n\n\n%*s\n\n\n", ANCHO_PANTALLA/2 + strlen(msj)/2, msj);
}


void presUnaTecla(){
	mostrarMensajeCentro("Presione una tecla para continuar."); 
	getch(); 	
}


int menu(char *nombreArchivo,char *nombreArchivoIndice, Lista *lista){
	int pos,control,opc;
	char car;
    do{
		opc=mostrarMenu();
	    switch (opc){
    	case 1:
    		control=agregarAmigo(lista,nombreArchivo);
    		if(control==0){
    			printf("\n\nSe ha hecho correctamente");
    			ordenar(lista);
			}else if(control==-1){
				mostrarMensajeCentro("Hubo un error. El amigo se encuentra en la lista.");
			}else{
				mostrarMensajeCentro("Hubo un error. El amigo se encuentra en el archivo.");
			}
			break;
		case 2:
			mostrarTituloMenu("AMIGOS EN AREA DE TRANSACCIONES");
			if(lista->cantidad!=0){
				tipoTabla();
				mostrarDatos(lista);
				printf("\n\n\n\n");
			}else
				mostrarMensajeCentro("Lista Vacia.");
			break;
		case 3:
			if (actualizarArchivo(nombreArchivo,lista)!=-1){
				formarIndice(nombreArchivo,nombreArchivoIndice);
				destruir(lista);
			}
			break;
		case 4:
			if(tamanioArchivo(nombreArchivo)!=0){
				mostrarTituloMenu("AMIGOS EN ARCHIVO");
				mostrarAgenda(nombreArchivo);
				printf("\n\n\n\n");
			}else{
				mostrarMensajeCentro("Archivo Vacio.");
			}
			break;
		case 5:
			mostrarTituloMenu("AMIGOS POR INICIAL");
			printf("\nIngrese una letra:");
			do{
				fflush(stdin);
				scanf("%c",&car);
			}while(car<65 || (car>90 && car<97)|| car>122);
			if (car>97 || car<122) car=car-32;					//Si no es mayuscula, la transforma en mayuscula
			printf("\n\n\n");
			MostrarApellidoInicial(nombreArchivo,nombreArchivoIndice,car);
			break;
		case 6:
			printf("\nEn construccion");
			break;
		case 7:
			printf("\nEn construccion");
			break;
		case 8:
			printf("\nEn construccion");
			break;
		case 9:
			remove(nombreArchivo);
			remove(nombreArchivoIndice);
			mostrarMensajeCentro("Los archivos se borraron efectivamente.");
			break;
		case 10:
			printf ("\nAdios");
			break;
		}
		//
		presUnaTecla();
	} while (opc!=10);
	
}



int agregarAmigo(Lista *lista,char *nombreArchivo){
	Amigo amigo=pedirAmigo();
	int encontrado=(estaAmigoLista(lista,amigo));
	if (estaAmigoLista(lista,amigo)==-1){
		return -1;
	}else if((estaAmigoArchivo(nombreArchivo,amigo))==-1)
		return -2;
	else{
		insertarInicio(lista,amigo);
		return 0;
	}
}


Amigo pedirAmigo(){
	Amigo aux;
	system("cls");
	mostrarTituloMenu("MENU DE CARGA DE DATOS");
	do{
		printf("\nIngrese el apellido de su amigo.\n");
		fflush(stdin);
        gets(aux.apellido);
	}while (strlen(aux.apellido)>17);
		do{
		printf("\nIngrese el nombre de su amigo.\n");
		fflush(stdin);
        gets(aux.nombre);
	}while (strlen(aux.nombre)>17);
		do{
		printf("\nIngrese el email de su amigo.\n");
		fflush(stdin);
        gets(aux.email);
	}while (strlen(aux.email)>30);
		do{
		printf("\nIngrese el celular de su amigo.\n");
		fflush(stdin);
        gets(aux.celular);
	}while (strlen(aux.celular)>15);
	printf("\nFecha de nacimiento de su amigo:\n");
	aux.fecNac=ingresarFecha(aux);
	aux.flag=' ';
	return aux;
}

int esBisiesto(int a){
	return (a%4==0 && a%100!=0) || (a%400==0);
}

TFecha ingresarFecha(Amigo aux){
	int d;
	do{	
		printf("\nIngrese el anio de nacimiento: [1900..2016]\n");
		scanf("%i",&aux.fecNac.anio);
	}while ((aux.fecNac.anio>2016)||(aux.fecNac.anio<1900));
	do{	
		printf("\nIngrese el mes de nacimiento:\n");
		scanf("%i",&aux.fecNac.mes);
	}while ((aux.fecNac.mes>12)||(aux.fecNac.mes<1));
	d=(topeDias(aux.fecNac.mes,aux.fecNac.anio));
	do{	
		printf("\nIngrese el dia de nacimiento:[1..%d]\n",d);
		scanf("%i",&aux.fecNac.dia);
	}while ((aux.fecNac.dia>d)||(aux.fecNac.dia<1));
	return aux.fecNac;
}

int topeDias(int mes,int anio){
	if((mes==1)||(mes==3)||(mes==5)||(mes==7)||(mes==8)||(mes==10)||(mes==12)){
		return 31;
	}else if((mes==4)||(mes==6)||(mes==9)||(mes==11)){
		return 30;
	}else if((mes==2)&&esBisiesto(anio)){
		return 29;
	}else{
		return 28;
	}
}


int estaAmigoLista(Lista *lista,Amigo p){
  int existe = 0;
  Persona *aux;
  for(aux=lista->inicio; aux && !existe; aux=aux->sig){
    existe = (strcmpi(aux->dato.apellido,p.apellido)==0);
    existe &= (strcmpi(aux->dato.nombre,p.nombre)==0);
    existe &= (strcmpi(aux->dato.email,p.email)==0);
    existe &= (strcmpi(aux->dato.celular,p.celular)==0);
    existe &= (aux->dato.fecNac.anio==p.fecNac.anio);
    existe &= (aux->dato.fecNac.mes==p.fecNac.mes);
    existe &= (aux->dato.fecNac.dia==p.fecNac.dia);
  }
  return existe;
}
SIGUE EN OTRO COMENTARIO
  #8 (permalink)  
Antiguo 28/07/2016, 14:25
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Respuesta: Archivos y Listas enlazadas simples en C

CONTINUA..

Código:
//revisa el archivo para ver si encuentra datos
int estaAmigoArchivo(char *nombreArchivo,Amigo p){
	FILE *file=fopen(nombreArchivo,"rb");
	int existe = 0;
	Amigo amigo;
	while(fread(&amigo, sizeof(Amigo), 1, file)){
	    existe = (strcmpi(amigo.apellido,p.apellido)==0);
	    existe &= (strcmpi(amigo.nombre,p.nombre)==0);
	    existe &= (strcmpi(amigo.email,p.email)==0);
	    existe &= (strcmpi(amigo.celular,p.celular)==0);
	    existe &= (amigo.fecNac.anio==p.fecNac.anio);
	    existe &= (amigo.fecNac.mes==p.fecNac.mes);
	    existe &= (amigo.fecNac.dia==p.fecNac.dia);
	}
	fclose(file);
	return existe;
}


int insertarInicio(Lista *lista, Amigo p){
  int toReturn = 0; // 0 = error
  Persona *aux = (Persona *) malloc (sizeof (Persona));
  if (aux != NULL){
    aux->dato=p;
    aux->sig=lista->inicio;
    lista->inicio=aux;
    lista->cantidad++;
    // Por si acaso la lista está vacía
    if( !lista->fin ) lista->fin = aux;
    toReturn = 1; // 1 = ok
  }
  return toReturn;
}

void tipoTabla(){
	printf("%-15s %-15s %-15s %-12s %-10s\n\n","APELLIDO","NOMBRE","EMAIL","CELULAR","DD/MM/AAAA");
}


void mostrarAmigo(Amigo p){
	printf("%-15s %-15s %-15s %-12s %i/%i/%i\n",p.apellido,p.nombre,p.email,p.celular,p.fecNac.dia,p.fecNac.mes,p.fecNac.anio);
}


void mostrarDatos(Lista *lista){
	Persona *aux=lista->inicio;;
	while (aux){
		mostrarAmigo(aux->dato);
		aux=aux->sig;
	}
}


int ordenar(Lista *lista){
	int pos=1;
	Amigo cam;
	if(lista->cantidad==1){
		return 0;
	}else{
		Persona *aux,*aux2,*min;
		min=lista->inicio;
		while(pos<lista->cantidad){
			aux=min;
			aux2=min->sig;
			while(aux2!=NULL){
				if((strcmpi(aux->dato.apellido,aux2->dato.apellido))>0){	//se comparan apellidos
					aux=aux2;											//se compara el nombre 
				}else if(((strcmpi(aux->dato.apellido,aux2->dato.apellido))==0)&&((strcmpi(aux->dato.nombre,aux2->dato.nombre))>0)){ 
					aux=aux2;
				}
				aux2=aux2->sig;		
			}
			cam=min->dato;
			min->dato=aux->dato;
			aux->dato=cam;
			min=min->sig;
			pos++;
		}
		return 0;
	}
}


void destruir (Lista *lista){
    while (lista->cantidad > 0){
        suprimirInicio (lista);
    }
}

/* eliminación al inicio de la lista */
int suprimirInicio (Lista *lista){
    if (lista->cantidad == 0){
        return -1;
    }
    Persona *supElemento;
    supElemento = lista->inicio;
    lista->inicio = lista->inicio->sig;
    if (lista->cantidad == 1){
        lista->fin = NULL;
        lista->inicio=NULL;
    }
    free (supElemento);
    lista->cantidad--;
    return 0;
}

int listaArchivo(Lista *lista, char *nombreArchivo){
	if(lista->cantidad!=0){
		Persona *aux=lista->inicio;
		while (aux){
			if(aux->dato.flag!='*'){
				guardarContacto(aux->dato,nombreArchivo);
				aux=aux->sig;
			}
		}
		return 0;
	}else{
		return -1;
	}
}

void unirListas(Lista *lista,Lista *aux){
	if(aux->cantidad!=0){
		Persona *recorrer=aux->inicio;
		while(recorrer){
			insertarInicio(lista,recorrer->dato);
			recorrer=recorrer->sig;
		}
		ordenar(lista);
	}
}

int tamanioArchivo(char *nombreArchivo){
	FILE *file=fopen(nombreArchivo,"ab");
	fseek(file, 0, SEEK_END);
	int a=ftell(file)/sizeof(Amigo);
	fclose(file);
	return a;
}


int actualizarArchivo(char *nombreArchivo,Lista *lista){
	if(tamanioArchivo(nombreArchivo)!=0){
		Lista *aux;
		if ((aux = (Lista *) calloc (1,sizeof(Lista))) == NULL){
			mostrarMensajeCentro("Error de Memoria.");
	    	return -1;
		}
		archivoLista(nombreArchivo,aux);
		if(remove(nombreArchivo)!=-1){
			unirListas(lista,aux);							//une, ordena
			listaArchivo(lista,nombreArchivo);
			destruir(aux);
		}
	}else if(tamanioArchivo(nombreArchivo)==0){
			if (listaArchivo(lista,nombreArchivo)==-1){
				mostrarMensajeCentro("No hay elementos para guardar.");
				return -1;
			}
	}
}

//CORREGIR ESTO

void archivoLista(char *nombreArchivo, Lista *aux){
	FILE* file= fopen(nombreArchivo, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }else{
        Amigo amigo;
        rewind(file);        
        while(fread(&amigo, sizeof(Amigo), 1, file)){
            if(amigo.flag!='*'){
				insertarInicio(aux,amigo);
        	}
		}
        fclose(file);
    }
}


void guardarContacto(Amigo persona, char* nombreArchivo){
    FILE* file= fopen(nombreArchivo, "ab");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        fwrite(&persona, sizeof(Amigo), 1, file);
        fclose(file);
    }
}


void mostrarAgenda(char* nombreArchivo){
    FILE* file= fopen(nombreArchivo, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
    	tipoTabla();
        Amigo persona;
        while (fread(&persona, sizeof(Amigo), 1, file)){
            if(persona.flag!='*'){
				mostrarAmigo(persona);
			}
        }
        fclose(file);
        printf("\n\n");
    }
}


void inicializar(Indice indice[]){
	int i;
	for (i=0;i<Max;i++){
		indice[i].letra=(17+i)+48;
		indice[i].pos=-1;
		indice[i].cantidad=0;
	}
}


int tamanioArchivoIndice(char *nombreArchivoIndice){
	FILE *file=fopen(nombreArchivoIndice,"ab");
	fseek(file, 0, SEEK_END);
	int a=ftell(file)/sizeof(Indice);
	fclose(file);
	return a;
}


int formarIndice(char *nombreArchivo,char *nombreArchivoIndice){
	Indice indice[Max];
	inicializar(indice);
	Amigo persona;
	char inic;
	int t=tamanioArchivoIndice(nombreArchivo),j=0,encontrado,i=0;
	FILE *file=fopen(nombreArchivo,"rb");
	while(fread(&persona, sizeof(Amigo), 1, file)){
		inic=persona.apellido[0];
		if (inic>97 || inic<122) inic=inic-32;					//Si no es mayuscula, la transforma en mayuscula
		encontrado=0;
		while(i<Max && encontrado!=1){
			if((indice[i].letra==inic)&&(indice[i].pos==-1)){
				indice[i].pos=j;
				indice[i].cantidad=indice[i].cantidad+1;
				encontrado=1;
			}else if((indice[i].letra==inic)&&(indice[i].pos!=-1)){
				indice[i].cantidad++;
				encontrado=1;
			}else{
				i++;
			}
		}
		j++;
	}
	fclose(file);
	remove(nombreArchivoIndice);
	arregloArchivoIndice(nombreArchivoIndice,indice);
}

void arregloArchivoIndice(char *nombreArchivoIndice,Indice indice[]){
	int i;
	for (i=0;i<Max;i++){
		guardarIndice(nombreArchivoIndice,indice[i]);
	}
}

void guardarIndice(char *nombreArchivoIndice,Indice ind){
    FILE* file= fopen(nombreArchivoIndice, "ab");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        fwrite(&ind, sizeof(Indice), 1, file);
        fclose(file);
    }
}
//LLENAR EL ARCHIVO INDICE!

void tipoTablaIndice(){
	printf("%-10s %-15s %-15s\n\n","LETRA","POSICION","CANTIDAD");
}

//Muestra uno
void mostrarLetra(Indice ind){
	if(ind.cantidad!=0)	printf("%-10c %-15d %-15d\n\n",ind.letra,ind.pos,ind.cantidad);
}

//Muestra el arreglo indice (No se usa, solo era para probar)
void mostrarArregloIndice(Indice indice[]){
	int i;
	tipoTablaIndice();
	for (i=0;i<Max;i++){
		mostrarLetra(indice[i]);
	}
}

//Muestra el archivo indice (No se usa, solo era para probar)
void mostrarArchivoIndice(char* nombreArchivoIndice){
    FILE* file= fopen(nombreArchivoIndice, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        Indice indice;
        while (fread(&indice, sizeof(Indice), 1, file)){
			mostrarLetra(indice);
    	}
        fclose(file);
    }
}

//Dada una pos y una cantidad, muestra contactos desde una posicion avanzando tanto como cant haya
void mostrarArchivoApellido(char *nombreArchivo,int pos,int cant){
	FILE *file=fopen(nombreArchivo,"rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
    	int i,elem;
    	if (cant!=0){
    		elem=pos;
    		tipoTabla();
	    	for (i=pos;i<pos+cant;i++){
		    	Amigo amigo;
		    	fseek (file, (elem)*sizeof(Amigo), SEEK_SET);
		        fread(&amigo, sizeof(Amigo), 1, file);
				mostrarAmigo(amigo);
				elem++;
			}
		}else{
			mostrarMensajeCentro("No hay amigos con esa inicial.");
		}
        fclose(file);
        printf("\n\n");
	}	
}

//Muestra los contactos dependiendo de la letra inicial
void MostrarApellidoInicial(char *nombreArchivo,char *nombreArchivoIndice,char c){
	c=c-65;
	FILE *file=fopen(nombreArchivo,"rb");
		if (tamanioArchivo(nombreArchivo)==0){
			mostrarMensajeCentro("Archivo Vacio");
		fclose(file);
	}else{
		FILE *fileInd=fopen(nombreArchivoIndice,"rb");
		if (fileInd==NULL){
			mostrarMensajeCentro("Error al intentar acceder al archivo");
	    }else{
			Indice ind;
			fseek(fileInd,(c)*sizeof(Indice),SEEK_SET);
			fread(&ind,sizeof(Indice),1,fileInd);
			fclose(fileInd);
			mostrarArchivoApellido(nombreArchivo,ind.pos,ind.cantidad);
		}
	}
}
  #9 (permalink)  
Antiguo 29/07/2016, 04:36
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 5 años, 2 meses
Puntos: 204
Respuesta: Archivos y Listas enlazadas simples en C

Código C:
Ver original
  1. while(fread(&amigo, sizeof(Amigo), 1, file)){
  2.     existe = (strcmpi(amigo.apellido,p.apellido)==0);
  3.     existe &= (strcmpi(amigo.nombre,p.nombre)==0);
  4.     existe &= (strcmpi(amigo.email,p.email)==0);
  5.     existe &= (strcmpi(amigo.celular,p.celular)==0);
  6.     existe &= (amigo.fecNac.anio==p.fecNac.anio);
  7.     existe &= (amigo.fecNac.mes==p.fecNac.mes);
  8.     existe &= (amigo.fecNac.dia==p.fecNac.dia);
  9. }

Si el fichero tiene 2 registros y el buscado es el primero la función te va a decir que no existe el registro.

El while tiene que tener como condición adicional el chequeo de existe para parar si se localiza el registro:

Código C:
Ver original
  1. while(!existe && fread(&amigo, sizeof(Amigo), 1, file)){
  2.     existe = (strcmpi(amigo.apellido,p.apellido)==0);
  3.     existe &= (strcmpi(amigo.nombre,p.nombre)==0);
  4.     existe &= (strcmpi(amigo.email,p.email)==0);
  5.     existe &= (strcmpi(amigo.celular,p.celular)==0);
  6.     existe &= (amigo.fecNac.anio==p.fecNac.anio);
  7.     existe &= (amigo.fecNac.mes==p.fecNac.mes);
  8.     existe &= (amigo.fecNac.dia==p.fecNac.dia);
  9. }

Y sigo sin entender la utilidad del contador de elementos de la lista:

Código C:
Ver original
  1. /* eliminación al inicio de la lista */
  2. int suprimirInicio (Lista *lista){
  3.     if (lista->cantidad == 0){
  4.         return -1;
  5.     }
  6.     Persona *supElemento;
  7.     supElemento = lista->inicio;
  8.     lista->inicio = lista->inicio->sig;
  9.     if (lista->cantidad == 1){
  10.         lista->fin = NULL;
  11.         lista->inicio=NULL;
  12.     }
  13.     free (supElemento);
  14.     lista->cantidad--;
  15.     return 0;
  16. }

Cuando queda más sencillo así:

Código C:
Ver original
  1. /* eliminación al inicio de la lista */
  2. int suprimirInicio (Lista *lista){
  3.   // ¿Por qué -1? si no hace nada lo lógico sería retornar 0, equivalente natural de false
  4.   int   toReturn = -1;
  5.  
  6.   if (lista->inicio){
  7.     Persona *sig = lista->inicio->sig;
  8.     free(lista->inicio);
  9.     lista->inicio = sig;
  10.     lista->cantidad--;
  11.  
  12.     if( !sig->sig )
  13.       lista->fin = NULL;
  14.  
  15.     toReturn = 0; // ¿Por qué 0? siguiendo el planteamiento análogo debería ser 1
  16.   }
  17.  
  18.   return toReturn;
  19. }

Pero es que, en una lista enlazada simple yo iría aún más lejos y eliminaría el puntero al último elemento de la lista. Recorrer una lista enlazada es relativamente rápido salvo que tenga millones y millones de elementos y mantener este segundo puntero que únicamente sirve como ayuda a la hora de añadir elementos al final de la lista no aporta demasiado:

Código C:
Ver original
  1. /* eliminación al inicio de la lista */
  2. int suprimirInicio (Lista *lista){
  3.   // ¿Por qué -1? si no hace nada lo lógico sería retornar 0, equivalente natural de false
  4.   int   toReturn = -1;
  5.  
  6.   if (lista->inicio){
  7.     Persona *sig = lista->inicio->sig;
  8.     free(lista->inicio);
  9.     lista->inicio = sig;
  10.  
  11.     toReturn = 0; // ¿Por qué 0? siguiendo el planteamiento análogo debería ser 1
  12.   }
  13.  
  14.   return toReturn;
  15. }

Y, bueno, como consejo adicional, para gestionar valores booleanos todos sabemos que en C no hay ningún tipo nativo que se encargue de ello. Sin embargo, tenemos la cabecera <stdbool.h> que incluye dicho tipo, lo que permite tener código más legible. Lo que hace esa cabecera es crear el tipo bool a partir de int y definir los valores true y false.

Un ejemplo compilable en C:

Código C:
Ver original
  1. #include <stdbool.h>
  2.  
  3. int main(void) {
  4.     bool continuar = true;
  5.     while(continuar) {
  6.       printf("Pulse 0 para terminar...\n");
  7.       scanf("%d",continuar);
  8.     }
  9.     printf("FIN!!!\n");
  10. }

Deberías plantearte usar esta librería para sustituir la lógica booleana que tienes actualmente implementada en tu aplicación.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #10 (permalink)  
Antiguo 29/07/2016, 10:43
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Respuesta: Archivos y Listas enlazadas simples en C

Gracias por la respuesta eferion..
Aca lo corregi y arregle lo que me aconsejaste..

[URL="http://codepaste.net/5iie7v"]http://codepaste.net/5iie7v[/URL]

En algunas le agregue lo de bool..
la pregunta es, a que mas se lo agregaria?.
En cuanto a la busqueda, algun consejo?, el borrado de algun elemento?
y quiero agregarle que muestre los que nacen en "marzo" por ejemplo..
El archivo esta ordenado por apellido..
tendria que hacer un archivo aparte ordenado por mes o que manera seria mas apropiada..

La idea, es aprender lo basico haciendo este ejercicio y despues implementarlo en otros proyectos.. Practicar..

gracias por la ayuda!. Es bueno saber que hay gente como vos dispuesta a brindar su conocimiento..

Última edición por matiri90; 30/07/2016 a las 07:10 Razón: Borrar informacion que no se necesitaba
  #11 (permalink)  
Antiguo 06/08/2016, 14:03
 
Fecha de Ingreso: abril-2016
Ubicación: Cordoba
Mensajes: 19
Antigüedad: 3 años, 7 meses
Puntos: 0
Respuesta: Archivos y Listas enlazadas simples en C

Buenas. Estuve mejorando un poco el programa.. Creo que ha quedado bastante bien..

[URL="http://codepaste.net/zm6v4s"]http://codepaste.net/zm6v4s[/URL]

http://codepaste.net/zm6v4s

Etiquetas: enlazadas, ficheros, listas, simples
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




La zona horaria es GMT -6. Ahora son las 11:38.