Autor
|
Tema: Problema en C con la funcion fread y fwrite (Leído 6,314 veces)
|
M01535
Desconectado
Mensajes: 4
|
Buenas, estoy haciendo un ejercicio de programacion en C en el cual tengo que lograr lo siguiente: Crear un "struct" que almacene los siguientes datos de una persona: nombre, edad, ciudad de residencia. Pedir al usuario esos datos de una persona y guardarlos en un fichero llamado "gente1.dat", usando "fwrite". Cerrar el fichero, volverlo a abrir para lectura y mostrar los datos que se habían guardado, que se deben leer con "fread".Aun me cuesta entender como funciona exactamente la orden fread y fwrite, por ejemplo, escribiendo: fread(&ficha, sizeof(ficha), 1, fichero); &ficha se refiere al lugar donde se guardan los datos, sizeof(ficha) el tamaño de los datos, el 1 a la cantidad de datos a leer, pero ¿hasta donde se lee?, ¿hasta que encuentre un \0 o \n?, no entiendo muy bien ese 1. Bueno, aqui os dejo mi intento del ejercicio anterior, el cual casi al finalizar me tira "programa.exe has stopped working" y no se donde está el error. Edit: Aclarar que el programa me da dos warning: "assignment make pointer from integer without a cast"#include <stdio.h> #include <string.h>
int main(){
struct{ char Name[100],City[100]; int Age; }Persona; FILE *Gente1; int X;
if(Gente1=fopen("gente1.dat","ab")==NULL){ printf("No se puede escribir en el fichero...\n"); } else{ printf("Que nombre deseas introducir?: "); fflush(stdin); gets(Persona.Name); printf("\nCiudad?: "); fflush(stdin); gets(Persona.City); printf("\nEdad?: "); fflush(stdin); scanf("%d",&Persona.Age); fwrite(&Persona,sizeof(Persona),1,Gente1); fclose(Gente1); }
if(Gente1=fopen("gente1.dat","rb")==NULL){ printf("\nNo se puede leer el fichero...\n"); } else{ while(!feof(Gente1)){ fread(&Persona,sizeof(Persona),1,Gente1); puts(Persona.Name); puts(Persona.City); printf("%s\n",Persona.Age); } fclose(Gente1); }
fflush(stdin); getchar(); return 0; }
Muchas gracias de antemano!
|
|
« Última modificación: 26 Marzo 2015, 16:05 pm por M01535 »
|
En línea
|
|
|
|
ivancea96
Desconectado
Mensajes: 3.412
ASMático
|
Estas escribiendo y leyendo datos binarios. No se atiende ni a caracteres nulos ni a saltos de linea. Si tu le especificas leer X bytes, leerá X bytes, no más. La cantidad de bytes que leerá fread en total, será el tamaño del tipo o estructura que le pasas (segundo parámetro), multiplicado por el número de elementos del arreglo (tercer parámetro. fwrite es más de lo mismo. Si quieres información detallada de las funciones, http://www.cplusplus.com/reference/cstdio/fread/.
|
|
|
En línea
|
|
|
|
M01535
Desconectado
Mensajes: 4
|
Muchas gracias ivancea96 por tu respuesta, eso de la cantidad de bytes que leerá fread en total me ha quedado bastante claro Ahora bien, alguien tiene idea de por qué el programa me tira los warning: "assignment make pointer from integer without a cast" y al ejecutarlo, cuando va a finalizar el programa, deja de funcionar: "program.exe has stopped working"
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
alguien tiene idea de por qué el programa me tira los warning: "assignment make pointer from integer without a cast" y al ejecutarlo, cuando va a finalizar el programa, deja de funcionar: "program.exe has stopped working"
Los errores se generan en las llamadas a fopen: if (Gente1 = fopen("gente1.dat","ab") == NULL ){ /* ... */ if (Gente1 = fopen("gente1.dat","rb") == NULL ){
El operador "==" tiene una prioridad mayor que "=" por lo que esas sentencias se procesan así: if (Gente1 = (fopen("gente1.dat","ab") == NULL )){ /* ... */ if (Gente1 = (fopen("gente1.dat","rb") == NULL )){
Por ello la variable almacenara el valor entero cero si fopen tiene éxito y uno en caso contrario. Para solucionarlo solo tienes que utilizar paréntesis para primero asignar y solo entonces comparar: if ((Gente1 = fopen("gente1.dat","ab")) == NULL ){ /* ... */ if ((Gente1 = fopen("gente1.dat","rb")) == NULL ){
Por ultimo evita el uso de gets y fflush(stdin), las razones de ello en el tema |Lo que no hay que hacer en C/C++. Nivel basico|Un saludo
|
|
|
En línea
|
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language
|
|
|
M01535
Desconectado
Mensajes: 4
|
Muchas gracias por tu respuesta rir3760, me habeis ayudado bastante y he aprendido unas cuantas cosas nuevas, lo agradezo. He hecho unas "mejoras" al programa también teniendo en cuenta lo que me comentaste de fflush(stdin) y los gets, aqui tengo el nuevo codigo a ver que os parece #include <stdio.h> #include <string.h>
int main(){
struct{ char Name[100],City[100]; int Age; }Persona; FILE *Gente1; int X; char Buffer[200];
if((Gente1=fopen("gente1.dat","wb"))==NULL){ printf("No se puede escribir en el fichero...\n"); } else{ printf("Que nombre deseas introducir?: "); fgets(Persona.Name,sizeof(Persona.Name),stdin); printf("\nCiudad?: "); fgets(Persona.City,sizeof(Persona.City),stdin); printf("\nEdad?: "); fgets(Buffer,sizeof(Buffer),stdin); sscanf(Buffer,"%d",&Persona.Age); fwrite(&Persona,sizeof(Persona),1,Gente1); fclose(Gente1); }
if((Gente1=fopen("gente1.dat","rb"))==NULL){ printf("\nNo se puede leer el fichero...\n"); } else{ while(!feof(Gente1)){ fread(&Persona,sizeof(Persona),1,Gente1); if(strlen(Persona.Name)>0) Persona.Name[strlen(Persona.Name)-1]='\0'; if(!feof(Gente1)) puts(Persona.Name); if(strlen(Persona.City)>0) Persona.City[strlen(Persona.City)-1]='\0'; if(!feof(Gente1)) puts(Persona.City); if(!feof(Gente1)) printf("%d\n",Persona.Age); } } fclose(Gente1);
return 0; }
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
Para imprimir el registro almacenado en el archivo no necesitas de un bucle, en su lugar basta con una sentencia condicional donde se verifique el valor de retorno de la función (uno en caso de una lectura exitosa). De esta forma: if (fread(&Persona , sizeof(Persona ), 1, Gente1 ) == 1) printf("%s%s%d\n", Persona. Name, Persona. City, Persona. Age);
Un saludo
|
|
|
En línea
|
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language
|
|
|
M01535
Desconectado
Mensajes: 4
|
Gracias a todos por vuestras respuestas, son de gran ayuda. Bueno, me surgió una nueva duda sobre fread y fwrite (la guerra que me está dando esta orden... ) asi que aprovecho este mismo tema para exponerla. El programa a construir es el siguiente: Mejorar la agenda anterior (del apartado 6.4), para guardar y leer cada "ficha" (struct) de una vez, usando fwrite/fread y sizeof, como en el último ejemplo.Y aqui teneis el código de la agenda de la que se habla: #include <stdio.h> #include <string.h>
int main(){
FILE* Agenda; struct{ char Name[100],Adress[100],Email[100],Movil[13]; unsigned short int Day,Month,Year; }Datos[100]; char Buffer[200],Buscar[200]; int X=0,Y,Menu,Algodon=0;
//LEER DATOS DEL FICHERO Agenda=fopen("agenda.dat","rt"); while(!feof(Agenda)){ fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Name,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Adress,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Movil,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Email,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; sscanf(Buffer,"%d",&Datos[X].Day);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; sscanf(Buffer,"%d",&Datos[X].Month);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; sscanf(Buffer,"%d",&Datos[X].Year); Algodon=1; X++; } fclose(Agenda); if(Algodon==0){ printf("No hay datos que leer...\n\n"); } else if(Algodon==1){ printf("Datos leidos...\n\n"); }
do{ printf("1 - Introducir nuevo dato\n2 - Ver todos los nombres de los datos\n3 - Buscar\n0 - Salir\nQue desea hacer?: "); fgets(Buffer,sizeof(Buffer),stdin); sscanf(Buffer,"%d",&Menu);
switch(Menu){ //INGRESAR NUEVO DATO case 1: printf("\n\nNUEVO DATO:\nIngrese el nombre: "); fgets(Datos[X].Name,sizeof(Datos[X].Name),stdin); Datos[X].Name[strlen(Datos[X].Name)-1]='\0';
printf("Ingrese la ciudad: "); fgets(Datos[X].Adress,sizeof(Datos[X].Adress),stdin); Datos[X].Adress[strlen(Datos[X].Adress)-1]='\0';
printf("Ingrese el numero de movil: "); fgets(Datos[X].Movil,sizeof(Datos[X].Movil),stdin); Datos[X].Movil[strlen(Datos[X].Movil)-1]='\0';
printf("Ingrese el email: "); fgets(Datos[X].Email,sizeof(Datos[X].Email),stdin); Datos[X].Email[strlen(Datos[X].Email)-1]='\0';
printf("Ingrese el dia de nacimiento: "); fgets(Buffer,sizeof(Buffer),stdin); sscanf(Buffer,"%d",&Datos[X].Day);
printf("Ingrese el mes de nacimiento: "); fgets(Buffer,sizeof(Buffer),stdin); sscanf(Buffer,"%d",&Datos[X].Month);
printf("Ingrese su year de nacimiento: "); fgets(Buffer,sizeof(Buffer),stdin); sscanf(Buffer,"%d",&Datos[X].Year); X++; break;
//MOSTRAR LOS NOMBRES DE TODOS LOS DATOS case 2: if(X==0){ printf("\n\nNo hay datos que mostrar\n\n"); break; }
printf("\n\nEstos son los nombres de todos los datos:\n"); for(Y=0;Y<X;Y++){ printf("%d - %s\n",Y,Datos[Y].Name); } printf("\n"); break;
//BUSCAR DATO POR NOMBRE case 3: printf("\n\nIntroduzca el nombre del contacto que desea buscar: "); fgets(Buscar,sizeof(Buscar),stdin); Buscar[strlen(Buscar)-1]='\0'; Algodon=0;
for(Y=0;Y<X;Y++){ if(strcmp(Buscar,Datos[Y].Name)==0){ printf("\nSe ha encontrado este/os resultado/s:\n"); printf("Name: %s\nAdress: %s\nPhone: %s\nEmail: %s\nBorn in: %d-%d-%d\n\n",Datos[Y].Name,Datos[Y].Adress,Datos[Y].Movil,Datos[Y].Email,Datos[Y].Day,Datos[Y].Month,Datos[Y].Year); Algodon=1; } } if(Algodon==0){ printf("\nNo se han encontrado resultados...\n\n"); } } }while(Menu!=0);
//ESCRIBIR LOS DATOS EN EL FICHERO Agenda=fopen("agenda.dat","wt"); for(Y=0;Y<X;Y++){ fprintf(Agenda,"%s\n",Datos[Y].Name); fprintf(Agenda,"%s\n",Datos[Y].Adress); fprintf(Agenda,"%s\n",Datos[Y].Movil); fprintf(Agenda,"%s\n",Datos[Y].Email); fprintf(Agenda,"%d\n",Datos[Y].Day); fprintf(Agenda,"%d\n",Datos[Y].Month); fprintf(Agenda,"%d\n",Datos[Y].Year); } fclose(Agenda);
printf("\nSaliendo...");
return 0; }
Bueno, para facilitar las cosas, las partes donde hay que sustituir e introducir un fread y fwrite son las siguientes: fread Agenda=fopen("agenda.dat","rt"); while(!feof(Agenda)){ fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Name,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Adress,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Movil,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; if(strlen(Buffer)>0) Buffer[strlen(Buffer)-1]='\0'; strcpy(Datos[X].Email,Buffer);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; sscanf(Buffer,"%d",&Datos[X].Day);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; sscanf(Buffer,"%d",&Datos[X].Month);
fgets(Buffer,200,Agenda); if(feof(Agenda)) break; sscanf(Buffer,"%d",&Datos[X].Year); Algodon=1; X++; } fclose(Agenda); fwrite Agenda=fopen("agenda.dat","wt"); for(Y=0;Y<X;Y++){ fprintf(Agenda,"%s\n",Datos[Y].Name); fprintf(Agenda,"%s\n",Datos[Y].Adress); fprintf(Agenda,"%s\n",Datos[Y].Movil); fprintf(Agenda,"%s\n",Datos[Y].Email); fprintf(Agenda,"%d\n",Datos[Y].Day); fprintf(Agenda,"%d\n",Datos[Y].Month); fprintf(Agenda,"%d\n",Datos[Y].Year); } fclose(Agenda);
Muchas gracias por vuestra atención y un saludo.
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
La recomendación anterior se mantiene: no utilices feof, en su lugar verifica el valor de retorno de la función en turno. También utiliza nombres descriptivos para las variables, "algodon" no lo es. ---- El bucle de lectura lo puedes sustituir con una sola llamada a fread: int num_regs; /* Numero de registros */ /* ... */ // Leer datos del fichero Agenda = fopen("agenda.dat", "rb");num_regs = fread(Datos , sizeof Datos [0], 100, Agenda );
Con ella se le indica a la función que lea un máximo de 100 registros del archivo y los almacene a partir de la dirección indicada por "Agenda". El numero actual de registros leídos se almacena en la variable "num_regs". En la misma linea el bucle de escritura se sustituye por la llamada a función: // Escribir los datos en el fichero Agenda = fopen("agenda.dat", "wb");fwrite(Datos , sizeof Datos [0], num_regs , Agenda );
---- Ya por ultimo cuando se desea leer un valor de tipo unsigned short el especificador de formato con scanf y familia es "%hu". Un saludo
|
|
|
En línea
|
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
fread y fwrite con clases
Programación C/C++
|
newone
|
4
|
4,888
|
23 Junio 2011, 23:40 pm
por newone
|
|
|
Usos fwrite, fread
Programación C/C++
|
diegoCmC
|
4
|
5,592
|
13 Septiembre 2012, 21:42 pm
por diegoCmC
|
|
|
fread o alguna funcion para leer un bloc de notas
Programación C/C++
|
Erres
|
8
|
7,212
|
5 Octubre 2012, 18:19 pm
por Erres
|
|
|
Función fread y saltos de línea
Programación C/C++
|
NathanD
|
8
|
5,987
|
20 Marzo 2013, 20:25 pm
por NathanD
|
|
|
FILE y funcion fwrite()
Programación C/C++
|
m@o_614
|
3
|
2,764
|
7 Septiembre 2013, 08:49 am
por Eternal Idol
|
|