# Thread: 2d array and fwrite and fread

1. ## 2d array and fwrite and fread

Hi! I've been looking for working code example that uses 2d arrays with fwrite and fread but haven't found any. So I tried to realize it myself but I cannot get it work. The goal is to make 2d array according to the given size, for example 10x10 and then to write these values into file and afterwards to read these values by using fread. I don't know if save_table function works correctly, because get_table_size returns 0 although it should return 10 because test program makes 10x10 table. Any ideas?

Code:
```int multiply(int x, int y)
{
return x*y;
}

int add(int x, int y)
{
return x+y;
}

int ** create_table(int size, int (* oper) (int, int))
{
int x;
int y;
int **2darray;
2darray = malloc (size*sizeof(int*));

for(x = 0; x < size; x++)
{
2darray[x] = (int*)malloc(sizeof(int)*size);
for(y=0;y<size;y++)
{
2darray[x][y]=(* oper)(x,y);
}
}
return 2darray;
}

int save_table(FILE * fp, int ** table, int size)
{
int x=0;
if(fp==NULL)
{
return 0;
} else {
for(x;x < size;x++)
fwrite(table[x],sizeof(int),size,fp);
}
return 1;
}

int get_table_size(FILE *file)
{
int nitems;

if(file==NULL)
return 1

return nitems;
}```

2. But you never write the size of the array to the file! How can it then read it later?
And you seriously need to indent the code.

3. Originally Posted by Elysia
But you never write the size of the array to the file! How can it then read it later?
And you seriously need to indent the code.
Code:
`fread(&nitems,sizeof(int),1,file);`
returns the number of lines as I've read from different sites.
I don't know how fwrite and fread behaves with 2d arrays, how it distinguishes between x and y. Using fprintf I can use for example '\n' and when reading data back with fread I can tokenize. But the last one is not my goal. I just want to make as short and effective code as possible.

4. That's the read - where's the write?
Understand that fwrite doesn't care what data it takes - it just dumps it right out. It does not care if it's a string, or an integer, or whatever. It writes as many bytes as you tell it to do, period.
It's your responsibility to write the array. Just feed it the individual pointers and size.

5. Since this line:
Code:
`    int **2darray;`
prevents the code from compiling, can we assume that the code you have posted is not actually the code you are using? And as such, we do not know if this code is correct in any other way either?

But Elysia has it right - you are not writing out how large the data is, so how would you expect to be able to read it back?

--
Mats

6. Originally Posted by Elysia
That's the read - where's the write?
Understand that fwrite doesn't care what data it takes - it just dumps it right out. It does not care if it's a string, or an integer, or whatever. It writes as many bytes as you tell it to do, period.
It's your responsibility to write the array. Just feed it the individual pointers and size.
That's the write:
Code:
`fwrite(table[x],sizeof(int),size,fp);`

7. That writes the array, does it not? Not the size.

8. I think what the problem here is that totalnewbie doesn't understand what gets stored in the file.

When you use fwrite(), it will write nitems * itemsize bytes of data. It doesn't store the size of such a write in any way. It is exactly the same thing to loop through nitmes times and use 1 as nitems, as it is to do one fwrite with a nitems written all in one go.

