Comment ferais-je pour que le dernier nom du joueur n'a pas de et non p> Mon code est: P> , code> de sorte qu'il est:
bool Commands::whoIsOnline(Creature* c, const std::string &cmd, const std::string ¶m)
{
Player* player = dynamic_cast<Player*>(c);
if (player)
{
player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, "Players online: ");
AutoList<Player>::listiterator iter = Player::listPlayer.list.begin();
std::string info;
int count = 0;
while (iter != Player::listPlayer.list.end())
{
info += (*iter).second->getName() + ", ";
++iter;
++count;
if (count % 10 == 0)
{
player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.c_str());
info.clear();
}
}
if (!info.empty())
player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.c_str());
}
return true;
}
11 Réponses :
Changer avec: p> Alternativement, vous pouvez faire quelque chose comme ça si vous ne voulez pas la virgule devant d'un nom après l'info.cpear (): p>
J'utiliserais cette approche, mais faites le subordonné de la boucle de temps imparti à la déclaration IF. Il n'y a aucun moyen le premier test de Why réussirait si le si le cas n'a pas.
Le moyen le plus simple consiste simplement à supprimer le supplémentaire "," code> à la fin:
S'il s'agit de C ++ et c'est un itérateur stl, alors si l'itérateur est un itérateur d'accès aléatoire, vous pouvez réellement demander p>
Si (iter + 1 == PLAER :: listplayer.list.end ()) p> blockQuote> blockQuote>
Si vous n'êtes pas autorisé à faire cela, vous souhaitez probablement mettre le code à l'intérieur de la boucle tandis que imprime le nom d'un joueur dans une fonction distincte et appelez cette fonction sur le premier élément avant la boucle tandis que l'appelez-le. à l'intérieur de la boucle. Ensuite, mettez le code qui imprime la virgule avant l'appel sur le nom du lecteur Imprimer dans la boucle tandis que. De cette façon, le premier appel imprime simplement le prénom, puis la boucle tandis que la boucle imprimait toujours une virgule, puis le nom du joueur, de sorte que la sortie se termine toujours avec le nom d'un joueur. P>
au lieu de le penser comme afin que vous puissiez faire quelque chose comme ça (pseudo-code ): p> de si votre langue prend en charge (quel c ++ fait): p> lecteur + "," code> y penser comme
"", "+ lecteur code>
Il serait beaucoup plus rapide de simplement itérer que sur les joueurs 2..end (s'ils existent). Si seulement quelqu'un avait suggéré que ..
Ce serait bien. Je n'ai jamais utilisé les itérateurs C ++, je ne savais pas que vous pourriez le faire avec eux.
Jetez un coup d'œil à ma réponse =) Vous avez juste besoin d'augmenter après avoir examiné la première valeur.
Presque, je pense que vous voulez dire pour chaque joueur dans les joueurs [1 ..] code>
Votre deuxième approche a besoin d'un contrôle pour vous assurer que la liste n'est pas vide.
@Mark, veuillez définir "beaucoup". Ce n'est pas "beaucoup plus rapide". Vous allez vous raser à propos d'une nanoseconde. Peut-être. Après avoir itérité à environ un million de fois
@Reverender assez juste, il semble en fait négligeable après tout ... Intérieur: Ideone.com/ddho1l7z , Extérieur: ideone.com/xxupikh4
(Pseudocode de Wallacoloo empruntant)
output = "" for each player in players: if output != "" output += ", " output += player's name
Tout comme le code de Wallacoloo, le vôtre serait beaucoup plus rapide si vous regardez le premier joueur en dehors de la boucle, de cette façon, vous ne frappez pas la déclaration IF pour chaque autre joueur ...
Sérieusement, "beaucoup plus rapide"? Combien? Plus ou moins de 25%?
Oui, mais: vous seriez dupliquer du code similaire à l'extérieur et à l'intérieur de la boucle (Imaginez que vous ayez dû rechercher ou formater le nom du joueur) et: la comparaison contre NULL est généralement très optimisable.
Cela ne fait pas de la même chose que la question indique dans le titre. Vous avez supposé qu'après les 10 premiers éléments, lorsque info.cpear () code> a été appelé, que l'élément suivant ne devrait pas avoir une virgule devant elle.
@Steve Jessop- droite, il détecte en fait la première itération. Pour le premier, il ajoute simplement le nom, pour le reste, il ajoute un , code>, puis le nom.
J'ai écrit un exemple de code il y a quelque temps pour démontrer quelques façons différentes de le faire en C: p>
http://www.taenarum.com/csua/fun -with-c / délimiter.c p>
Malheureusement, il n'y a pas de méthode qui est clairement supérieure aux autres. Personnellement, j'irais avec une approche conventionnelle (vérifiez explicitement le premier ou le dernier élément) pour plus de clarté et pour éviter la duplication du code. (Et évitez certainement d'utiliser la version code> goto code> en code C ++.) P>
Si tel était mon code, je vérifierais probablement la chaîne au début de la boucle et ajouter la virgule quand ce n'est pas vide. Il est agréable de savoir comment gérer des situations similaires lorsque cette solution de contournement n'est pas disponible, alors voici un alternatif:
while (iter != Player::listPlayer.list.end()) { info += (*iter).second->getName(); ++iter; if (iter != Player::listPlayer.list.end()) info += ", "; ++count; ... }
Vous pouvez utiliser une jointure de chaîne à partir de .NET ou boost ou une autre bibliothèque ou écrivez votre propre. Bien que cela puisse être surchargé pour cette fonction particulière, c'est le genre de chose que vous utiliserez probablement ailleurs dans ce projet et que vous réutilisez certainement dans un autre projet. P>
Au lieu de trouver la dernière itération, trouvez la première itération. Poignez des cas spéciaux au début de la boucle, ont un état «propre» défini avant de faire le «vrai travail» et effectuez l'incrément à la fin.
while (iter != Player::listPlayer.list.end()) { if ( count != 0 ) { info += ", "; if (count % 10 == 0) { player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.c_str()); info.clear(); } } // invariant: info is clean and ready to accept data info += (*iter).second->getName(); ++iter; ++count; }
Ma solution implique une variable qui commence comme la chaîne vide et est définie sur "", " code> après chaque itération (qui n'a qu'un effet après la première itération). Aucun cas particulier n'a besoin d'être vérifié.
template<class ForwardIterator>
std::string sequence_to_string(ForwardIterator begin, ForwardIterator end)
{
std::string output;
const char* delimiter = "";
for (ForwardIterator it = begin; it != end; ++it)
{
output += delimiter;
output += *it;
delimiter = ", ";
}
return output;
}
... std::string info; ... while (iter != Player::listPlayer.list.end()) { if(info.size() > 0) info += ","; info += (*iter).second->getName(); ...... }
Pour reconnaître la dernière itération, vérifiez la boucle de l'état de la boucle.