J'ai récemment eu un problème pour créer un en stringstream
raison du fait que j'ai supposé à tort que std::setw()
cela affecterait le flux de chaînes pour chaque insertion, jusqu'à ce que je le modifie explicitement. Cependant, il est toujours désactivé après l'insertion.
// With timestruct with value of 'Oct 7 9:04 AM'
std::stringstream ss;
ss.fill('0'); ss.setf(ios::right, ios::adjustfield);
ss << setw(2) << timestruct.tm_mday;
ss << timestruct.tm_hour;
ss << timestruct.tm_min;
std::string filingTime = ss.str(); // BAD: '0794'
Donc, j'ai un certain nombre de questions:
- Pourquoi est-
setw()
ce ainsi? - Y a-t-il d'autres manipulateurs de cette façon?
- Y a-t-il une différence de comportement entre
std::ios_base::width()
etstd::setw()
? - Enfin, existe-t-il une référence en ligne qui documente clairement ce comportement? La documentation de mon fournisseur (MS Visual Studio 2005) ne semble pas le montrer clairement.
Réponses:
Notes importantes tirées des commentaires ci-dessous:
Par Martin:
Par Charles:
Voici la discussion qui mène à la conclusion ci-dessus:
En regardant le code, les manipulateurs suivants renvoient un objet plutôt qu'un flux:
Il s'agit d'une technique courante pour appliquer une opération uniquement à l'objet suivant appliqué au flux. Malheureusement, cela ne les empêche pas d'être collants. Les tests indiquent que tous sauf
setw
sont collants.Tous les autres manipulateurs renvoient un objet stream. Ainsi, toute information d'état qu'ils changent doit être enregistrée dans l'objet de flux et est donc permanente (jusqu'à ce qu'un autre manipulateur change l'état). Ainsi, les manipulateurs suivants doivent être des manipulateurs collants .
Ces manipulateurs effectuent en fait une opération sur le flux lui-même plutôt que sur l'objet de flux (bien que techniquement, le flux fasse partie de l'état des objets de flux). Mais je ne pense pas qu'ils affectent une autre partie de l'état des objets de flux.
La conclusion est que setw semble être le seul manipulateur de ma version à ne pas coller.
Pour Charles, une astuce simple pour n'affecter que l'élément suivant de la chaîne:
Voici un exemple comment un objet peut être utilisé pour changer temporairement l'état puis le remettre en utilisant un objet:
la source
operator<<
pour le manipulateur garantit que l'état du flux est modifié d'une certaine manière. Aucune des deux formes ne met en place une sorte de sentinelle d'État. Seul le comportement de la prochaine opération d'insertion formatée détermine quelle partie de l'état est réinitialisée, le cas échéant.setw
semble se comporter différemment est qu'il existe des exigences sur les opérations de sortie formatées pour explicitement.width(0)
le flux de sortie.La raison qui
width
ne semble pas être «collante» est que certaines opérations sont assurées d'appeler.width(0)
un flux de sortie. Ce sont:21.3.7.9 [lib.string.io]:
22.2.2.2.2 [lib.facet.num.put.virtuals]: Toutes les
do_put
surcharges pour lenum_put
modèle. Ceux-ci sont utilisés par les surcharges deoperator<<
prise d'unbasic_ostream
et d'un type numérique intégré.22.2.6.2.2 [lib.locale.money.put.virtuals]: Toutes les
do_put
surcharges pour lemoney_put
modèle.27.6.2.5.4 [lib.ostream.inserters.character]: surcharges de
operator<<
prise de abasic_ostream
et un du type char de l'instanciation basic_ostream ouchar
, signéchar
ouunsigned char
ou pointeurs vers des tableaux de ces types char.Pour être honnête, je ne suis pas sûr de la justification de cela, mais aucun autre état d'un
ostream
ne doit être réinitialisé par des fonctions de sortie formatées. Bien sûr, des éléments tels quebadbit
etfailbit
peuvent être définis en cas d'échec de l'opération de sortie, mais cela devrait être prévisible.La seule raison à laquelle je peux penser pour réinitialiser la largeur est qu'il pourrait être surprenant que, lorsque vous essayez de générer des champs délimités, vos délimiteurs aient été remplis.
Par exemple
Pour `` corriger '' cela, il faudrait:
alors qu'avec une largeur de réinitialisation, la sortie souhaitée peut être générée avec le plus court:
la source
setw()
n'affecte que la prochaine insertion. C'est juste la façon dontsetw()
se comporte. Le comportement desetw()
est le même queios_base::width()
. J'ai obtenu messetw()
informations de cplusplus.com .Vous pouvez trouver une liste complète des manipulateurs ici . À partir de ce lien, tous les indicateurs de flux devraient indiquer ensemble jusqu'à ce qu'ils soient modifiés par un autre manipulateur. Une note sur le
left
,right
etinternal
Manipulateurs: Ils sont comme les autres drapeaux et ne persistent jusqu'à la prochaine modification. Cependant, ils n'ont d'effet que lorsque la largeur du flux est définie et la largeur doit être définie à chaque ligne. Donc, par exemplete donnerait
mais
te donnerait
Les manipulateurs d'entrée et de sortie ne sont pas collants et n'apparaissent qu'une seule fois là où ils sont utilisés. Les manipulateurs paramétrés sont chacun différents, voici une brève description de chacun:
setiosflags
vous permet de définir manuellement des indicateurs, dont une liste peut être affichée ici , donc elle est collante.resetiosflags
se comporte de la même manière quesetiosflags
sauf qu'il annule les indicateurs spécifiés.setbase
définit la base des nombres entiers insérés dans le flux (donc 17 en base 16 serait "11", et en base 2 serait "10001").setfill
définit le caractère de remplissage à insérer dans le flux lorsqu'ilsetw
est utilisé.setprecision
définit la précision décimale à utiliser lors de l'insertion de valeurs à virgule flottante.setw
fait seulement la prochaine insertion de la largeur spécifiée en remplissant avec le caractère spécifié danssetfill
la source
std::hex
plus n'est pas collant et, évidemment,std::flush
oustd::setiosflags
n'est pas collant non plus. Donc je ne pense pas que ce soit aussi simple.std::hex
ne pas être collante était fausse - je viens de le découvrir aussi. Les indicateurs de flux, cependant, peuvent changer même si vous n'insérez pas destd::setiosflags
nouveau, donc on pourrait voir cela comme non collant. En outre,std::ws
n'est pas collant non plus. Ce n’est donc pas si simple.