• Lunes 29 de Abril de 2024, 22:24

Autor Tema:  Problema con entrada/salida por archivos  (Leído 1836 veces)

ndi

  • Nuevo Miembro
  • *
  • Mensajes: 4
    • Ver Perfil
Problema con entrada/salida por archivos
« en: Lunes 12 de Julio de 2010, 22:47 »
0
Antes que nada, mil disculpas, es una pena que en mi primer tema ya este pidiendo ayuda.
Resulta que cada vez que quiero escribir un archivo (en cualquier programa que haga ) me escribe 2 veces el ultimo registro. No se que es lo que esta mal o como puedo solucionarlo, agradeceria enormemente que alguien me de una mano con esto.
El fragmento de codigo en cuestion es el siguiente:

[php:1s7j49g3]
  1.  
  2. //mientras  en numero de envio (valor ingresado por teclado) no sea negativo:
  3. while (env.nenv >=0){
  4. //Cargar en por teclado:
  5.            env = cargar (env);
  6.  
  7. //Poner el puntero del archivo al principio del mismo e inicializar el indice a :
  8.             fseek (pf, 0l, 0);
  9.             indice =0;
  10. //Mientras que  lo que lea del archivo (buff.cat) sea distinto de lo que se ingreso por teclado y, a la vez, mientras que  no se llegue al final del archivo....
  11.  
  12.             while ((buff.cat != env.cat) && !feof(pf)){
  13. //poner el buffer a 0:
  14.                 buff.total =0;
  15.                 buff.cat=0;
  16.  
  17. //posicionar el indice:
  18.                 indice = ftell(pf)/sizeof(categoria);
  19.  
  20. //leer leer registro del arhchivo y ponerlo en el buffer:
  21.                 fread(&buff, sizeof(categoria), 1, pf);              
  22.                 }
  23.  
  24. //asignar  el valor de lo que ingrese por teclado al buffer (por las dudas)
  25.             buff.cat = env.cat ;
  26. //sumar lo que leyo del archivo al buffer:
  27.             buff.total = buff.total + env.impor ;
  28.  
  29. //Actualizar archivo:
  30.             fseek (pf, indice*sizeof(categoria), 0);
  31.             fwrite(&buff, sizeof(categoria), 1, pf);
  32.             fseek(pf, 0l, 1);
  33.  
  34.  
  35.  
[/php:1s7j49g3]
Programa completo:



[php:1s7j49g3]
  1.  
  2.  
  3. #include <stdio.h>
  4. #include <conio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. typedef struct {
  9.     int nenv;
  10.     int cat;
  11.     float impor;
  12.     } envio;
  13.  
  14. typedef struct {
  15.     float total;
  16.     int cat;
  17.     } categoria;
  18.  
  19. envio cargar (envio) ;
  20.  
  21. void mostrar (FILE *);
  22. void main (void ) {
  23.     FILE * pf;
  24.     envio env;
  25.     categoria cate;
  26.     categoria buff;
  27.     int indice;
  28.  
  29.     if ((pf = fopen ("C:\encomienda.dat", "w+b"))==NULL){
  30.         printf ("error al abrir el archivo");
  31.         exit(1);
  32.         }
  33.  
  34.  
  35.     while (env.nenv >=0){
  36.         env = cargar (env);
  37.         //if (env.nenv >=0) {
  38.             printf("Envio:%d n", env.nenv);
  39.             fseek (pf, 0l, 0);
  40.             indice =0;
  41.             while ((buff.cat != env.cat) && !feof(pf)){
  42.                 buff.total =0;
  43.                 buff.cat=0;
  44.                 indice = ftell(pf)/sizeof(categoria);
  45.                 fread(&buff, sizeof(categoria), 1, pf);
  46.                 printf ("ftell: %d n", ftell(pf));
  47.                 }
  48.             buff.cat = env.cat ;
  49.             buff.total = buff.total + env.impor ;
  50.  
  51.             fseek (pf, indice*sizeof(categoria), 0);
  52.             fwrite(&buff, sizeof(categoria), 1, pf);
  53.             fseek(pf, 0l, 1);
  54.  
  55.         //}
  56.  
  57.     }
  58.     printf("Fin de carga n");
  59.  
  60.     mostrar (pf);
  61.  
  62. }
  63.  
  64. envio cargar (envio envi) {
  65.     categoria cat;
  66.     printf ("Ingresar numero de envio:n");
  67.     scanf ("%d", &envi.nenv);
  68.     //printf("%d", envi.nenv);
  69.     fflush(stdin);
  70.     if (envi.nenv >=0) {
  71.         printf ("Ingresar categoria:n");
  72.         scanf ("%d", &envi.cat);
  73.         fflush(stdin);
  74.         printf ("Ingresar Importe:n");
  75.         scanf ("%f", &envi.impor);
  76.         fflush(stdin);
  77.     }
  78.  
  79.     return envi;
  80.  
  81. }
  82.  
  83. void mostrar (FILE * fp ) {
  84.     categoria buff2;
  85.     fseek (fp, 0l, 0);
  86.     printf ("|t Cat t|t Totalt|n");
  87.     while (!feof(fp)){
  88.  
  89.         fread(&buff2, sizeof(categoria), 1, fp);
  90.         printf ("|t %d t|t %0.2f t|n", buff2.cat, buff2.total);
  91.  
  92.         }
  93.     printf("nnn Fin! ");
  94.  
  95.  
  96.     }
  97.  
[/php:1s7j49g3]

Desde ya, muchas gracias :D

Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Problema con entrada/salida por archivos
« Respuesta #1 en: Martes 13 de Julio de 2010, 01:15 »
0
En realidad el problema está al mostrar, no al escribir por que no estás revisando el resultado de fread().
Código: C
  1.  
  2.         if (fread(&buff2, sizeof(categoria), 1, fp))
  3.             printf ("|t %d t|t %0.2f t|n", buff2.cat, buff2.total);
  4.  
  5.  

ndi

  • Nuevo Miembro
  • *
  • Mensajes: 4
    • Ver Perfil
Re: Problema con entrada/salida por archivos
« Respuesta #2 en: Martes 13 de Julio de 2010, 02:08 »
0
Cita de: "Amilius"
En realidad el problema está al mostrar, no al escribir por que no estás revisando el resultado de fread().
Código: C
  1.  
  2.         if (fread(&buff2, sizeof(categoria), 1, fp))
  3.             printf ("|t %d t|t %0.2f t|n", buff2.cat, buff2.total);
  4.  
  5.  

Antes que nada, muchisimas gracias... :D ... voy a intentar frecuentar mas el foro a ver si puedo devolver el favor :D

En cuanto a mi tema, tambien pense que era lo mismo, pero se me ocurrio que era un problema de escritura porque el while que uso para imprimir es muy claro: "Si llego al final  del archivo para" (en pseudo-pseudo-pseudo-codigo :D ) y lo corrobore con tu sujerencia, el dato lo encuentra, por lo tanto el "if" que vos me indicas lo valida e imprime el dato :S. Asi que seguimos con la duda :(.

de nuevo, muchas gracias por la ayuda :D

ndi

  • Nuevo Miembro
  • *
  • Mensajes: 4
    • Ver Perfil
Re: Problema con entrada/salida por archivos
« Respuesta #3 en: Martes 13 de Julio de 2010, 15:13 »
0
Solucionado !!!! :D

El problema hay que agregar

[php:15ckliwe]
  1.  
  2.  
  3.         if (feof(fp))
  4.             break;
  5.         if (fread(&buff2, sizeof(categoria), 1, fp))
  6.              printf ("|t %d t|t %0.2f t|n", buff2.cat, buff2.total);
  7.  
[/php:15ckliwe]

De esta manera, el bucle se corta  cuando llega al fin del archivo sin llegar a imprimir la ultima vez :D

Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Problema con entrada/salida por archivos
« Respuesta #4 en: Martes 13 de Julio de 2010, 19:00 »
0
Hmm esto es interesante. Tal vez estás usando otro compilador. Yo usé VS 2005 y con la verificación del fread era suficiente para que no muestre repetido el último item. Por otra parte, usando un visor hexadecimal, es posible ver que el archivo está correctamente escrito, 8 bytes por item.

Otro punto interesante es que feof() no está funcionando como se esperaría. La última operación que encontró el final de archivo, el último fread, debería actualizar la bandera de fin de archivo, pero no es así. Posiblemente este comportamiento sólo sucede cuando el archivo es abierto para lectura y escritura.

ndi

  • Nuevo Miembro
  • *
  • Mensajes: 4
    • Ver Perfil
Re: Problema con entrada/salida por archivos
« Respuesta #5 en: Martes 13 de Julio de 2010, 19:51 »
0
Estoy usando Borland 5.5 para compilar. Segund lei feof() no es presiso, es decir, puede devolver "true" aunque no este en el final del archivo, otra posibilidad seria, ir al final del archivo con fseek(pf, 0l, 2) y hacer un fell() para sacar la posicion del ultimo byte y asi vlaerse de este valor y no de feof() :S

Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Problema con entrada/salida por archivos
« Respuesta #6 en: Martes 13 de Julio de 2010, 22:44 »
0
Cita de: "ndi"
Estoy usando Borland 5.5 para compilar. Segund lei feof() no es presiso, es decir, puede devolver "true" aunque no este en el final del archivo, otra posibilidad seria, ir al final del archivo con fseek(pf, 0l, 2) y hacer un fell() para sacar la posicion del ultimo byte y asi vlaerse de este valor y no de feof() :S

Tal parece que en este caso feof() devuelve "false" aunque esté en el final del archivo.  :mellow:

De todas formas esta sería la forma más correcta:
Código: C
  1.  
  2. void mostrar (FILE * fp ) {
  3.      categoria buff2;
  4.      fseek (fp, 0L, 0);
  5.      printf ("|t Cat t|t Totalt|n");
  6.      while (1 == fread(&buff2, sizeof(categoria), 1, fp)){
  7.            printf ("|t %d t|t %0.2f t|n", buff2.cat, buff2.total);
  8.            }
  9.      printf("nnn Fin! ");
  10.      }
  11.  
  12.  
Se desea leer un item y el resultado debería ser que se leyó un item. Tal vez en Borland 5.5 fread retorna "-1" si no pudo leer el item por que no hay más datos en el archivo y "0" si ocurrió otro error.