My post-increment operator isn't working

Started by
11 comments, last by JohnBolton 16 years, 10 months ago
I've used "pp" to represent the plus-plus increment operator since it doesn't appear. So, I have a .txt file with this in it:

First room description.
door
Second room description.
hole
Third room description.
window

The 1,3,5 lines are descriptions of the rooms, and the 2,4,6 lines are the exits available in those rooms. Now I'm trying to read in this information into a vector, and then send this information to a function that creates rooms, like this:

void GenerateRooms(int DIFFICULTY)
{
	vector<string> room_descriptions;

	ifstream descFile ("RoomDescriptions.txt");

	if( descFile.is_open() )
	{
		while( !descFile.eof() )
		{
			string description;
			getline( descFile, description );
			room_descriptions.push_back(description);
		}
		descFile.close();
	}	


	vector<string>::iterator iter = room_descriptions.begin();

	// Initialize the various Rooms.  
	// The first parameter is the description, 
	// the second parameter is the exits, and 
	// the third parameter is the hint.
	// the fourth parameter is the chance that a monster will spawn in the room
	AddRoom(*(iter)pp, *(iter)pp, "Try the door.", DIFFICULTY);
	AddRoom(*(iter)pp, *(iter)pp, "Try the hole.", DIFFICULTY);
	AddRoom(*(iter)pp, *(iter)pp, "Try the trapdoor.", DIFFICULTY);
	AddRoom(*(iter)pp, *(iter)pp, "none.", DIFFICULTY);

So in my vector I want the 0th element to be the room description, the 1st element to be the exits, the 2nd element the second room description, the 3rd element the second room's exit, ... But I can't get the pp operator to work correctly. When I run this I get this output:

door
Exits: First room description.

Where those lines should be switched. What is the correct placement of the pp operator? I've tried every possibility I could find, although perhaps some funky parentheses placement is needed.
Advertisement
Hmmm..., I don't understand what all the trouble is. You are making things more complex then they need to be.

Here is what I would do:
void GenerateRooms(int DIFFICULTY){    vector<string> room_descriptions;    ifstream descFile ("RoomDescriptions.txt");    if( descFile.is_open() )    {        while( !descFile.eof() )	{            string description;	    getline( descFile, description );	    room_descriptions.push_back(description);	}	descFile.close();    }	    for( int i = 0; i < room_descriptions.size(); i += 2 )        AddRoom( room_descriptions.at( i ), room_descriptions.at( i + 1 ), DIFFICULTY );}


As you can see I have removed the hint because it did not work with the loop, but you should probably be loading that from a file anyways.
Mike Popoloski | Journal | SlimDX
Yeah I was going to put all the info in the .txt file and run it through a for loop just as you did, but I couldn't get the pp operator to work. I'll just go straight to the for loop I guess, I'll go see if it works.

Good lord, this error was printed straight to the console:
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information."

Uhh...

EDIT: Ah found the problem. I added the hint into the for loop, but I didn't change the increment in the for loop to add 3 instead of 2. So I changed it to 3 and it works fine now.
Don't test for end-of-file. The end of file flag is only set *after* you make an unsuccessful read.

Instead, test the stream itself. A stream has an implicit convertion to a pointer, which if NULL indicates that the stream is in an error state (for whatever reason, including EOF). All stream operations (such as << or >>, and std::getline) return the stream itself. We can simply test the return value of std::getline to see if it succeeded.

So:
if( descFile.is_open() ){    std::string description;    while( std::getline( descFile, description ) )    {			room_descriptions.push_back(description);    }    // dont need this, std::fstream objects close themselves    // descFile.close();}	


With this, if the stream isnt open std::getline will fail on the first read so we dont even need to test if it opened correctly (unless you wish to alert the user that the file didn't open...).

Like so:
std::string description;while( std::getline( descFile, description ) ){		   room_descriptions.push_back(description);}


You need to be very careful with you other loop, for example test if there are an even number of entries to ensure you don't access invalid memory.
I'm assuming you're warning me to make sure I have an even number of entries because of the i += 2 increment in the for loop? I changed that to increment by 3 so I can have more in the .txt file, but, why would it matter if I have an even or odd number of entries? I don't see how I can access invalid memory. For every room there is a description, an exit, and a hint that is read from the .txt file. I can't think of how I would run into invalid memory.

If there were 100 rooms, that would be a vector size of 300, so the for loop would run 100 times. If there were 99 rooms, that would be a vector size of 297, and the for loop would run 297/3 = 99 times.
Quote:Original post by Shakedown
I'm assuming you're warning me to make sure I have an even number of entries because of the i += 2 increment in the for loop? I changed that to increment by 3 so I can have more in the .txt file, but, why would it matter if I have an even or odd number of entries? I don't see how I can access invalid memory. For every room there is a description, an exit, and a hint that is read from the .txt file. I can't think of how I would run into invalid memory.

If there were 100 rooms, that would be a vector size of 300, so the for loop would run 100 times. If there were 99 rooms, that would be a vector size of 297, and the for loop would run 297/3 = 99 times.


You are reading in data from an external source. All external data should be validated. If you don't do this, your program will crash sometime. You might accidentally forget to add a description to some room, for example. Your program may crash immediately, or you could end up having some form of subtle memory corruption that will leave you scratching your head.

If you intend on releasing your game, this is even more important. You know that your program will crash if you corrupt your file, users may not.

Seeing as you know this possibility exists, its almost irresponsible not to fix it.

Quote:Original post by rip-off
Quote:Original post by Shakedown
I'm assuming you're warning me to make sure I have an even number of entries because of the i += 2 increment in the for loop? I changed that to increment by 3 so I can have more in the .txt file, but, why would it matter if I have an even or odd number of entries? I don't see how I can access invalid memory. For every room there is a description, an exit, and a hint that is read from the .txt file. I can't think of how I would run into invalid memory.

If there were 100 rooms, that would be a vector size of 300, so the for loop would run 100 times. If there were 99 rooms, that would be a vector size of 297, and the for loop would run 297/3 = 99 times.


You are reading in data from an external source. All external data should be validated. If you don't do this, your program will crash sometime. You might accidentally forget to add a description to some room, for example. Your program may crash immediately, or you could end up having some form of subtle memory corruption that will leave you scratching your head.

If you intend on releasing your game, this is even more important. You know that your program will crash if you corrupt your file, users may not.

Seeing as you know this possibility exists, its almost irresponsible not to fix it.


How do I validate it? Divide the vector size by 3 and if its not divisible then there's a missing line?
Quote:Original post by Shakedown
How do I validate it? Divide the vector size by 3 and if its not divisible then there's a missing line?


Almost, you cannot use division directly due to integer division. You could just drop the last entries until the vector is of correct size:
int numToDrop = vec.size() % 3;if( numToDrop ) {   std::cerr << "warning, " << numToDrop << " excess room description lines dropped\n";   vec.erase( vec.end() - numToDrop, vec.end() );}
I just did
if(room_descriptions.size() % 3 != 0){   cerr << "Error. Missing line in .txt file.";   done = true;}


done is a bool that I check at the beginning of my game loop, so it'll just display the error and then skip over the game loop and exit the game. Why do you say this doesn't work with integers?
Quote:Original post by Shakedown
I just did
if(room_descriptions.size() % 3 != 0){   cerr << "Error. Missing line in .txt file.";   done = true;}


done is a bool that I check at the beginning of my game loop, so it'll just display the error and then skip over the game loop and exit the game. Why do you say this doesn't work with integers?


Test out integer division:
for( int i = 1 ; i < 4 ; ++i )   std::cout << i << " / 3 is " << ( i / 3 ) << '\n';


Integer division truncates the answer, drops anything that would appear after the decimal place.

This topic is closed to new replies.

Advertisement