Objects and Binary files (RPG game)

For my school project we are working through building a basic RPG style game with custom classes and reading/writing to a binary file. I believe I have all of my classes built correctly, however I am stuck at getting it to write to file and read for the file properly.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Start program

	Backpack Basic;        //Create backpack object
	CoinPouch small = 100; //create CoinPouch object


	Character* P1 = new Character; // create character object
	P1->setName("Aldon");           //initialize character name
	P1->setFunds(small);		//initialize character funds
	P1->setPack(Basic);		//initialize character pack


	Potion Potion1;                   //Initialize 2 potions
	Potion1.setName("Strength");
	Potion1.setDesc("Gives user strength");
	Potion1.setPotency("1");
	Potion1.setCost(150);

	Potion Potion2;
	Potion2.setName("Speed");
	Potion2.setDesc("Gives user speed");
	Potion2.setPotency("2");
	Potion2.setCost(100);

	Basic.AddToPack(Potion1);            //Add potions to backpack
	Basic.AddToPack(Potion2);

	WriteToDataFile(P1);                 //Write Character P1 to file 
	ReadFromDataFile(P1);



It throws an erro a the write to file and says "Exception thrown at 0x7AA408CC (ucrtbased.dll) in PotionsGameRPG.exe: 0xC0000005: Access violation reading location 0xFDFDFDFD."



Here is what my file ops looks like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void ReadFromDataFile(Character character_array[])
{
	ifstream charData("data.bin", ios::in | ios::binary); //open file to read from it

	if (charData.is_open())
	{
		for (int i = 0; i < MAX_GUYS; ++i)
		{
			character_array[i].deserialize(charData);
		}
		charData.close();
	}
	else
	{
		cout << "Error: could not open file to read." << endl;
	}
}

void WriteToDataFile(Character character_array[])
{
	ofstream charData("data.bin", ios::out | ios::binary);

	if (charData.is_open())
	{
		for (int i = 0; i < MAX_GUYS; ++i)
		{
			character_array[i].serialize(charData);
		}
		charData.close();
	}
	else
	{
		cout << "Error: could not open file to write." << endl;
	}

}
https://www.tutorialspoint.com/reading-and-writing-binary-file-in-c-cplusplus

All your strings need to be C strings, char arrays with a predefined size no matter how much of the actual array is occupied by data. Trying to do a simple read/write with C++ strings may work some of the times, and definitely go *ka-blooie* most of the time.
You create only a single Character. At line 25, you loop for MAX_GUYS times. You don't show MAX_GUYS. If it is > 1 you are going to be indexing out of bounds.
Thank you for the input so far!

I was able to tinker around and get it working. It writes the character object to a binary file. However the output was not what I expected.
A character has "String name, Object backpack, Object CoinPouch" and in the binary file using hex edit I only see the name.

Using my current save method, is it missing the pointers inside the character class? or is what was saved to be expected?
Last edited on
What is the definition of Character? What does serialize() and deserialize() do?

L7 defines P1 as a pointer to Character. Yet in ReadFrom...() and WriteTo...() the params expected are arrays....
All your strings need to be C strings, char arrays with a predefined size no matter how much of the actual array is occupied by data. Trying to do a simple read/write with C++ strings may work some of the times, and definitely go *ka-blooie* most of the time.


@George P,

the tutorial you linked does exactly that.
A simple read/write with C++ std::string may work if SSO (small string optimization) is used and the string is small enough to fit into the small buffer. It definitely will not work if SSO is not used or the string is too large to fit. In any case, using a simple read/write with C++ std::string is very flaky at best. It should never be used. If dynamic memory is used (ie with std::string, std:vector etc), then a proper serialization/deserialization routines are needed (which may be as simple as converting to say a CSV format or to json etc) or to a designed bespoke format. If the contents of a struct/class need to be read/written from/to a file, then this may be one of those times when c-style arrays (c-style string is just a char array) are used for storage in the struct. Much depends upon what is stored in the struct and the operations performed on the members.
thmm wrote:
the tutorial you linked does exactly that.
I know it does. Kinda the reason why I gave the link, ya know.

I mentioned it because we don't know what the OP uses to store text data member, C or C++ strings. Caution is therefore advised.

I mentioned it because I learned the hard way doing simple writing/reading of binary files with C++ strings is a very iffy proposition at best without some serious serialization support. Support that Boost has, and it ain't simple.
a fixed sized c-string makes it easy if at all possible. Most real data has a max length defined in the documentation, and its that floating length that makes most of the problems. Zero out unused length so your file is easier to compress, esp if the max length vs actual is overkill like you use 10 bytes and have 500.
Topic archived. No new replies allowed.