1

El programa no sobreescribe el bloque del archivo binario. He intentado varias soluciones como usar el fseek, redwind, cerrar el archivo y volverlo a abrir con modo de escritura(Borraba el contenido anterior del archivo por lo cual no me sirve). También he investigado y preguntado sobre la causa del error, pero tampoco he obtenido una solución. La verdad no encuentro la causa del error. A su vez que se muestra dos veces el contenido de un mismo bloque ¿Alguien me podría ayudar? ¡Se lo agradecería bastante! :D

FILE *arch;
struct productos
{
    int codigo;
    char descripcion[60];
    float precio;
}tproducto;
void altas()
{
    arch = fopen("productos.dat","ab");
    if(arch == NULL)
        exit(1);
    printf("Ingrese el codigo del producto:");
    scanf("%i",&tproducto.codigo);
    fflush(stdin);
    printf("Ingrese el nombre del producto:");
    fflush(stdin);
    gets(tproducto.descripcion);
    printf("Ingrese precio:");
    scanf("%f", &tproducto.precio);
    fwrite(&tproducto, sizeof(tproducto), 1, arch);
    fclose(arch);
}

void reporte()
{
    arch=fopen("productos.dat","rb");
    if(arch==NULL)
        exit(1);
    while(!feof(arch))
    {
        fread(&tproducto, sizeof(tproducto), 1, arch);
        printf("El codigo del producto es: %i\n", tproducto.codigo);
        printf("El nombre del producto es: %s\n", tproducto.descripcion);
        printf("El precio del producto es: %f\n", tproducto.precio);
    }
    fclose(arch);
}

void consulta()
{
    int existe=0, consulta;
    arch=fopen("productos.dat","rb");
    if (arch==NULL)
        exit(1);
    printf("Ingrese el codigo de producto a consultar:");
    scanf("%i", &consulta);
    while(!feof(arch))
    {
        fread(&tproducto, sizeof(tproducto), 1, arch);
        if(consulta==tproducto.codigo)
        {
            printf("El codigo del producto es: %i\n", tproducto.codigo);
            printf("La descripcion es: %s\n",tproducto.descripcion);
            printf("El precio es de: %0.2f\n" , tproducto.precio);
            existe++;
            break;
        }
    }
    if(existe==0)
    {
        printf("No existe un producto con dicho codigo\n");
        fclose(arch);
    }
}
void modificar()
{
    int existe=0, modificar;
    arch=fopen("productos.dat","r+b");
    if (arch==NULL)
        exit(1);
    printf("Ingrese el codigo de producto a consultar:");
    scanf("%i", &modificar);
    while(!feof(arch))
    {
        fread(&tproducto, sizeof(tproducto), 1, arch);
        if(modificar==tproducto.codigo) {
            printf("Ingrese el codigo del producto:");
            scanf("%i", &tproducto.codigo);
            fflush(stdin);
            printf("Ingrese el nombre del producto:");
            fflush(stdin);
            gets(tproducto.descripcion);
            printf("Ingrese precio:");
            scanf("%f", &tproducto.precio);
            fwrite(&tproducto, sizeof(tproducto), 1, arch);
            existe++;
            break;
        }
    }
    if(existe==0)
    {
        printf("No existe un producto con dicho codigo\n");
    }
    fclose(arch);
}

1 respuesta 1

0

Para conseguir lo que quieres tienes que abrir el fichero en modo r+ y utilizar fseek antes llamar a fwrite. Para saber cual es el offset correcto dentro del fichero, lo más fácil es contar. Por ejemplo:

void modifica () {
  int existe=0, modificar;
  char buf[1024];
   
  arch=fopen("prod.db","r+");
  if (arch==NULL)
    exit(1);

  printf("Ingrese el codigo de producto a consultar:");
  fgets (buf, 1024, stdin);
  sscanf(buf, "%d", &modificar);

  int i = 0;  // Inicializamos nuestro contador de registros a 0
  while(!feof(arch))
    {
      if (fread(&tproducto, sizeof(PRODUCTO), 1, arch)  <= 0) break;
      if(modificar==tproducto.id) {
        printf ("Modificando entrada %d en el fichero\n", i);
        printf("Ingrese el codigo del producto:");
        fflush(stdout);
        fgets (buf, 1024, stdin);
        tproducto.id = atoi (buf);

    
        printf("Ingrese el nombre del producto:");
        fflush(stdout);
        fgets(tproducto.des, 60, stdin);
        tproducto.des[strlen(tproducto.des) - 1] = 0;
    
        printf("Ingrese precio:");
        fflush(stdout);
        fgets (buf, 1024, stdin);
        tproducto.p = atof (buf);
    
        // Nos movemos al offset del registro actual antes de escribir
        fseek (arch, i*sizeof(tproducto), SEEK_SET);
        fwrite(&tproducto, sizeof(tproducto), 1, arch);
        existe++;
        break;
      }
      i++; // Incrementamos el contador
    }
  if(existe==0)
    {
      printf("No existe un producto con dicho codigo\n");
    }
  fclose(arch);
}

He modificado el código para usar fgets en lugar de scanf que suele ser problemático.

Además observa que la condición de fin de fichero solo se activa al tratar de leer más allá del fin del fichero. Cuando lees el último registro del fichero, la lectura es correcta y el indicador de fin de fichero no se a activado aún de forma que feof devolverá 0 y el bucle continuará una iteración más. Para evitarlo debes comprobar el valor retornado por fread que será 0 si no ha podido leer más datos. Sin esta modificación tu función reporte imprime el último registro 2 veces.

¿No es la respuesta que buscas? Examina otras preguntas con la etiqueta o formula tu propia pregunta.