Not Using References Properly

A

A_StClaire_

hi,

my poker game does

playersActiveInRound = players;

at the start of every round where both are vector<Player> (i.e.,
containers of a user-defined class). the latter vector is everyone who
hasn't run out of money yet.

in a round, when someone folds I wish to remove them from
playersActiveInRound by calling

void Game::DropPlayer(Player& targetPlayer)
{

for(posPlayer = playersActiveInRound.begin(); posPlayer !=
playersActiveInRound.end(); ++posPlayer)
{
if((*posPlayer).GetFullName() == targetPlayer.GetFullName())
{
playersActiveInRound.erase(posPlayer);
}
}

}

and feeding it the Player identifier.

can anyone tell me why I get a crash everytime this function runs?

thx a lot
 
J

Jim Langston

hi,

my poker game does

playersActiveInRound = players;

at the start of every round where both are vector<Player> (i.e.,
containers of a user-defined class). the latter vector is everyone who
hasn't run out of money yet.

in a round, when someone folds I wish to remove them from
playersActiveInRound by calling

void Game::DropPlayer(Player& targetPlayer)
{

for(posPlayer = playersActiveInRound.begin(); posPlayer !=
playersActiveInRound.end(); ++posPlayer)
{
if((*posPlayer).GetFullName() == targetPlayer.GetFullName())
{
playersActiveInRound.erase(posPlayer);
}
}

}

and feeding it the Player identifier.

can anyone tell me why I get a crash everytime this function runs?

thx a lot
The following is a fully functioning program that uses your method without
change. Your error must be somewhere else in code you haven't shown.

#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <cmath>
#include <cassert>
#include <windows.h>
#include <list>

class Player
{
public:
std::string GetFullName() { return FullName; };
void SetFullName( std::string Name ) { FullName = Name; };
private:
std::string FullName;
};

class Game
{
public:
void InsertPlayer( Player player ) { playersActiveInRound.push_back(
player ); };
void DropPlayer(Player& targetPlayer);
void ListPlayers();
private:
std::vector<Player> playersActiveInRound;
std::vector<Player>::iterator posPlayer;
};

void Game::DropPlayer(Player& targetPlayer)
{
for(posPlayer = playersActiveInRound.begin(); posPlayer !=
playersActiveInRound.end(); ++posPlayer)
{
if((*posPlayer).GetFullName() == targetPlayer.GetFullName())
{
playersActiveInRound.erase(posPlayer);
}
}
}

void Game::ListPlayers()
{
for(posPlayer = playersActiveInRound.begin(); posPlayer !=
playersActiveInRound.end(); ++posPlayer)
{
std::cout << (*posPlayer).GetFullName() << std::endl;
}
}

int main()
{
Game MyGame;
Player Temp;
Temp.SetFullName( "Jim" );
MyGame.InsertPlayer( Temp );
Temp.SetFullName( "Joe" );
MyGame.InsertPlayer( Temp );
Temp.SetFullName( "Bob" );
MyGame.InsertPlayer( Temp );
MyGame.ListPlayers();

std::cout << "Deleting..." << std::endl;
Temp.SetFullName("Joe");
MyGame.DropPlayer( Temp );

MyGame.ListPlayers();

char wait;
std::cin >> wait;
};
 
H

Heinz Ozwirk

....
for(posPlayer = playersActiveInRound.begin(); posPlayer !=
playersActiveInRound.end(); ++posPlayer)
{
if((*posPlayer).GetFullName() == targetPlayer.GetFullName())
{
playersActiveInRound.erase(posPlayer);
}
}

You must not increment the iterator if you remove an element from the
vector. Erase moves all elements after the removed one towards the vector's
front and the iterator will address the first element originally following
the removed one. Then, as part of the for statement, you move the iterator
to the next place in the vector. In the best case this will skip one
element. In the worst case, if the element at the end of the vector has been
removed, your iterator will never be equal to end().

There are several ways to solve your problem. If all the players have
different names and you always remove at most one player, the best way seems
to separate searching and removing. Something like

Iterator it = Find(playersActiveInRound, targetPlayer.GetFullName());
if (it != playersActiveInRound) playersActiveInRound.erase(it);

HTH
Heinz
 
J

John Harrison

hi,

my poker game does

playersActiveInRound = players;

at the start of every round where both are vector<Player> (i.e.,
containers of a user-defined class). the latter vector is everyone who
hasn't run out of money yet.

in a round, when someone folds I wish to remove them from
playersActiveInRound by calling

void Game::DropPlayer(Player& targetPlayer)
{

for(posPlayer = playersActiveInRound.begin(); posPlayer !=
playersActiveInRound.end(); ++posPlayer)
{
if((*posPlayer).GetFullName() == targetPlayer.GetFullName())
{
playersActiveInRound.erase(posPlayer);
}
}

}

and feeding it the Player identifier.

can anyone tell me why I get a crash everytime this function runs?

thx a lot

This is a case where you have to look at exactly what you wrote instead
of what you think you wrote.

Specifically what do you think happens to posPlayer when you erase a player

for(...; ++posPlayer)
{
if(...)
{
playersActiveInRound.erase(posPlayer);
}
}

Think about it, you are erasing a player and moving the iterator forward
in the same iteration.

The right way is like this

while (...)
{
if (...)
posPlayer = playersActiveInRound.erase(posPlayer);
else
++posPlayer;
}

erase returns an iterator to the element after the erased element.

john
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top