I've been stuck on this for a few nights now and although I have found some examples for pointer arrays and single objects, I have not found a solution.
I have a larger assignment that needs to be able to read and write from a binary file, however, as I read from what I think is written correctly I either receive garbage (perhaps not written correctly) or segfault.
Oddly enough, the "record count" routine I modified seems to return the correct amount after the .dat file is initialized, so my assumption is I'm reading it back in incorrectly
Any pointers, no pun intended, would be appreciated:
You shouldn't do this file.write( (char*)(&pers[i]), sizeof(Person)); for two reasons.
1. If you switch the declaration order of name and age in your Person class, it will be written/read from the file differently, and
2. sizeof(Person) and sizeof(std::string) return 36 bytes and 32 bytes, respectively (on my computer). What if a Person has a name that takes up more than 32 bytes? 36 bytes will still (incorrectly) be written to the file! You can only trust sizeof(Person) if your Person class contains plain old data.
Instead, to write to the file, what I would do is:
1. Write the length of the name (excluding '\0') as an int (so you know how many chars to read)
2. Write the char* contained in the name
3. Write the age as an int
Then, to read:
1. Read the length of the name
2. Read the char* (with the length read above). Put it into a std::string
3. Read the age
4. Assign the name and age to a Person instance with a Set method
Is this because string can be of any size (ie grows)?
It's apparently working great with the following modifications to Person, namely changing the string to char[50] then setting it to '' in the constructor so when I write out 200, some don't get garbage.
Person.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#ifndef PERSON_H
#define PERSON_H
class Person
{
protected:
char name[50];
int age;
public:
Person();
void getData();
void showData();
};
#endif // PERSON_H
Is this because string can be of any size (ie grows)?
Yes, you can't trust sizeof (in this context) because of this. Apparently, on my computer the internals of std::string add up to give it a size of 32 bytes. But, no matter the length of the string, it always gives 32 bytes. Also, file.write was probably just writing the internals of the string, and thus just a pointer to the first character when it came to write the actual char*. Since that pointer is no longer valid upon reading back from the file, you got garbage.
It works fine with your current implementation because now you've got plain old data as its members (and a const limit on the length of the char array, name). Again, if you change the order of the member variables, your code won't be able to read from a file that was written to with a different ordering (or when run on a computer with a different endian scheme).