Array of objects

Started by
10 comments, last by CrazyCdn 17 years, 8 months ago
..........
Advertisement
Can you show us some more code of your function and the functions that can't access it?
We should do this the Microsoft way: "WAHOOOO!!! IT COMPILES! SHIP IT!"
void UnitLoad(){ long end; long unitnumber; string line; ifstream fin; fin.open("units.txt"); fin.seekg(0,ios::end); end = fin.tellg(); fin.close(); unitnumber = end/64; CUNIT_INFO *Unit; CUNIT_INFO unitinfo; unitinfo.unitnumb = unitnumber; Unit = new CUNIT_INFO[unitnumber]; fin.open("units.txt"); fin.seekg(0,ios::beg);	for (int i=0; i<=unitnumber; i++)	{	 fin>>line>>Unit.name;	 fin>>line>>Unit.id;	 fin>>line>>Unit.health;	 fin>>line>>Unit.movement;	 fin>>line>>Unit.x>>Unit.y>>line;	} }

And well I can't access it for any other function
Hello Crackingod,

I do not fully understand what you mean.

If Unit is a global variable then is should be available for other functions in the same file-scope (even beyond the file-scope, but with an addition external declaration).

The following should be possible:
#include <Windows.h>// Other includes...// Object definitions...class CUNIT_INFO{	public:		int unitnumb;		string name;		int id;		int health;		int movement;		int x;		int y;};// Global variable declarationsCUNIT_INFO* Units = NULL;CUNIT_INFO Unit;int UnitCount = 8192;// Declare functionsvoid InitializeUnits();void Update();void DrawLevel();void DrawUnits();int main(){	// Inits	Units = new CUNIT_INFO[UnitCount];	InitialiseUnits();	// Do game routine here	while(Quit == false)	{		// Do game updates		Update();		// Draw		DrawLevel();		DrawUnits();	};	// Free with 'new' allocated memory	delete Units;	return 0;}void InitializeUnits(){	for(int i = 0; i < UnitCount; i++)	{		Units.id = i;		Units.health = 100;	}}void Update(){	// Do game update	// Do unit position update}void DrawLevel(){	// Draw level}void DrawUnits(){	// Draw units}


But the next is more elegant:

#include <Windows.h>// Other includes...// Object definitions...class CUNIT_INFO{	public:		int unitnumb;		string name;		int id;		int health;		int movement;		int x;		int y;};// Declare functionsvoid InitializeUnits(CUNIT_INFO* Units, int Count);void Update(CUNIT_INFO* Units, int Count);void DrawLevel();void DrawUnits(CUNIT_INFO* Units, int Count);int main(){	CUNIT_INFO* Units = NULL;	int UnitCount = 8192;	// Inits	Units = new CUNIT_INFO[UnitCount];	InitialiseUnits(Units, UnitCount);	// Do game routine here	while(Quit == false)	{		// Do game updates		Update(Units, UnitCount);		// Draw		DrawLevel();		DrawUnits(Units, UnitCount);	};	// Free with 'new' allocated memory	delete Units;	return 0;}void InitializeUnits(CUNIT_INFO* Units, int Count){	for(int i = 0; i < Count; i++)	{		Units.id = i;		Units.health = 100;	}}void Update(CUNIT_INFO* Units, int Count){	// Do game update	// Do unit position update}void DrawLevel(){	// Draw level}void DrawUnits(CUNIT_INFO* Units, int Count){	// Draw units}


The are more ways, but these should work.

Hope this help,

Regards,

Xeile
Of course you can't access it in another function. :)

See, you created the objects on the heap, so they're still around, but the pointer to them was created on the stack, and stopped existing when that function ended. Xeile's solution solves the problem, and if this is a class member function, making this pointer a member variabele will solve it as well.
However, don't forget to destroy this array when you don't need it anymore, using the delete [] operator. Otherwise, you've got a memory leak...
Create-ivity - a game development blog Mouseover for more information.
As Xelie said, you're creating memory on the free store, which can be accessed, but the problem is, you're not returning any information on where it is. The "Unit" pointer is created in the local scope for the function, but when the function returns, the pointer is destroyed, therefore you have memory sitting in the middle of your program. So, if you wish to access it, you should return the address of the memory. This can easily be done by changing the return type to CUNIT_INFO*. So, change your function to:

CUNIT_INFO* UnitLoad(){ long end; long unitnumber; string line; ifstream fin; fin.open("units.txt"); fin.seekg(0,ios::end); end = fin.tellg(); fin.close(); unitnumber = end/64; CUNIT_INFO *Unit; CUNIT_INFO unitinfo; unitinfo.unitnumb = unitnumber; Unit = new CUNIT_INFO[unitnumber]; fin.open("units.txt"); fin.seekg(0,ios::beg);	for (int i=0; i<=unitnumber; i++)	{	 fin>>line>>Unit.name;	 fin>>line>>Unit.id;	 fin>>line>>Unit.health;	 fin>>line>>Unit.movement;	 fin>>line>>Unit.x>>Unit.y>>line;	}  return Unit;  //Returns the address so you can use the memory. }CUNIT_INFO* Unit = UnitLoad();  //Now you can use this GLOBAL SCOPE variableUnit[1].name = "Hiya";          //to access the data
We should do this the Microsoft way: "WAHOOOO!!! IT COMPILES! SHIP IT!"
crackingod - this is off topic but I am a bit concerned by the logic in your unit loading function. You appear to be getting the size of the file in bytes, then dividing this by 64 to get the number of units.

You are reading a text file so I can't really understand how the length of each unit's details in the file would be exactly 64 each time.

I don't quite understand all this:

fin >> line >> Unit.x;

stuff either, unless you have a name for each attribute in the file that you are ignoring. You know this line will read in two whitespace seperated words, and discard the first since line is a local variable?

Sorry if I have misunderstood the way your file format works. It just looked a bit "wrong" at first glance.
Hi, thanks for your reply.
I started looking into unit stuff before you replied onto the other topic, so I thought that a dynamic array to store all the unit info would look nice.
My text file basically looks like this for the units:

Unit: SettlerId: 1Health: 100Movement: 1Position: 3 3*Unit: WarriorId: 1Health: 050Movement: 1Position: 3 3*


It is basically for easier reading/editing.

So yes, the size of each unit until the star is 64, the point being that the name tag will always be of fixed size, like the health etc... (for example 050).
Now yes this looks dodgy but thats the first thing I thought and it works. Probably not the best way to do it I admit. If you have any ideas for the file reading?
Welcome to C++. (BTW, this really should go in For Beginners.)

Data file:

Notice no 'hacked' numbers or constrained-length strings. I also took out the labels, because they actually make the file *harder* to read. Finally, I made it be one entry per line, to avoid the need for '*' delimiters.

Settler 1 100 1 3 3Warrior 1 50 1 3 3


Reading code:

Notice how the reading is done by grabbing individual lines and re-parsing them. This is less efficient, but I usually recommend it as being much less error-prone. In particular, this makes sure that file reading for each line starts at the proper beginning of each line (if you read into a number at the end of a line, it will leave the newline on the stream, which would be picked up by a subsequent getline() call).

struct Unit {  // If it's just going to be a collection of data, then just use a struct.  // However, you really should take the time to learn some proper class design.  // Note that it makes no sense at all to store the "total number of units"  // into every Unit.  string name;  int id;  int health;  int movement;  int x;  int y;};// I encapsulate the process of reading a single struct from a stream, thus:istream& operator>>(istream& is, Unit& u) {  return is >> u.name >> u.id >> u.health >> u.movement >> u.x >> u.y;}// Now, we return the objects, in a standard library container:// std::vector comes from <vector>// std::istringstream comes from <sstream>// By using the vector, we never have to add our own code to track the number // of units: we can always ask it for its .size(). As well, the memory// management gets done for us.vector<Unit> readUnitsFromFile() {  fstream fin("units.txt");  vector<Unit> result;  string line;  while (getline(fin, line)) {    istringstream ss(line);    Unit u;    ss >> u;    result.push_back(u);  }  return result;}
Hey, thanks a lot, that works perfectly.
So now I manage to load both my map info and my unit info.
To display the units on the map, I was thinking about checking each time a cell was created wheter a unit existed on that cell (by checking position) and if so draw the unit.

This topic is closed to new replies.

Advertisement