elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Escritura y lectura de archivos binarios
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Escritura y lectura de archivos binarios  (Leído 3,889 veces)
++c

Desconectado Desconectado

Mensajes: 29


Ver Perfil
Escritura y lectura de archivos binarios
« en: 3 Septiembre 2014, 19:04 pm »

Hola amigos, estoy tratando de hacer un código de archivo binario con array de estructuras pero no encuentro como hallar adecuadamente la lectura de los registros que introduzco con fread.

Si introduzco dos personas como en el ejemplo necesita de tres ocasiones para leerlas hasta llegar a final de archivo. No encuentro la manera sencilla de que haga las lecturas correctas de las personas que solicito a través de un número.

Dejo el código para conocer en que puedo estar fallando, gracias!!

Código
  1.  
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #define N 2
  6.  
  7. struct{
  8.    char nombre[20];
  9.    char ciudad[20];
  10.    int edad;
  11. }persona[N];
  12.  
  13. int main(void)
  14. {
  15.    char temporal[20];
  16.    char name[15]="gente.dat";
  17.    int i,numero,leo;
  18.    FILE *fichero;
  19.    if((fichero=fopen(name,"ab"))!=NULL){
  20.        do{
  21.            for(i=0;i<N;i++){
  22.                printf("\nIntroduzca nombre: ");
  23.                gets(persona[i].nombre);
  24.                if(strcmp(persona[i].nombre,"")!=0){
  25.                    printf("\nIntroduzca ciudad: ");
  26.                    gets(persona[i].ciudad);
  27.                    printf("\nIntroduzca edad: ");
  28.                    fgets(temporal,19,stdin);
  29.                    sscanf(temporal,"%d",&persona[i].edad);
  30.                    fwrite(&persona[i],sizeof(persona),1,fichero);
  31.                }
  32.            }
  33.        }while(strcmp(persona[i].nombre,"")!=0);
  34.        fclose(fichero);
  35.    }
  36.    else{
  37.        printf("\nError en apertura fichero");
  38.        exit(1);
  39.    }
  40.    if((fichero=fopen(name,"rb"))!=NULL){
  41.        do{
  42.                printf("\nIntroduzca numero de persona a visualizar: ");
  43.                fgets(temporal,19,stdin);
  44.                sscanf(temporal,"%d",&numero);
  45.                for(i=0;i<N;i++){
  46.                     if(numero==i){
  47.                        printf("\nNombre: %s",persona[i].nombre);
  48.                        printf("\nCiudad: %s\n",persona[i].ciudad);
  49.                        printf("Edad: %d",persona[i].edad);
  50.                        leo=fread(&persona[i],1,sizeof(persona),fichero);
  51.                    }
  52.                }
  53.        }while(leo!=0);
  54.        fclose(fichero);
  55.    }else{
  56.        printf("\nError en apertura fichero");
  57.        exit(1);
  58.    }
  59.    return 0;
  60. }
  61.  
  62.  


En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #1 en: 4 Septiembre 2014, 09:51 am »

Código
  1. if((fichero=fopen(name,"rb"))!=NULL){
  2.  do{
  3.    printf("\nIntroduzca numero de persona a visualizar: ");
  4.    // ...
  5.  
  6.    for(i=0;i<N;i++){
  7.      if(numero==i){
  8.        printf("\nNombre: %s",persona[i].nombre);
  9.        printf("\nCiudad: %s\n",persona[i].ciudad);
  10.        printf("Edad: %d",persona[i].edad);
  11.        leo=fread(&persona[i],1,sizeof(persona),fichero);
  12.      }
  13.    }
  14.  }while(leo!=0);
  15.  fclose(fichero);
  16. }

No me ha quedado muy clara esta parte del código.

Intentas leer un registro determinado del archivo... pero el mecanismo es extraño. Me explico:

1. Abres el archivo
2. Preguntas al usuario el índice del registro a visualizar??? antes de haber leído el archivo ?????
3. Después, localizas ese registro, lo sacas por pantalla y entonces sobreescribes su contenido con el primer registro que te encuentras en el fichero. Al final lo que acabas de leer te lo guardas para ti y no lo sacas por pantalla.
4. Vuelves al paso 2 hasta que hayas leído todos los registros del archivo.

El código de arriba lo puedes simplificar. Quizás te ayude a ver que no tiene mucho sentido :

Código
  1. if((fichero=fopen(name,"rb"))!=NULL){
  2.  do{
  3.    printf("\nIntroduzca numero de persona a visualizar: ");
  4.    // ...
  5.  
  6.    printf("\nNombre: %s",persona[numero].nombre);
  7.    printf("\nCiudad: %s\n",persona[numero].ciudad);
  8.    printf("Edad: %d",persona[numero].edad);
  9.    leo=fread(&persona[numero],1,sizeof(persona),fichero);
  10.  }while(leo!=0);
  11.  fclose(fichero);
  12. }

El comportamiento es francamente extraño.

Quizás deberías comentar qué se espera acerca del funcionamiento de este programa.


En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #2 en: 4 Septiembre 2014, 17:26 pm »

estoy tratando de hacer un código de archivo binario con array de estructuras pero no encuentro como hallar adecuadamente la lectura de los registros que introduzco con fread.
Como ya te comento eferion el programa tiene bastantes errores, si no tienes un curso o libro de calidad debes conseguir uno, recomendaciones sobre ellos las puedes revisar mediante el motor de búsqueda de los foros.

Diría que el error principal es lógico (imprimir el registro y solo después de ello leerlo) pero debido a la cantidad de errores es mejor rescribir esa parte desde cero. Los pasos son:

1) Pides el numero de registros al usuario.
2) Llamas a fread tratando de leer el numero indicado (pueden ser menos).
3) Utilizas un bucle para imprimir cada registro leído.

Mas o menos así:
Código
  1. if ((fichero = fopen(name, "rb")) == NULL){
  2.   /* Manejo de error */
  3. }else {
  4.   char aux[128];
  5.   int regs_a_leer;
  6.   int regs_leidos;
  7.  
  8.   /* 1) Obtener el numero de registros a leer */
  9.   puts("Numero de personas a visualizar:");
  10.   fgets(aux, sizeof aux, stdin);
  11.   sscanf(aux, "%d", &regs_a_leer);
  12.  
  13.   /* 2) Tratar de leer el numero indicado */
  14.   regs_leidos = fread(persona, sizeof persona[0], regs_a_leer, fichero);
  15.  
  16.   /* 3) Imprimir los registros leidos */
  17.   for (i = 0; i < regs_leidos; i++){
  18.      printf("Registro No %d\n", i + 1);
  19.  
  20.      printf("Nombre: %s\n", persona[i].nombre);
  21.      printf("Ciudad: %s\n", persona[i].ciudad);
  22.      printf("Edad: %d\n", persona[i].edad);
  23.   }
  24.  
  25.   fclose(fichero);
  26. }

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
++c

Desconectado Desconectado

Mensajes: 29


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #3 en: 4 Septiembre 2014, 23:08 pm »

Hola!!

Gracias por los consejos eferion y rir3760.

Me han ayudado vuestros consejos y metodología para trabajar con ficheros.

No me he explicado muy bien y espero expresarme lo que pretendo hacer.

Mirar lo que quiero que haga el programa en la lectura:

1. Lea el fichero.

2. Que pregunte al usuario por el nº de registro que desea visualizar. Ejemplo:
    Se han introducido y guardado previamente en la primera parte del código con        fwrite:
    - Nombre= José , se habrá guardado en persona[0]
    - Nombre2= David , persona[1]

3. El programa mostrará los datos correspondientes a ese usuario.

