2010-02-25 18 views
12

je suis tombé sur un bug subtil, il y a quelques jours où le code ressemblait à ceci:À quoi servent les «fins» ces jours-ci?

ostringstream ss; 
int anInt(7); 

ss << anInt << "HABITS"; 
ss << ends; 
string theWholeLot = ss.str(); 

Le problème était que la ends collait un « \ 0 » dans le ostringstream si theWholeLot ressemblait réellement "7HABITS\0" (par exemple une valeur nulle à la fin)

maintenant, cela n'a pas démontré parce que theWholeLot a ensuite été utilisé pour prendre la partie en utilisant const char *string::c_str() cela signifiait que le nul était masqué comme il est devenu juste un delimiter. Toutefois, lorsque cela a changé d'utiliser des chaînes tout au long, l'hypothèse nulle signifie quelque chose et tout à coup des comparaisons telles que:

if (theWholeLot == "7HABITS") 

échouerait. Cela m'a fait penser: Vraisemblablement la raison pour ends est un retour aux jours de ostrstream quand le flux n'était normalement pas terminé avec un null et devait être ainsi que str() (qui a ensuite chassé pas un string mais un char *) fonctionnerait correctement .

Cependant, maintenant qu'il est impossible de jeter un char * d'un ostringstream, en utilisant ends est non seulement superflue, mais potentiellement dangereux et je considère les enlever tout de mon code clients.

Quelqu'un peut-il voir une raison évidente d'utiliser ends dans un environnement std::string seulement?

+0

Mon seul problème serait quel est l'environnement std :: string? Tout programme non trivial va aux arguments char * system call, etc. Cela dit, il y a une demi-douzaine d'autres façons de traiter cela et la fin a une utilité négligeable. – Duck

+0

Voici une utilisation de 'std :: ends': http://stackoverflow.com/questions/624260/how-to-reuse-an-ostringstream/624291#624291 –

+1

Ce n'est pas seulement pour les chaînes. C'est utile pour les flux généraux. Certains outils Unix ont besoin d'octets NULL comme terminateurs. 'cout << se termine;' les fournira. –

Répondre

7

Vous avez essentiellement répondu à votre propre question, c'est autant de détails que nécessaire. Je ne peux certainement pas penser à aucune raison d'utiliser std::ends lorsque std::string et std::stringstream gérer tout cela pour vous. Donc, pour répondre explicitement à votre question, non, il n'y a pas de raison d'utiliser std::ends dans un environnement std::string seulement.

+0

Je dirais qu'il n'y a aucune raison d'utiliser la période 'std :: ends'. Je dirais que je suis un programmeur C++ très expérimenté et pourtant je ne savais même pas qu'il existait. –

+3

@Andreas, pour en avoir entendu parler la première fois, vous avez l'air extraordinairement sûr à ce sujet :) –

+1

Comme l'a souligné Johannes, il y a des raisons suffisantes. De nombreux programmes UNIX requièrent le terminateur commun '\ 0', par ex. pour envoyer du texte avec des caractères ASCII <= 32 dans d'autres programmes. Je ne peux même pas imaginer une vie sans 'find -print0',' xargs --null' ou 'read -d '\ 0'', pour n'en nommer que quelques-uns. De nombreuses API nécessitent également '\ 0'. C'est le terminateur de chaîne commun, et les chaînes sont les éléments de données les plus importants, puisque tout peut être converti en chaîne. Par conséquent, vous voulez que les chaînes soient aussi flexibles que possible. –

6

Certaines API attendent un "tableau de chaînes" avec plusieurs chaînes à zéro, un double zéro pour marquer la fin. Raymond Chang récemment, blogged about it, surtout pour démontrer à quelle fréquence cela est foiré.

+0

Neat. Merci pour le lien. –