binary files / dynamic memory

Good day. Lets simplify my problem. There are two programs. One writes to a binary file. The other reads from it. We write to the file somehow like this:


struct a {
int b; //the number of cars
int *c; //number of eatch car
}d;

d.b = 2; //for example there are 2 cars
d.c = new int[ b];
d.c[1]=11; //first car number is 11
d.c[2]=22; //second is 22

Now we write this struct into a binary file.

The question:
How do I read this using other program into identical struct?
If I perform the read((char*)&d,sizeof(a)); I get the correct number of cars, but there's no way I can define how many cars has to obtain the numbers.So the *c values are some random 3495823948...

The true programs are much more complex by the way.




Last edited on
One writes to a binary file. The other reads from it

Is there any chance that you can use xml files or something like that? If you write binary, the byte sequence is implementation-defined (well, OS defined), so the files you generate are not portable and hard to debug (do you know if the error is in the reading- or in the writing part?).
read((char*)&d,sizeof(a))

Use std::fstream, set to ios::binary, if you must.
Your problem is that sizeof(a) is sizeof(int) + sizeof(int*), you want sizeof(int)+sizeof(int)*length of your array.
int *c;

Use a std::vector if you can.

PS
you have a question about file I/O, but the part is missing in your post is the I/O-code. For any further assistance, I suggest you post it.
Last edited on
Thanks. The question concerns the reading part. I just can't figure out the way how can I request for dynamic memory if I don't know how much I am going to need it yet (before reading the whole struct). Or maybe I don't even have to do that?
Last edited on
read first the number of cars (sizeof(int)) and read afterwards from the current position your array (number_of_cars*sizeof(int)).
There's nothing wrong with straight-binary I/O, so long as you are strict about endian and size issues.

I think that your problem has to do with that pointer. It is useless to write a pointer to disk, because once your program terminates (if not before) it becomes meaningless.

jmc gave you the basic formula for the correct answer: Your binary file should look something like
3 12 9 77


First read the number of cars, then allocate enough memory, then read the car numbers.
1
2
3
  f.read( (char*)&d.b, sizeof(int) );  // number of cars
  d.c = new int[ d.b ];  // allocate space for all those cars
  f.read( (char*)d.c, (sizeof(int) * d.b) );  // read them into memory 



More about endian and size issues:
exception made a point about problems when using istream::read(). If you want your code to work properly cross-platform, you need to explicityly define 1) byte-order (endianness) and 2) integer size.

So if you were to say that your file will be in network byte order (big-endian) and integers are four bytes, then you can write routines like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int readint( istream& ins )
  {
  int result = 0;
  char buf[ 4 ];
  ins.get( buf, 4 );
  if (ins)
    for (int n = 0; n < 4; n++)
      result = (result << 8) +buf[ n ];
  return result;
  }

int readints( istream& ins, int count, int* ints )
  {
  int n;
  for (n = 0; ins && (n < count); n++, ints++)
    *ints = readint( ins );
  return n;
  }

You can use them both handily:
1
2
3
4
d.b = readint( f );
if (!f) complain();
d.c = new int[ d.b ];
if (readints( f, d.b, d.c ) != d.b) complain();

etc.
Topic archived. No new replies allowed.