He intentado hacerlo de otra forma pero solo consigo que me lea ambos contactos(José y David) si introduzco el contacto '0', si coloco el que me busque el contacto '1' me muestra por pantalla en blanco las opciones que deseo se me visualicen.

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #define N 2
  5.  
  6. struct{
  7.    char nombre[20];
  8.    char ciudad[20];
  9.    int edad;
  10. }persona[N];
  11.  
  12. int main(void)
  13. {
  14.    char temporal[20];
  15.    char name[15]="gente.dat";
  16.    int i,numero;
  17.    FILE *fichero;
  18.    if((fichero=fopen(name,"wb"))!=NULL){
  19.        do{
  20.            for(i=0;i<N;i++){
  21.                printf("\nIntroduzca nombre: ");
  22.                fgets(persona[i].nombre,sizeof(persona),stdin);
  23.                if(strcmp(persona[i].nombre,"")!=0){
  24.                    printf("\nIntroduzca ciudad: ");
  25.                    fgets(persona[i].ciudad,sizeof(persona),stdin);
  26.                    printf("\nIntroduzca edad: ");
  27.                    fgets(temporal,19,stdin);
  28.                    sscanf(temporal,"%d",&persona[i].edad);
  29.                    fwrite(&persona[i],sizeof(persona),1,fichero);
  30.                }
  31.            }
  32.        }while(strcmp(persona[i].nombre,"")!=0);
  33.        fclose(fichero);
  34.    }
  35.    else{
  36.        printf("\nError en apertura fichero");
  37.        exit(1);
  38.    }
  39.    if((fichero=fopen(name,"rb"))!=NULL){
  40.        fread(&persona,sizeof(persona),1,fichero); /*leo el archivo antes de preguntar*/
  41.        while(!feof(fichero)){
  42.                printf("\nIntroduzca numero de persona a visualizar: ");
  43.                fgets(temporal,19,stdin);
  44.                sscanf(temporal,"%d",&numero);
  45.                printf("\nNombre: %s",persona[numero].nombre);
  46.                printf("\nCiudad: %s\n",persona[numero].ciudad);
  47.                printf("Edad: %d",persona[numero].edad);
  48.                fread(&persona[numero],sizeof(persona),1,fichero);
  49.        }
  50.        fclose(fichero);
  51.    }else{
  52.        printf("\nError en apertura fichero");
  53.        exit(1);
  54.    }
  55.    return 0;
  56. }
  57.  

Pdata: se que no se ve de muy buena forma el uso de !feof por algunos programadores...

Pdata eferion: me sirvió como simplificaste el código.

Pdata rir3760: me guardo tu código y me quedo con la copla de como leer y mostrar contactos.

Saludos!!
« Última modificación: 4 Septiembre 2014, 23:29 pm por ++c » En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #4 en: 5 Septiembre 2014, 04:14 am »

Mirar lo que quiero que haga el programa en la lectura:

1. Lea el fichero.
Ya que en el programa declaras un array de N elementos solo tienes que utilizar la función fread para tratar de leer ese numero. Ya que se puede leer un numero menor almacenas el valor de retorno de la función en una variable (es el numero de elementos leídos). Eso ya lo explique en mi mensaje anterior:
Código
  1. /* 2) Tratar de leer el numero indicado */
  2. regs_leidos = fread(persona, sizeof persona[0], regs_a_leer, fichero);

2. Que pregunte al usuario por el nº de registro que desea visualizar.
Solo tienes que utilizar la función scanf para obtener el indice del elemento en el array: 0 .. regs_leidos - 1.

3. El programa mostrará los datos correspondientes a ese usuario.
Imprimes el valor de los campos del elemento en cuestión, de nuevo eso ya lo tienes.

Pdata: se que no se ve de muy buena forma el uso de !feof por algunos programadores.
El problema con feof es que usualmente es innecesaria ya que se puede utilizar directamente el valor de retorno de la función utilizada.

