Angenommen, ich habe einen Code wie diesen:
void printHex(std::ostream& x){
x<<std::hex<<123;
}
..
int main(){
std::cout<<100; // prints 100 base 10
printHex(std::cout); //prints 123 in hex
std::cout<<73; //problem! prints 73 in hex..
}
Meine Frage ist, ob es eine Möglichkeit gibt cout
, den ursprünglichen Zustand nach der Rückkehr von der Funktion wiederherzustellen . (Etwas wie std::boolalpha
und std::noboolalpha
..)?
Vielen Dank.
Antworten:
Sie müssen
#include <iostream>
oder#include <ios>
dann, wenn erforderlich:Sie können diese an den Anfang und das Ende Ihrer Funktion setzen oder diese Antwort zur Verwendung mit RAII lesen .
quelle
Der Boost IO Stream State Saver scheint genau das zu sein, was Sie brauchen. :-)
Beispiel basierend auf Ihrem Code-Snippet:
quelle
ios_flags_saver
Grunde nur die Flags speichert und setzt, wie in der Antwort von @ StefanKendall.ios_flags_saver
nur eine ist.Beachten Sie, dass die hier dargestellten Antworten nicht den vollständigen Status von wiederherstellen
std::cout
. Zum Beispielstd::setfill
bleibt auch nach dem Anruf "hängen".flags()
. Eine bessere Lösung ist zu verwenden.copyfmt
:Wird drucken:
eher, als:
quelle
std::ios
es immer in einem schlechten Zustand ist, weil esNULL
rdbuf hat. Das Festlegen eines Status mit aktivierten Ausnahmen führt daher zum Auslösen von Ausnahmen aufgrund eines schlechten Status. Lösungen: 1) Verwenden Sie eine Klasse (zum Beispielstd::stringstream
) mitrdbuf
set anstelle vonstd::ios
. 2) Speichern Sie den Ausnahmestatus separat in der lokalen Variablen und deaktivieren Sie sie zuvor. Stellen Siestate.copyfmt
dann die Ausnahme von der Variablen wieder her (und wiederholen Sie dies, nachdem Sie den Status wiederhergestelltoldState
haben, für den Ausnahmen deaktiviert sind). 3)rdbuf
std::ios
struct : std::streambuf {} sbuf; std::ios oldState(&sbuf);
Ich habe eine RAII-Klasse mit dem Beispielcode aus dieser Antwort erstellt. Der große Vorteil dieser Technik besteht darin, dass Sie mehrere Rückgabepfade von einer Funktion haben, die Flags in einem Iostream setzt. Unabhängig davon, welcher Rückweg verwendet wird, wird der Destruktor immer aufgerufen und die Flags werden immer zurückgesetzt. Es besteht keine Chance zu vergessen, die Flags wiederherzustellen, wenn die Funktion zurückkehrt.
Sie würden es dann verwenden, indem Sie eine lokale Instanz von IosFlagSaver erstellen, wann immer Sie den aktuellen Flag-Status speichern möchten. Wenn diese Instanz den Gültigkeitsbereich verlässt, wird der Flag-Status wiederhergestellt.
quelle
Mit ein wenig Modifikation, um die Ausgabe besser lesbar zu machen:
quelle
Sie können einen weiteren Wrapper um den Standardpuffer erstellen:
In einer Funktion:
Wenn die Leistung ein Problem darstellt, ist dies natürlich etwas teurer, da das gesamte
ios
Objekt (aber nicht der Puffer) kopiert wird, einschließlich einiger Dinge, für die Sie bezahlen, die Sie jedoch wahrscheinlich nicht verwenden werden, wie z. B. das Gebietsschema.Ansonsten denke ich, wenn Sie es verwenden wollen, ist
.flags()
es besser, konsistent zu sein und es auch zu verwenden,.setf()
als die<<
Syntax (reine Frage des Stils).Wie andere gesagt haben, können Sie die oben genannten (und
.precision()
und.fill()
, aber normalerweise nicht das Gebietsschema und wortbezogene Dinge, die normalerweise nicht geändert werden und schwerer sind) in eine Klasse einordnen, um sie zu vereinfachen und ausnahmsicher zu machen. Der Konstruktor sollte akzeptierenstd::ios&
.quelle
std::stringstream
für den Formatierungsteil zu verwenden, wie Mark Sherred betonte .std::stringstream
ist einstd:ostream
, außer wenn man eins verwendet, wird ein zusätzlicher Zwischenpuffer eingeführt.std:stringstream
Wille sein eigenes unabhängigesstd:stringbuf
(einstd::streambuf
Derivat) schafft , das dann instd::cout.rdbuf()
Ich möchte die Antwort von qbert220 etwas verallgemeinern:
Dies sollte auch für Eingabestreams und andere funktionieren.
PS: Ich hätte dies gerne einfach als Kommentar zur obigen Antwort gemacht. Der Stackoverflow erlaubt mir dies jedoch nicht, da der Ruf fehlt. Lassen Sie mich daher die Antworten hier anstelle eines einfachen Kommentars durcheinander bringen ...
quelle