[ Foro de C ]

agenda en la seccion de ficheros.

11-Jul-2013 17:51
Jose Manuel Illanes Juan
3 Respuestas

Buenas estoy en la seccion de ficheros y me he encontrado con el ejercicio 6.4.3 que dice lo siguiente.

Una agenda que maneje los siguientes datos: nombre, dirección, tlf móvil, email, y día,
mes y año de nacimiento (estos tres últimos datos deberán ser números enteros cortos).
Deberá tener capacidad para 100 fichas. Se deberá poder añadir un dato
nuevo, visualizar los nombres de las fichas existentes, o mostrar todos los datos de una
persona (se preguntará al usuario cual es el nombre de esa persona que quiere
visualizar). Al empezar el programa, leerá los datos de un fichero llamado ?agenda.dat?
(si existe). Al terminar, guardará todos los datos en ese fichero.

Mi codigo fuente es el siguiente:

 
#include<stdio.h>
#include<string.h>
 
main()
{
 
	struct{
	char nombre[80],direccion[100];
	int movil;
	char email[50];
	int dia,mes,anno;
	}agenda[100];
	int ficha=0;/*lo utilizaremos para saber cuantas personas llevamos registradas en la agenda*/
 
	FILE* fichero;
	int i; /*lo utilizaremos de contador*/
	int opcion;/*se utiliza para saber que opción del menu ha elegido el usuario*/
	char textoTemporal[100];
 
/*lo primero que hay que hacer cada vez que abrimos el programa es comprobar si ya había datos 
introducidos con anterioridad. Si es asi debemos recopilarlos*/
 
	fichero=fopen("agenda.dat","rt");
	if(fichero != NULL);
	{
		while(!feof(fichero)){
 
	fscanf(fichero,"%s.\n",agenda[ficha].nombre);
	if(!feof(fichero))
	printf("%s.\n",agenda[ficha].nombre);
 
	fscanf(fichero,"%s.\n",agenda[ficha].direccion);
	if(!feof(fichero))
	printf("%s.\n",agenda[ficha].direccion);
 
	fscanf(fichero,"%d.\n",&agenda[ficha].movil);
	if(!feof(fichero))
	printf("%d.\n",agenda[ficha].movil);
 
	fscanf(fichero,"%s.\n",agenda[ficha].email);
	if(!feof(fichero))
	printf("%s.\n",agenda[ficha].email);
 
	fscanf(fichero,"%d/%d/%d.\n",&agenda[ficha].dia,
	&agenda[ficha].mes,&agenda[ficha].anno);	
	if(!feof(fichero))
	printf("%d/%d/%d.\n",agenda[ficha].dia,agenda[ficha].mes,agenda[ficha].anno);
 
	ficha++;
		}/*con esta llave se cierra el while*/
	fclose(fichero);
	}/*con esta llave cerramos el if*/
 
	printf("Leidos %d datos.\n",ficha+1);
 
	do
	{
	printf("¿Qué quieres hacer?\n"
	"Pulsa 1 para introducir un nuevo contacto en la agenda\n"
	"Pulsa 2 para ver los nombres de las fichas existentes\n"
	"Pulsa 3 para ver los datos de una persona introduciendo su nombre\n"
	"Pulsa 0 para salir del programa\n");
	gets(textoTemporal);
	sscanf(textoTemporal,"%d",&opcion);
 
	switch(opcion){
 
	case 1:/*introducir un nuevo dato*/
	/*abrimos el fichero*/
	fichero=fopen("agenda.dat","at");		
	if( fichero== NULL)
	printf("Se ha creado el fichero.No existia");
 
	/*introducimos todos los datos que queremos que tenga la agenda*/
		printf("¿Como se llama la persona que quieres añadir"
	" a la agenda?");
		gets(agenda[ficha].nombre);
		fprintf(fichero,"%s\n",agenda[ficha].nombre);
 
		printf("¿Cual es la dirección?");
		gets(agenda[ficha].direccion);
		fprintf(fichero,"%s\n",agenda[ficha].direccion);
 
		printf("Su número de movil es:");
		gets(textoTemporal);
		sscanf(textoTemporal,"%d\n",&agenda[ficha].movil);	
		fprintf(fichero,"%d\n",agenda[ficha].movil);
 
		printf("Su email:");
		gets(agenda[ficha].email);
		fprintf(fichero,"%s\n",agenda[ficha].email);
 
		printf("¿Qué día nació?");
		gets(textoTemporal);
		sscanf(textoTemporal,"%d\n",&agenda[ficha].dia);
		fprintf(fichero,"%d\n",agenda[ficha].dia);
 
		printf("¿En que mes?");
		gets(textoTemporal);
		sscanf(textoTemporal,"%d\n",&agenda[ficha].mes);
		fprintf(fichero,"%d\n",agenda[ficha].mes);
 
		printf("Y por último, ¿en que año?");
		gets(textoTemporal);
		sscanf(textoTemporal,"%d\n",&agenda[ficha].anno);
		fprintf(fichero,"%d\n",agenda[ficha].anno);
 
		ficha++;/*sumamos un numero a la variable persona para saber que hemos guardado una persona mas*/	
	/*cerramos el fichero*/
	fclose(fichero);
		break;
 
 
	case 2:/*ver los nombres de todas las fichas existentes*/
	fichero=fopen("agenda.dat","rt");
	for(i=0;i<ficha;i++)
	printf("Persona numero %d; El nombre es: %s.\n",
	i+1,agenda[i].nombre);
	fclose(fichero);
	break;
 
 
	case 3:/*ver los datos de una persona introduciendo su nombre*/
	printf("Introduce el nombre de la persona de la que"
	" quieres ver todos los datos.");
	gets(textoTemporal);
	fichero=fopen("agenda.dat","rt");
	for(i=0;i<ficha;i++){
	if(strcmp(agenda[i].nombre,textoTemporal)==0)
	printf("Los datos de la persona son:"
	"Nombre: %s.\n"
	"Direccion: %s.\n"
	"Movil: %d.\n"
	"Email: %s.\n"
	"Fecha nacimiento: %d/%d/%d.\n",agenda[i].nombre,agenda[i].direccion,
	agenda[i].movil,agenda[i].email,agenda[i].dia,agenda[i].mes,
	agenda[i].anno);
	}
	fclose(fichero);
	break;
 
	case 0:/*salir del programa*/
	printf("Muchas gracias por confiar en nuestra compañia, hasta la próxima.\n");
	break;
 
	default: 
	printf("Opcion no conocida, introduce de nuevo la opción.\n");
	break;
		}/*con esta llave cerramos el switch*/
	}while(opcion!=0); /*asi cerramos el do*/
}
 



Debo decir dos cosas la primera es que no entiendo muy bien la primera parte antes de entrar en el menu, es decir cuando lee los datos que ya están en el fichero agenda.dat.
No sabia como hacerlo asi que buscando en el foro encontré ese modelo y lo copie.
Pero al hacer esto el programa no funciona. Al compilar no da problemas pero cuando lo quiero usar no me deja pone:

Violación de segmento (`core' generado)

No tengo ni idea de lo que es esto. Soy licenciado en Física y mis conocimientos sobre informatica no llegan para saber que significa esto. Si me lo puedes explicar te lo agradeceria mucho.

por otra parte la tercera opcion del menu la de buscar un dato por el nombre de la persona tampoco funciona.

Si puedes revisarme el código y sugerirme mejoras te lo agradecería mucho.

Por cierto muchas gracias por tu ayuda desinteresada se necesita mas gente así en este planeta.

Un Saludo.

Jose Manuel Illanes Juan.


13-Jul-2013 19:31
Nacho Cabanes (+31)

Por partes:

- Lo de leer los datos se puede hacer de varias formas, pero en cualquier caso deberías guardar los datos automáticamente al terminar una sesión y recuperarlos al principio de la siguiente. Espero que la duda no sea ese concepto general, sino la forma concreta en que está hecho en ese fuente. En ese caso, no tengas reparo en preguntar las dudas concretas de "¿por qué esto está hecho así?" (incluyendo el fragmento de fuente que no entiendes)

- La "violación de segmento" surge cuando intentas acceder a una posición de memoria que no te pertenece. Si tu dices "dime el dato que hay en la posición 30.000 de la memoria" y esa posición no pertenece a la memoria accesible por tu usuario, sino que es de otro usuario o del sistema operativo, estás "saliéndote de tu segmento de datos" y tu programa se interrumpirá con ese mensaje de error.

- El motivo más habitual de una "violación de segmento" es que un puntero (o un array) no tiene valor y aun así intentas acceder a él, de modo que puedes estar intentando leer la posición cero o una posición al azar, que probablemente no te pertenecerá. También ocurre sin intentas leer de un fichero que no has abierto.

- En tu caso, lo que tiene el valor 0 (NULL) es la variable "fichero". Mira esta línea:

f(fichero != NULL);


Le sobra el punto y coma final, de modo que si se cumple la condición no hace nada (hace la orden vacía que indica el punto y coma). Por eso, todo lo que hay entre llaves se ejecuta siempre, e intentas leer de un fichero que no existe.

Recomendación: si te ocurre esto, usa el depurador de tu compilador (si ya lo has probado) o incluye varias órdenes "printf" que te indiquen por dónde va pasando tu programa, para ver qué línea concreta está provocando el fallo.


28-Jul-2013 13:17
Jose Manuel Illanes Juan

Creo que tengo un problema de concepto no entiendo muy bien como puede leer un fichero poniendo una direccion que el no tiene porque saber que es eso. Por ejemplo al hacer:

 
fscanf(fichero,"%s.\n",agenda[ficha].nombre);
	if(!feof(fichero))
	printf("%s.\n",agenda[ficha].nombre);
 


¿Porque sabe el programa que solo tiene que leer el nombre si nosotros ya hemos creado eso con anterioridad y no tiene porque saber que lo hemos guardado como agenda[ficha].nombre?

Es decir a ver si consigo explicarme que no es facil.

Nosotros abrimos el programa por primera vez. Introducimos un dato en la agenda y cerramos el programa.

¿Al dia siguiente despues de haber apagado el ordenador, haber dormido... volvemos al programa lo abrimos y como el programa sabe que al meterse en el fichero agenda el nombre sólo es la primera linea?
Es una duda conceptual nose si la he explicado bien pero me sorprende que un ordenador pueda ser tan listo.

Y si llevamos el programa a otro pc y el archivo tambien, ¿sería capaz de hacerlo?

Por otra parte he quitado el ; como me dijiste. Entiendo el error pero al correr el programa ahora me aparece lo siguiente al empezar:

 
Jose.
Manuel.
0.
Calle.
0/0/0.
Jilguero,7.
666298619.
0.
josemaillaxxx@gmaix.com.
4/0/0.
10.
1987.
0.
Encarni.
0/0/0.
illanes.
jilguero.
10.
651942507.
0/0/0.
encarniinxxx@hotmaix.com.
30.
8.
1982.
Leídos 5 datos. 
 


Sólo he introducido dos contactos en la agenda.
Uno con el nombre josemanuel y otro con el nombre encarni sin embargo pone que ha leido 5 datos.Por tanto está sumando más fichas de las que debe. No se porque hace esto ni como solucionarlo.

Además esta el problema del formato de como muestra los datos. No entiendo porque sale asi ni como arreglarlo.

Muchas gracias por la ayuda.

Espero su respuesta.


05-Aug-2013 12:12
Nacho Cabanes (+31)

Decías "¿Porque sabe el programa que solo tiene que leer el nombre si nosotros ya hemos creado eso con anterioridad y no tiene porque saber que lo hemos guardado como agenda[ficha].nombre?"

El motivo es básicamente "porque tú se lo dices". Tú eres quien decide qué va a contener el fichero, en qué orden, y tú eres quien crea un fragmento de programa que guarda los datos en ese orden, y otro fragmento de programa que lee los datos en ese orden.

Es parte de la planificación de un programa: Comienzas con un "necesitaré guardar, el nombre la dirección, el teléfono y el e-mail" (sin ambigüedades). Luego sigues detallando el cómo: "esos datos los guardaré en un fichero de texto, cada dato en una línea distinta". Cuando esos detalles están claros, es cuando creas un programa que manipule esos datos.






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)