Por ejemplo en tu programa se debe duplicar la sentencia de lectura para que el bucle funcione correctamente (con feof) cuando utilizando el valor de retorno de fread te olvidas de feof y la duplicación:
Código
  1. while (fread(&persona,sizeof(persona),1,fichero) == 1){
  2.   printf("\nIntroduzca numero de persona a visualizar: ");
  3.   fgets(temporal,19,stdin);
  4.   sscanf(temporal,"%d",&numero);
  5.  
  6.   printf("\nNombre: %s",persona[numero].nombre);
  7.   printf("\nCiudad: %s\n",persona[numero].ciudad);
  8.   printf("Edad: %d",persona[numero].edad);
  9. }

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
++c

Desconectado Desconectado

Mensajes: 29


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #5 en: 5 Septiembre 2014, 21:31 pm »

Hola rir3760,

gracias por las aclaraciones, sólo me queda una duda y es la que me indicas aquí:

Citar
Solo tienes que utilizar la función scanf para obtener el indice del elemento en el array: 0 .. regs_leidos - 1.

La duda me viene en que no deduzco como recorrer ese array con regs_leidos...

Saludos!!
En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #6 en: 5 Septiembre 2014, 21:58 pm »

Tal vez no me estoy explicando correctamente ya que no hay necesidad alguna de "recorrer" el array, simplemente se imprime el registro indicado cuyo indice obtienes con la función scanf.

Solo para estar seguro.

1) Al utilizar fread en esta forma:
Código
  1. fread(persona, sizeof persona[0], regs_a_leer, fichero);
Se le indica que lea el numero de registros indicado por "regs_a_leer", el objetivo de ello es leer todos los registros en el archivo y como máximo (el tercer argumento de la función) debes indicar la capacidad del array "persona". De nuevo se leen todos los registros.

2) La función puede leer menos bien porque se genere un error o porque simplemente no hay tantos registros en el archivo. Por eso la función retorna el numero de elementos leídos y almacenamos ese valor en la variable "regs_leidos":
Código
  1. regs_leidos = fread(persona, sizeof persona[0], regs_a_leer, fichero);

3) Si todo sale bien el valor de "regs_leidos" sera igual a "regs_a_leer" (si no es así hay un error tal vez lógico, tal vez en la lectura del archivo). Solo resta obtener el indice del registro e imprimirlo:
Código
  1. int i;
  2.  
  3. /* ... */
  4.  
  5. puts("Indice del registro a imprimir:");
  6. scanf("%d", &i);
  7.  
  8. /* ... */
  9.  
  10. /* Se imprimen los campos del registro "persona[i]" */

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
++c

Desconectado Desconectado

Mensajes: 29


Ver Perfil
Re: Escritura y lectura de archivos binarios
« Respuesta #7 en: 10 Septiembre 2014, 23:21 pm »

Hola rir3760,

gracias de nuevo por las explicaciones, me han servido para resolver los algoritmos de dos formas, te los agrego para que veas como han quedado:

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #define N 2
  5.  
  6. struct{
  7.    char nombre[20];
  8.    char ciudad[20];
  9.    int edad;
  10. }persona[N];
  11.  
  12. int main(void)
  13. {
  14.    char temporal[20];
  15.    char name[15]="gente.dat";
  16.    int i,numero;
  17.    FILE *fichero;
  18.    if((fichero=fopen(name,"wb"))!=NULL){
  19.        do{
  20.            for(i=0;i<N;i++){
  21.                printf("\nIntroduzca nombre: ");
  22.                fgets(persona[i].nombre,sizeof(persona),stdin);
  23.                if(strcmp(persona[i].nombre,"")!=0){
  24.                    printf("\nIntroduzca ciudad: ");
  25.                    fgets(persona[i].ciudad,sizeof(persona),stdin);
  26.                    printf("\nIntroduzca edad: ");
  27.                    fgets(temporal,19,stdin);
  28.                    sscanf(temporal,"%d",&persona[i].edad);
  29.                    fwrite(&persona[i],sizeof(persona[i]),1,fichero);
  30.                }
  31.            }
  32.        }while(strcmp(persona[i].nombre,"")!=0);
  33.        fclose(fichero);
  34.    }
  35.    else{
  36.        printf("\nError en apertura fichero");
  37.        exit(1);
  38.    }
  39.    if((fichero=fopen(name,"rb"))!=NULL){
  40.  
  41.       while (fread(&persona,sizeof(persona),N,fichero) !=NULL){
  42.           printf("\nIntroduzca numero de persona a visualizar: ");
  43.           scanf("%d",&numero);
  44.           printf("\nNombre: %s",persona[numero].nombre);
  45.           printf("\nCiudad: %s\n",persona[numero].ciudad);
  46.           printf("Edad: %d",persona[numero].edad);
  47.        }
  48.        fclose(fichero);
  49.    }else{
  50.        printf("\nError en apertura fichero");
  51.        exit(1);
  52.    }
  53.    return 0;
  54. }
  55.  

