Save and Load struct C

0

I'll be back with another question because I've been doing it all day, I want to store the struct data in a file, but I get an error. Before putting the code I explain that I have the variable contador , which is where I store every time I add a item .

When I save struct I save it in TXT to be able to visualize the data without coding, but random values and symbols come out. On the other hand, when loading it does not load anything, it detects that there is some data, but it does not detect the data as such, why? When I'm going to delete a copy or modify it, it does not indicate that it's empty BDD .

Save:

 void Guardar(tRegLista *reg)
{
    FILE *pfichero;
    int i;
    pfichero=fopen("BIBLIOTECA.DAT","w+b");
    if(pfichero!=NULL){
        fwrite(reg->contador,sizeof(reg->contador),1,pfichero);
        for(i=0;i<reg->contador;i++){
            fwrite(&reg[i],sizeof(reg[i]),1,pfichero);
        }
    }
    fclose(pfichero);
}

Upload:

void Cargar(tRegLista *reg)
{
    FILE *pfichero;
    pfichero=fopen("BIBLIOTECA.DAT","rb");
    if(pfichero!=NULL){
        fread(&reg->contador,sizeof(reg->contador),1,pfichero);
        while(!feof(pfichero)){
            fread(&reg[reg->contador],sizeof(reg[reg->contador]),1,pfichero);
            reg->contador++;
        }
        reg->contador--;
    }
    fclose(pfichero);
}

Struct:

typedef struct
{
    char nomEditorial[TAM];
    int numPagina;

} tRegLibros;

typedef struct
{
    char nomRevista[TAM];
    int numRevista;
    int paginaInicio;

} tRegArticulos;

typedef struct
{
    char titulo[50];
    char autor[TAM];
    char idEjemplar[5];
    int anioPubli;
    int prestado;
    char fecha[20];
    char dniSocio[9];
    char clave[4];

    union
        uTipo
    {
        tRegArticulos articulo;
        tRegLibros libro;
    } uTipo;
} tRegEjemplares;

typedef struct
{
    tRegEjemplares ejemplar[maxEJEMPLARES];
    int contador;
    int contadorLibros;
    int contadorArticulo;
} tRegLista;

Main:

tRegLista reg;
    
asked by Peter 15.04.2017 в 21:39
source

2 answers

1

I found the error, logically it was a step of parameters from one subprogram to another had to pass the variables with

  

& *

and passed them only with &. Thank you very much to the others for your answers! Greetings:)

    
answered by 22.04.2017 / 13:16
source
1
void Cargar(tRegLista *reg)
{
    FILE *pfichero;
    pfichero=fopen("BIBLIOTECA.DAT","rb");
    if(pfichero!=NULL){
        fread(&reg->contador,sizeof(reg->contador),1,pfichero); // (1)
        while(!feof(pfichero)){
            fread(&reg[reg->contador],sizeof(reg[reg->contador]),1,pfichero); // (3)
            reg->contador++; // (2)
        }
        reg->contador--;
    }
    fclose(pfichero);
}

If in (1) you have already read the number of elements ... Why do you update the variable again in (2) ? On the other hand, note that if you initialize reg->contador with the number of records when you try to retrieve the first record, you will store it in reg->ejemplar[reg->contador] (the comment labeled as (3) duly corrected).

Solution?

Use a local variable to store the number of records:

void Cargar(tRegLista *reg)
{
    FILE *pfichero;
    pfichero=fopen("BIBLIOTECA.DAT","rb");
    if(pfichero!=NULL){
        int numRegistros;
        fread(&numRegistros,sizeof(numRegistros),1,pfichero);
        reg->contador = 0; // Importante!!!
        while(!feof(pfichero)){
            fread(&reg->ejemplar[reg->contador],sizeof(tRegEjemplares),1,pfichero);
            reg->contador++;
        }

        reg->contador--; // <<--- AQUI

        if( reg->contador != numRegistros )
        {
          // Por si quieres mostrar un error por haber una inconsistencia
        }
        fclose(pfichero);
    }
}

What's the point of the line that I highlight with the comment? What happens is that feof is only going to activate after to perform an erroneous reading, then as you have programmed the loop the last reading will be incorrect ... then you increase the counter and to compensate for that error, you have to decrease it ... What happens if there are no records in the file? That the counter will end up worth -1 ...

Solution to this new problem? Do the checks when you really touch

void Cargar(tRegLista *reg)
{
    FILE *pfichero;
    pfichero=fopen("BIBLIOTECA.DAT","rb");
    if(pfichero!=NULL){
        int numRegistros;
        fread(&numRegistros,sizeof(numRegistros),1,pfichero);
        reg->contador = 0;
        if(!feof(pfichero)){ // Por si acaso el fichero está vacío
          fread(&reg->ejemplar[reg->contador],sizeof(tRegEjemplares),1,pfichero);
          while(!feof(pfichero)) {
            reg->contador++;
            fread(&reg->ejemplar[reg->contador],sizeof(tRegEjemplares),1,pfichero);
        }

        if( reg->contador != numRegistros )
        {
          // Por si quieres mostrar un error por haber una inconsistencia
        }
        fclose(pfichero);
    }
}

It is a bit uglier in the sense that you have to duplicate the line that reads from the file but at least that way you avoid incorrect values. Another possibility:

void Cargar(tRegLista *reg)
{
    FILE *pfichero;
    pfichero=fopen("BIBLIOTECA.DAT","rb");
    if(pfichero!=NULL){
        int numRegistros;
        fread(&numRegistros,sizeof(numRegistros),1,pfichero);
        reg->contador = 0;
        if(!feof(pfichero)){ // Por si acaso el fichero está vacío
          while(1) {
            fread(&reg->ejemplar[reg->contador],sizeof(tRegEjemplares),1,pfichero);
            if(feof(pfichero)) break;
            reg->contador++;
          }
        }

        if( reg->contador != numRegistros )
        {
          // Por si quieres mostrar un error por haber una inconsistencia
        }
        fclose(pfichero);
    }
}

Note also that I have moved the fclose instruction. It does not make much sense to try to close a file that you have not been able to open. As you had it, it was not going to fail, but it has a more accurate use.

    
answered by 17.04.2017 в 15:29