2

I had a problem with the pointers. I wanna read a binary file with a function, and then, use the read data in the main. The problem is that I had to pass a pointer to array of struct to can use the data in main.

The code is:

#define TMOLDEO 8
#define TAM 41


struct fichpiezas{
    int codPieza;
    float dimPieza;
    float costePieza[TMOLDEO];
};

int leer_fichero(struct fichpiezas *vpiezas[]);

int main(int argc, const char * argv[]) {

    struct fichpiezas vpiezas[TAM];

    leer_fichero(&vpiezas);

    for(int i = 0; sizeof(vpiezas)/sizeof(struct fichpiezas); i++){
        printf("Codigo pieza : %d\n", vpiezas[i].codPieza);
    }

    return 0;
}


int leer_fichero (struct fichpiezas *vpiezas[]){

    FILE *fich;
    struct fichpiezas pieza;
    int error_dev = 0, i = 0;
    if ((fich = fopen("piezas.bin", "rb")) == NULL){
        printf ( "Error en apertura del fichero para lectura \n " );
        error_dev = 1;
    } else{
        //Bucle mientras no sea fin de fichero
        while (! feof(fich)){
            fread (&pieza, sizeof(pieza), 1, fich);
            vpiezas[i] = &pieza;
            i++;
        }

        fclose (fich);
    }

    return error_dev;
}
kenorb
  • 155,785
  • 88
  • 678
  • 743
abemart
  • 70
  • 2
  • 10
  • 1
    Code/comments in English will generally make it easier to read, but `pieza` in `leer_fichero` has local storage, and you just keep putting that one address into your array, and that object will be out of scope after the end of the functions. – crashmstr Jan 16 '15 at 19:55
  • this line: 'for(int i = 0; sizeof(vpiezas)/sizeof(struct fichpiezas); i++){' in main() has a problem. it does not ever exit the for loop because the calculation is always the same. suggest: 'for(int i = 0; i < (sizeof(vpiezas)/sizeof(struct fichpiezas)); i++){' Note: the value of the calculation will always be 'TAM' – user3629249 Jan 17 '15 at 04:41
  • this line: 'while (! feof(fich)){' will not work as expected because feof() is not defined until after a read operation from the fich file.. suggest using: 'while( fread (&pieza, sizeof(pieza), 1, fich) ) ' fread will return the third parameter on success and (in this case) 0 when failure/EOF occurs. – user3629249 Jan 17 '15 at 04:50
  • this line: 'vpiezas[i] = &pieza; passes the same address every time. suggest: 'memcpy( &(vpiezas[i]), &pieza, sizeof(struct fichpiezas) ); '' – user3629249 Jan 17 '15 at 04:53
  • this line: 'int leer_fichero (struct fichpiezas *vpiezas[]){' indicates passing an array of pointers, when actually only one pointer to an array of structs is involved. suggest: 'int leer_fichero (struct fichpiezas *vpiezas){' – user3629249 Jan 17 '15 at 04:55
  • the function: leer_fichero, while loop should be checking the value of 'i' to exit the loop when the callers' array of structs if full. suggest: 'if( i>=TAM) break;' – user3629249 Jan 17 '15 at 04:58

2 Answers2

4

Just change this

int leer_fichero (struct fichpiezas *vpiezas[])

to

int leer_fichero (struct fichpiezas *vpiezas)

and in your main()

leer_fichero(&vpiezas);

to

leer_fichero(vpiezas);

the array will automatically decay to a pointer when passed to the function. So you don't need to pass it's address to the function.

You have another problem, this assignment

vpiezas[i] = &pieza;

is a problem, because you are storing the address of the local variable pieza in the array, and the data will be gone when this function returns.

Aditionally the value of pieza is being overwritten in each iteration bu fread() and since you store the address of pieza instead of it's value, all the elements of the array will have the same value if it succeeded this way.

You need to copy the struct into the array element, and this line if you follow my advice above should change to

vpiezas[i] = pieza;

or the program will fail to compile, because the type of &pieza is struct fichpiezas * and that of vpiezas[i] now is struct fichpiezas after changing the function prototype.

Also, about while (! feof(fich)) there was an answer which explains in detail why that is wrong.

And one more thing, add a check i < TAM because you are in risk of overflowing the array otherwise.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
3

This

int leer_fichero(struct fichpiezas * vpiezas[]);

defines vpiezas to be a pointer to a pointer to struct fichpiezas, as

int leer_fichero(struct fichpiezas * vpiezas[]);

is equivalent to

int leer_fichero(struct fichpiezas ** vpiezas);

To address the elements of the array you pass by doing

leer_fichero(&vpiezas);

do like this

(*vpiezas)[index]

inside of leer_fichero().


It would be more straight forward to define

int leer_fichero(struct fichpiezas * vpiezas);

and pass

leer_fichero(vpiezas);

then you can address the elements as you do:

vpiezas[index]
alk
  • 69,737
  • 10
  • 105
  • 255
  • `int leer_fichero(struct fichpiezas * vpiezas[]);` does not "define `vpiezas` to be a pointer to a pointer to `struct fichpiezas`". It defines `vpiezas` to be (used in the function as) an array of pointers to `struct fichpiezas`. Otherwise, your solution works, but your first proposal would be clearer, if you also proposed to change the definition of the function to `int leer_fichero(struct fichpiezas (*vpiezas)[]);`, or simply `int leer_fichero(struct fichpiezas **vpiezas);`, for clarity reasons, when using `(*vpiezas)[index]` for access. – kavadias Jan 31 '17 at 20:39
  • @kavadias: Please see my updated answer, especially please note that in the context of defining function parameters in C `char []` is equivalent to `char *`, as well as `char *[]` being equivalent to `char **` ... – alk Jan 31 '17 at 21:09
  • @kavadias: Also please note that any array passed to a function decays to a pointer to is 1st element. – alk Jan 31 '17 at 21:11
  • You are right! I thought that there would be an error, if the function was declared as, e.g., `int leer_fichero (struct fichpiezas vpiezas[TAM+1])`, calling it like `leer_fichero(vpiezas);` in main, but I was wrong. An array argument is a declaration --not a definition-- of an array, so it is always, simply, a pointer; whereas inside function or global scope it is always a definition (unless `extern` is used). – kavadias Feb 02 '17 at 23:50