Y este el otro sin uso de array de struct:

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4.  
  5. struct{
  6.    char nombre[20];
  7.    char ciudad[20];
  8.    int edad;
  9. }persona;
  10.  
  11. int main(void)
  12. {
  13.    char temporal[20];
  14.    char name[15]="gente.dat";
  15.    int i,numero;
  16.    FILE *fichero;
  17.    if((fichero=fopen(name,"wb"))!=NULL){
  18.        do{
  19.                printf("\nIntroduzca nombre: ");
  20.                fgets(persona.nombre,sizeof(persona.nombre),stdin);
  21.                if(strcmp(persona.nombre,"\n")!=0){
  22.                    printf("\nIntroduzca ciudad: ");
  23.                    fgets(persona.ciudad,sizeof(persona.ciudad),stdin);
  24.                    printf("\nIntroduzca edad: ");
  25.                    fgets(temporal,19,stdin);
  26.                    sscanf(temporal,"%d",&persona.edad);
  27.                    fwrite(&persona,sizeof(persona),1,fichero);
  28.                }
  29.  
  30.        }while(strcmp(persona.nombre,"\n")!=0);
  31.        fclose(fichero);
  32.    }
  33.    else{
  34.        printf("\nError en apertura fichero");
  35.        exit(1);
  36.    }
  37.    if((fichero=fopen(name,"rb"))!=NULL){
  38.  
  39.        printf("\nIntroduzca numero de persona a visualizar: ");
  40.        scanf("%d",&numero);
  41.  
  42.        i=0;
  43.        while ( (fread(&persona,sizeof(persona),1,fichero) !=NULL) && (i<numero) ){
  44.           ++i;
  45.        }
  46.        if (!feof(fichero))
  47.        {
  48.           printf("\nNombre: %s",persona.nombre);
  49.           printf("\nCiudad: %s\n",persona.ciudad);
  50.           printf("Edad: %d",persona.edad);
  51.        }
  52.        else
  53.            printf ("La persona no existe.\n");
  54.        fclose(fichero);
  55.    }else{
  56.        printf("\nError en apertura fichero");
  57.        exit(1);
  58.    }
  59.    return 0;
  60. }
  61.  

Seguro que encuentras algún pero... pero funcionan, jeje

Saludos y gracias
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Lectura y Escritura de CDs y DVDs.
Hardware
B€T€B€ 8 7,935 Último mensaje 19 Julio 2011, 01:18 am
por B€T€B€
[Ayuda] Lectura y escritura de archivos.
Java
ignorantev1.1 3 2,840 Último mensaje 30 Marzo 2013, 18:03 pm
por ignorantev1.1
Duda LECTURA ARCHIVOS BINARIOS
Programación C/C++
Omar_2013 6 2,616 Último mensaje 11 Mayo 2014, 20:28 pm
por Omar_2013
Lectura y escritura en Archivos
Programación C/C++
Swastik 3 2,665 Último mensaje 8 Febrero 2015, 01:00 am
por ivancea96
[AYUDA] Lectura y escritura de archivos
Programación C/C++
Kougami 3 2,399 Último mensaje 27 Noviembre 2016, 20:38 pm
por engel lex
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines