[ Foro de C ]

Agenda fread/fwrite

31-Jul-2010 13:19
emuletas yp
3 Respuestas

Hice el ejercicio siguiente:

***************************************************************************
*            agenda.c
*
*  Wed Jul 21 22:41:39 2010
*  Copyright  2010  cesar
*  <cesar@<host>>
****************************************************************************/

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
*/

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

main(){

FILE* fichero;

fichero=fopen("agenda.dat", "rb");

struct{

char nombre[81];
char direccion[81];
char telf[21];
char email[81];
short int dia, mes, anyo;

}ficha[100];

int i, opcionmenu;

int ultimaficha=-1;

char linea[800];

char nom[81];

if(fichero!=NULL){

puts("Leyendo datos...");

while(!feof(fichero)){

fread(ficha[ultimaficha+1].nombre, 1, sizeof(ficha[ultimaficha+1].nombre), fichero);
fread(ficha[ultimaficha+1].direccion, 1, sizeof(ficha[ultimaficha+1].direccion), fichero);
fread(ficha[ultimaficha+1].telf, 1, sizeof(ficha[ultimaficha+1].telf), fichero);
fread(ficha[ultimaficha+1].email, 1, sizeof(ficha[ultimaficha+1].email), fichero);
fread(&ficha[ultimaficha+1].dia, 1, sizeof(ficha[ultimaficha+1].dia), fichero);
fread(&ficha[ultimaficha+1].mes, 1, sizeof(ficha[ultimaficha+1].mes), fichero);
fread(&ficha[ultimaficha+1].anyo, 1, sizeof(ficha[ultimaficha+1].anyo), fichero);

ultimaficha++;

}

fclose(fichero);
printf("Leídos %d contactos\n", ultimaficha+1);

}

do{

printf("AGENDA, por Emuletas\n");
menu:
printf("\nMENÚ\n");
printf("Elige una opción:\n");
printf("1: Añadir un contacto\n");
printf("2: Mostrar contactos\n");
printf("3: Mostrar los datos sobre un contacto\n");
printf("4: Guardar y salir\n");

scanf("%d", &opcionmenu);

getchar();

switch(opcionmenu){

case 1:

puts("Añadiendo datos...");

printf("Nombre: ");

gets(ficha[ultimaficha+1].nombre);

printf("Direccion: ");

gets(ficha[ultimaficha+1].direccion);

printf("Teléfono: ");

gets(ficha[ultimaficha+1].telf);

printf("Dirección Email (max: 35 caract.): ");

gets(ficha[ultimaficha+1].email);

printf("Fecha de nacimiento (formato: día/mes/año) ");

gets(linea);

sscanf(linea, "%hd/%hd/%hd", &ficha[ultimaficha+1].dia, &ficha[ultimaficha+1].mes, &ficha[ultimaficha+1].anyo);

ultimaficha++;

goto menu;

case 2:

printf("Los contactos guardados son:\n");

for(i=0; i<=ultimaficha; i++){

printf("%d:%s\n", i, ficha[i].nombre);

}

goto menu;

case 3:

printf("Escribe el nombre del contacto\n");

scanf("%s", nom);

getchar();

i=0;

for(i=0; i<=ultimaficha+1; i++){

if(strcmp(nom, ficha[i].nombre)==0) {
printf("\n-----------------------------------\n");
printf("Nombre: %s \n", ficha[i].nombre);
printf("Dirección: %s \n", ficha[i].direccion);
printf("Teléfono: %s \n", ficha[i].telf);
printf("Email: %s \n", ficha[i].email);
printf("Fecha de nacimiento: %hd/%hd/%hd ", ficha[i].dia, ficha[i].mes, ficha[i].anyo);
printf("\n-----------------------------------\n");
}

}
goto menu;
}

}while(opcionmenu!=4);

fichero=fopen("agenda.dat","wb");

for(i=0; i<=ultimaficha+1; i++){

fwrite(ficha[ultimaficha+1].nombre, 1, sizeof(ficha[ultimaficha+1].nombre), fichero);
fwrite(ficha[ultimaficha+1].direccion, 1, sizeof(ficha[ultimaficha+1].direccion), fichero);
fwrite(ficha[ultimaficha+1].telf, 1, sizeof(ficha[ultimaficha+1].telf), fichero);
fwrite(ficha[ultimaficha+1].email, 1, sizeof(ficha[ultimaficha+1].email), fichero);
fwrite(ficha[ultimaficha+1].dia, 1, sizeof(ficha[ultimaficha+1].dia), fichero);
fwrite(ficha[ultimaficha+1].mes, 1, sizeof(ficha[ultimaficha+1].mes), fichero);
fwrite(ficha[ultimaficha+1].anyo, 1, sizeof(ficha[ultimaficha+1].anyo), fichero);
}

fclose(fichero);

}

ni funciona, y no se por qué


01-Aug-2010 11:45
Nacho Cabanes (+84)

En general, toma como costumbre dar más detalles: en vez de decir "no funciona", indica el error de compilación que obtienes, o el comportamiento incorrecto que notas cuando lanzas el programa.

Aún así, algunos de los problemas que le veo:

- Falta la barra (/) que abre el comentario inicial.

- Hay declaraciones después de órdenes. En C estándar deberías declarar todas las variables y luego incluir las órdenes ejecutables. Por eso "fichero=fopen("agenda.dat", "rb");" debería estar bastante más abajo, o no compilará con los compiladores más estrictos.

- Al final de cada "case" usas un "goto" en vez de simplemente un "break", con lo que técnicamente, sigues dentro del "switch". Ya que todo el bloque principal está dentro de un "do...while", esos "goto" son innecesarios y pueden dar lugar a errores muy difíciles de encontrar.

- ultimaFicha empieza valiendo 1, y siempre accedes a "ultimaficha+1", por lo que comienzas a guardar datos en la ficha 2, dejando con basura la ficha 0 y la ficha 1.

- Las líneas como "fwrite(ficha[ultimaficha+1].dia, 1, sizeof(ficha[ultimaficha+1].dia), fichero);" no compilarán en la mayoría de compiladores, porque el primer dato no es una dirección de memoria, sino un número entero.

- De hecho, si usas "fread" y "fwrite" sería más práctico guardar todos los campos de golpe, en vez de uno por uno, o incluso las 100 fichas a la vez con una sola orden.


01-Aug-2010 12:28
emuletas yp

- La barra se me coló al copiar y pegar.

-"Por eso "fichero=fopen("agenda.dat", "rb");" debería estar bastante más abajo, o no compilará con los compiladores más estrictos...." Sí compila con gcc.

-El goto fue fallo.

- <<ultimaFicha empieza valiendo 1, y siempre accedes a "ultimaficha+1", por lo que comienzas a guardar datos en la ficha 2, dejando con basura la ficha 0 y la ficha 1>> en que zona? debería usar simplemente ultimaficha? o quizas ultimaficha-1?

- Las líneas como "fwrite(ficha[ultimaficha+1].dia, 1, sizeof(ficha[ultimaficha+1].dia), fichero);" no compilarán en la mayoría de compiladores, porque el primer dato no es una dirección de memoria, sino un número entero.

compilar compila, pero que funcione es otra cosa. que debo hacer?

- como se guarda todo de golpe?¿?

gracias


04-Aug-2010 11:59
Nacho Cabanes (+84)

Por partes:

- Quizá compile con GCC (recuerda indicar la versión), pero no con Borland C++ 5.5, ni por los fwrite, que tienen parámetros de tipo incorrecto, ni por la colocación de "fopen".

- En cualquier caso, ese uso de "fwrite" generará al menos advertencias (warnings) en casi cualquier compilador: revisa esos warnings porque generalmente te avisan de errores que has pasado por alto y que harán que no se comporte correctamente.

- Si deberías usar "ultimaFicha" o "ultimaFicha-1" depende totalmente de cómo lo plantees. En tu caso, parece más natural usar "ultimaFicha-1" porque le das el valor inicial 1, y el primer elemento de un array siempre tiene el índice 0.

- Para guardar todo de golpe, en vez de guardar trozo a trozo con algo como

for(...
 fwrite(ficha[ultimaficha+1].nombre, 1, sizeof(ficha[ultimaficha+1].nombre), fichero);
 ...
 fwrite(ficha[ultimaficha+1].anyo, 1, sizeof(ficha[ultimaficha+1].anyo), fichero);
}

(que, por cierto, tiene otro fallo: no deberías guardar siempre el dato de la posición "ultimaFicha", sino el de la posición "i"), puedes guardar directamente todo el array con

fwrite(ficha, 1, sizeof(ficha), fichero);






(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.)