user3224353
user3224353

Reputation: 43

fwrite and fread structs

I want to write this struct into a binary file and then read it back from the binary file, but it doesn't work. The struct tLista has an array of impresora, and impresora have a tCola struct. The value of l->oc is 256883222 and obviously is incorrect. This value depends on the loadData function.

typedef char tcadena[13];

typedef struct 
{   
    tcadena nombres [TAM];
    int lectura;
    int escritura;
}tCola; 

typedef struct 
{
    char nombre [21];
    int pendientes;
    tCola cola;
}impresora;

typedef struct 
{
    impresora lista[TAMI];
    int oc;
}tLista;

...

void finalizar(tLista *l)
    {
    /* Apertura del fichero de destino, para escritura en binario*/
    FILE *fichero;
    fichero = fopen ("listaImpresoras.bin", "wb");
    if (fichero==NULL)
    {
        printf("No se puede abrir listaImpresoras.bin");
    }
    else
    {
        fwrite(l, sizeof(*l), 1, fichero);
    }
    fclose(fichero);
}

...

void inicializarLista (tLista *l)
{ 
    FILE *fichero;
    fichero=fopen("listaImpresoras.bin", "r");
    if(fichero==NULL)
    {
        printf("No existe el fichero listaImpresoras.bin\n");
        l->oc=0;
    }
    else
    {
        fread(l, sizeof(*l), 1, fichero);
    }
    fclose(fichero);
}

...

int main(int argc, char* argv[])
{
    tLista l;
    inicializarLista(&l);
    loadData(&l); //printf and scanf (user) charge the list
    finalizar(&l);
    return 0;
}

Upvotes: 0

Views: 1739

Answers (2)

user3629249
user3629249

Reputation: 16550

The code below:

  • compiles cleanly,
  • properly initializes the tLista struct,
  • removes the obfuscation from the struct definitions,
  • exits the program when an error occurs,
  • properly writes the reason for the error to stderr before exiting.

Revised code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TAM  (2)
#define TAMI (2)

struct tCola
{
    char nombres [TAM][13];
    int lectura;
    int escritura;
};

struct impresora
{
    char nombre [21];
    int pendientes;
    struct tCola cola;
};

struct  tLista
{
    struct impresora lista[TAMI];
    int oc;
};

void loadData( struct tLista *);

void finalizar(struct tLista *l)
{
    /* Apertura del fichero de destino, para escritura en binario*/
    FILE *fichero;

    if( NULL == (fichero = fopen ("listaImpresoras.bin", "wb") ) )
    { // then, fopen failed
        perror("fopen failed");
        printf("No se puede abrir listaImpresoras.bin\n");
        exit(EXIT_FAILURE);
    }

    // implied else, fopen successful

    fwrite(l, sizeof(struct tLista), 1, fichero);
    fclose(fichero);
}  // end function: finalizar



void inicializarLista (struct tLista *l)
{
    FILE *fichero;

    if( NULL == (fichero=fopen("listaImpresoras.bin", "r") ) )
    { // then, fopen failed
        perror(" fopen failed");
        printf("No existe el fichero listaImpresoras.bin\n");
        exit(EXIT_FAILURE);
    }

    // implied else, fopen successful

    fread(l, sizeof(*l), 1, fichero);
    fclose(fichero);
} // end function: inicializarLista



int main()
{
    struct tLista l;

    memset( &l, 0x00, sizeof(struct tLista) );
    inicializarLista(&l);
    loadData(&l); //printf and scanf (user) charge the list
    finalizar(&l);
    return 0;
} // end function: main

Upvotes: 1

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53036

You have a couple of problems, but the main problem, is you don't initialize the tList l; struct properly, below I post some code that may help you see the problem, it works I tested it.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define TAM 100
#define TAMI 100

typedef char tcadena[13];

typedef struct
{
    tcadena nombres[TAM];
    int lectura;
    int escritura;
}tCola;

typedef struct
{
    char nombre[21];
    int pendientes;
    tCola cola;
}impresora;

typedef struct
{
    impresora lista[TAMI];
    int oc;
}tLista;

void finalizar(tLista *l)
{
    /* Apertura del fichero de destino, para escritura en binario*/
    FILE *fichero;

    fichero = fopen ("listaImpresoras.bin", "w");
    if (fichero == NULL)
    {
        printf("No se puede abrir listaImpresoras.bin");
    }
    else
    {
        fwrite(l, sizeof(*l), 1, fichero);
        /* solo debes llamar fclose(fichero); si (fichero != NULL) */
        fclose(fichero);
    }
    /* fclose(fichero); esto va a ser ejecutado, aunque (fichero == NULL) */
}

void inicializarLista(tLista *l)
{
    FILE *fichero;

    fichero = fopen("listaImpresoras.bin", "r");
    if (fichero == NULL)
    {
        printf("No existe el fichero listaImpresoras.bin\n");
        l->oc = 0;
    }
    else
    {
        fread(l, sizeof(*l), 1, fichero);
        /* solo debes llamar fclose(fichero); si (fichero != NULL) */
        fclose(fichero);
    }
    /* fclose(fichero); esto va a ser ejecutado, aunque (fichero == NULL) */
}

void loadData(tLista *l)
{
    int i;
    for (i = 0 ; i < 10 ; i++)
    {
        l->oc++;
    }
}

int main(int argc, char* argv[])
{
    tLista l;

    /* tienes que iniacializar todos los campos de `l`. */
    memset(&l, 0, sizeof(l));
    /* si no quieres hacerlo asi, entonces puede que
     *
     * l.oc = 0;
     *
     * sea suficiente, pero quedan los otros campos.
     *
     * al no inicializar explicitamente los campos, contienen
     * basura aleatoria, que has estado escribiendo en el archivo.
     */                               

    inicializarLista(&l);
    printf("%d\n", l.oc);

    loadData(&l); //printf and scanf (user) charge the list

    finalizar(&l);
    return 0;
}

When you don't explicitly initialize all the fields in tLista l; they contain garbage, which you have been writing into the file.

Also if you check the success of fopen() why do you try to fclose() the resulting NULL? In case fopen() returns NULL you have to exit the function without fcloseing the result of fopen since it's NULL.

Upvotes: 2

Related Questions