0

I have a struct. I would like to have an array in this struct, and then write this to a binary file, and then read it. However this array should be dynamically allocated. I'm not sure how should I approach this. My current guess is this:

I define and then write the struct to the file like this:

struct map {
    int *tiles;
};

int main() {

    map sample;

    sample.tiles = new int[2];

    sample.tiles[0]=1;
    sample.tiles[1]=2;

    ofstream file("sample.data", ios::binary);

    file.write((char *)&sample, sizeof(sample));

    file.close();

    return 0;
}

Then read it like this in another program:

map test;
ifstream file("sample.data", ios::binary);
file.read((char *)&test, sizeof(test));

When I want to check the results with

cout << test.tiles[0];

I get a weirdly huge number, but clearly not the number I originally wrote to the file.

What is the right way to do this? How can I read an array without knowing its size?

4
  • 1
    First, I would suggest another name for your struct, you could collide with std::map Commented Nov 27, 2016 at 16:18
  • 1
    That will not work size() is a compile-time operator. If you don't know the size ahead of time, use a std collection such a vector or similar. Commented Nov 27, 2016 at 16:20
  • 1
    By the way, your code is here leaking memory (when writing) and accessing uninitialized memory (when reading). You should read about rule of 3/5/0, and redesign your structure, maybe using std::unique_ptr<int[]> Commented Nov 27, 2016 at 16:25
  • @kebs, OldProgrammer, wasthishelpful - Thanks for all these tips! I'll keep them in mind. Commented Nov 28, 2016 at 7:38

2 Answers 2

3
file.write((char *)&sample, sizeof(sample));

This writes to the file the following structure:

struct map {
    int *tiles;
};

That is, a structure that contains a single pointer. A pointer is an address in memory. So, what you end up writing to the file is one, meaningless, raw, memory address.

Which, obviously, is of absolutely no use, whatsoever, when it gets read back later. You did not write any of your integers to your file, just what their address in memory was, in a program that long ago terminated.

In order to do this correctly, you will need to:

  1. Record how many int-egers the tiles pointer is pointing to.

  2. fwrite() not the structure itself, but the integers that the tiles pointer is pointing to.

You will also need to write, to the file, how many integers there are in this array. If the file contains only these integers, this is not really needed, since you can simply read the entire contents of the file. But, if you expect to write some additional data in the file, it obviously becomes necessary to also record the size of the written array, in the file itself, so that it's possible to figure it out how many integers there are, when reading them back. The simplest way to do this is to write a single int, the size of the array first, followed by the contents of the array itself. And do the reverse process, when reading everything back.

Sign up to request clarification or add additional context in comments.

1 Comment

I took your advice, and instead of storing the struct, now I write the size of the array and the array itself to the file.
1

Your sample object contains a pointer tiles and it's the pointer value that you're writing to the file. What you want to write is what the pointer points at. In your example, you'd want to do file.write(sample.tiles, 2*sizeof(*sample.tiles));. It's 2* because you did new int[2]. In general, you'd also want to save the size (2 in this case) in the file so you know how many ints to read back in. In this simple case you could infer the 2 from the size of the file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.