Search code examples
cc99fwritefreadstrtok

Problems with fread and fwrite saving a float matrix from .dat file to array in memory


GOAL

I need to:

1. Write, with fwrite, a N*N matrix in to a binary file. The matrix is ​​stored contiguously in memory, in an array of N * N elements.

2. Allocate another N*N array and read with fread the matrix from the previously created file, saving it, element by element, in the newly created array.

3. Print on standard output the new array.

The first array is float* and the second array must be float* too.

MY CODE

This is my code, it seems to print the right matrix in the binary file but when i read it with fread and save it into a new array, when i print the new array it prints just 0.0 0.0 0.0 ecc

void fileBinPrintMat(float* a, int dim, FILE* output){
    float x;
    for(int i = 0; i < dim; i++){
          x = a[i];
          fwrite(&x, sizeof(float), 1, output);
    }
 }
   

     
#define DIM 512

//PART 1, PRINT THE MATRIX IN .dat FILE
int main(int argc, char** argv){
    .
    .
    .
    float* M1 = calloc(n*n, sizeof(float));
        CHECK_MEMORY(M1, "CALLOC"); //MACRO for checking allocation memory
        for(size_t i = 0; i < (n); i++)
            for(size_t j = 0; j < n; j++)
                M1[(i*n)+j] = (i+j)/2.0;
    FILE* ofpbin = fopen("mat_dump.dat", "wb");
    CHECK_OPEN_FILE(ofpbin, "mat_dump.dat");
    fileBinPrintMat(M1, n*n, ofpbin); //Function that print matrix in file.dat
    free(M1);
    fclose(ofpbin);

//PART 2, SAVE THE MATRIX PRINTED IN .dat FILE IN N*N ARRAY
    FILE* ifpbin = fopen("mat_dump.dat", "rb");
    CHECK_OPEN_FILE(ifpbin, "mat_dump.dat");
    char* buffer = calloc(DIM, sizeof(char));
    CHECK_MEMORY(buffer, "CALLOC");
    float* M2 = calloc(n*n, sizeof(float));
    CHECK_MEMORY(M2, "CALLOC"); 
//READ MATRIX FROM FILE AND WRITE IT IN ARRAY M2
    int i = 0;
    float elemBuffer;
    while(fgets(buffer, DIM, ifpbin) != NULL){
        fread(&elemBuffer, sizeof(float), 1, ifpbin);
        M2[i] = elemBuffer;
        i++;   
    }
    

P.S. I know that i must check all return values of fread ecc... I will do it later

DESIRED OUTPUT

Assuming n = 4, final output matrix must be:

  0.0   0.5   1.0   1.5
  0.5   1.0   1.5   2.0
  1.0   1.5   2.0   2.5
  1.5   2.0   2.5   3.0

in binary file is something as:

 ? ? �? �?
 ? �? �? @
 �? �? @  @
 �? @  @ @@

And i think it's ok, it must be saved from .dat to array float* M2 like this:

0.0   0.5   1.0   1.5   0.5   1.0   1.5   2.0   1.0   1.5   2.0   2.5   1.5   2.0   2.5   3.0
 

MY OUTPUT

  0.0   0.0   0.0   0.0
  0.0   0.0   0.0   0.0
  0.0   0.0   0.0   0.0
  0.0   0.0   0.0   0.0

IMPORTANT:

It's an univesity homework, i just can use fread and fwrite for binary file i/o and strtok for tokenize the space between elements in file.


Solution

  • When working with binary files, the rule of thumb is that the code that reads from the file, and code that writes to the file should be identical but with reverse functions.

    What I mean by this is, in your case you have simple loop writing a continuous array of float values to file.

    This means, your read code must do the same - read a continuous array of floats from file.

    Adding extra logic to the read loop(s) makes you code parse the data in a wrong way, which is why you can not get the values back.

    So here is how you should read them:

    void fileBinReadMat(float* a, int dim, FILE* input){
        float x;
        for(int i = 0; i < dim; i++){
              fread(&x, sizeof(float), 1, input);
              a[i] = x;
        }
    }
    

    Strictly speaking, you don't need the x intermediate variable for reading or writing, but I left it in there to keep the code identical and easier to understand.