0

I am working on a test on C++ where one program writes an object in a file, and another program reading the contents of the file.

The write segment:

DClass cc;
ofstream ofs;
ofs.open("data.dat", ios::binary);
cc.enroll = 11;
cc.name = "tom the cat";
ofs.write((char *)&cc, sizeof(cc));

The read segment:

DClass cc;
ifstream ifs;
ifs.open("data.dat", ios::binary);
while (!ifs.eof())
{
    ifs.read((char *)&cc, sizeof(cc));
    cout << cc.enroll << " " << cc.name << endl;
}

The structure of DClass:

struct ConClass
{
    int enroll;
    string name;
};

When running the read program, the output is the data in the file, but twice,

11 tom the cat

11 tom the cat

It seems that the program has no errors but the while loop in the read program does not reach the eof after reading the data, so it print the data in the cc which is not overwritten in the second iteration.

What can I do to make sure the program runs properly?

I am compiling this in mingw on windows, and do not see such problem in Borland C++.

Community
  • 1
  • 1
Krishanu
  • 552
  • 3
  • 21
  • 3
    [Why !.eof() inside a loop condition is always wrong.](https://stackoverflow.com/q/5605125/9254539) Suggest `while (ifs.read((char *)&cc, sizeof(cc))) { ... }` (considering the last update to the Borland compiler was 1997 -- the difference is no surprise) – David C. Rankin Mar 29 '20 at 05:35
  • 3
    Note: you can’t just write out the memory of a struct containing objects. `string` May have its data stored anywhere in heap so your program will fail badly. You also don’t check if the read succeeded the second time. – Sami Kuhmonen Mar 29 '20 at 05:36
  • The eof flag inside the stream is only set after you try (and fail) to read beyond the end of file. Your first read succeeds, but the eof is not set yet. The second read fails, leaving the data you have in memory untouched, hence it looks like it 'reads' twice, while it actually doesn't Now the eof flag is set and you finally exit the loop. Hope my explanation makes enough sense. – Boris Lipschitz Mar 29 '20 at 05:38
  • @DavidC.Rankin Thanks I get whats wrong. – Krishanu Mar 29 '20 at 05:40
  • And yep, @SamiKuhmonen is absolutely right, you don't just dump objects binary data into files. You could do this with C style string (char name[100] or something), but with std::string thats a terrible idea. – Boris Lipschitz Mar 29 '20 at 05:40
  • `string` was quite a different thing when the last Borland compiler was written. Agree with @BorisLipschitz - you would need to use the `.c_str()` raw value to write it out. – David C. Rankin Mar 29 '20 at 05:41
  • FYI: [C++ FAQ: Serialization and Unserialization](https://isocpp.org/wiki/faq/serialization) – Scheff's Cat Mar 29 '20 at 05:48
  • This doesn't address the question, but get in the habit of initializing objects with meaningful values rather than default-constructing them and immediately overwriting them. In this case that means changing `ofstream ofs; ofs.open("data.dat", ios::binary);` to `ofstream ofs("data.dat", ios::binary);` and making the analogous change for `ifs`. – Pete Becker Mar 29 '20 at 16:04

0 Answers0