So if you want to store the size in the file, you will need a separate fwrite() to store that. Or you could, perhaps, examine the size of the file and figure out what the actual size is [this works if the size is always symmetrical, e.g. a square or rectangle with known proportions of the sides - it won't work if it's equally legal to have a 10 x 1 or 2 x 5 or 5 x 2 or 1 x 10 array stored in the file, in that case you would need to store both x and y dimensions (well, you could store just one and determine the other from that, but it's just extra work to do that - and saving 4 bytes is probably not worth the extra effort)].

--
Mats

9. That pretty much sums up what I said. Fwrite only writes whatever data you pass it. It parses the data as "raw" data, not as types and just dumps it to the disk.
It does not care if it's an integer, a string or whatever. Since it does not know the data, it does not write the size.

10. I have that example: http://www.daniweb.com/forums/thread52253.html but I cannot find anything like that about multidimensional array. I've been looking for multidimensional example but haven't found. That's the way I learn new things - experimenting with working examples.

11. It works the same for a multi-dimensional array allocated on the stack.
For dynamically allocated arrays, you must store the size and write each element separately because they are not adjacent to each other in memory. Plus you must know how much memory to allocate beforehand before you read it back. Unless, of course, the size is static (always the same).

12. There is absolutely no difference between writing a 2D array and 1D arrays (or any other data) - except a complication in your case is that your array is dynamically allocated, so you can't write it as one big lump - you have to write a row at a time, as that is how the memory is allocated.

However, when you read your data back, you either need to know it's size by implication (e.g. you know the applicatikn writes a 100 x 100 matrix, so you read 100 x 100 matrix bac) or you need to STORE the size within the file when you write the file (or use the size of the file to figure out the size of the content). Your current code is NOT storing the size of the array, so you are not able to read that information from the file.

--
Mats

13. Originally Posted by Elysia
It works the same for a multi-dimensional array allocated on the stack.
For dynamically allocated arrays, you must store the size and write each element separately because they are not adjacent to each other in memory. Plus you must know how much memory to allocate beforehand before you read it back. Unless, of course, the size is static (always the same).
Ok, just tell me wheter I am riht or not.
1. If I make 10x10 table (dynamic array) then all of these memory cells are side by side and figuratively speaking the beginning of the memory cell number is 1 and the end of the memory cell is 100. For my case the size of the array is given only once and it wouldn't be changed during the program runtime.
2. To read the size of the array afterwards I think to add one element to the array for storing the size. As for my case the first one is the size and the elements from 2 to 101 are values.
3. For fwrite I look it's size up int the first array cell, then I do the array for that size and then I read all of these values from the file by using fwrite into the array.

That's the idea how I try to realize this program now. Does it work?

14. Originally Posted by totalnewbie
Ok, just tell me wheter I am riht or not.
1. If I make 10x10 table (dynamic array) then all of these memory cells are side by side and figuratively speaking the beginning of the memory cell number is 1 and the end of the memory cell is 100. For my case the size of the array is given only once and it wouldn't be changed during the program runtime.
As was explained to you, no they are not.
Your dynamic 2D array works by defining an array of pointers, and then allocating memory and store their address in those pointers.
That memory is not adjacent!
Each call to malloc is not guaranteed to be side-by-side.

2. To read the size of the array afterwards I think to add one element to the array for storing the size. As for my case the first one is the size and the elements from 2 to 101 are values.
No. Why would you need to do that?
You can issue two writes and two reads.
The first writes the size. The second writes the data.
And vice versa.

3. For fwrite I look it's size up int the first array cell, then I do the array for that size and then I read all of these values from the file by using fwrite into the array.
I have no idea what that just meant, but as I explained above. Write size first, then the array. Similarly, read the size first, allocate, read the array.

15. I am getting the error: "glibc detected malloc(): memory corruption: 0xb7fd3008" when function int ** load_table(FILE * file, int size) starts under UNIX. It works nicely under Windows.

Code:
```#include "mathalizer.h"

int multiply(int x, int y)
{
return x*y;
}

int add(int x, int y)
{
return x+y;
}

int ** create_table(int size, int (* oper) (int,int))
{
int x;
int y;
int **array;
if(size<1) return NULL;
array = (int **)malloc(size*sizeof(int*));
if(array==NULL) return 1;

for(x=0;x<size;x++)
{
array[x]=(int*)malloc(size*sizeof(int));
}

for(x=0;x<size;x++)
{
for(y=0;y<size;y++)
{
array[x][y]=(* oper)(x,y);
}
}

return array;
}

int save_table(FILE * fp, int ** array, int size)
{
int x;

for(x=0;x<size;x++)
{
fwrite(array[x],sizeof(int),size,fp);
}
fclose (fp);

return 1;
}

int ** load_table(FILE * file, int size)
{
int x;
int **array2;
array2 = (int **)malloc(size*sizeof(int*));
if(array2==NULL) return 1;

for(x=0;x<size;x++)
{
array2[x]=(int*)malloc(size*sizeof(int));
}

for(x=0;x<size;x++)
{