Supongamos que tengo un código como este:
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..
}
Mi pregunta es si hay alguna forma de 'restaurar' el estado cout
a su estado original después de regresar de la función. (Algo así como std::boolalpha
y std::noboolalpha
..)?
Gracias.
Respuestas:
necesita
#include <iostream>
o#include <ios>
luego cuando sea necesario:Puede colocarlos al principio y al final de su función, o consulte esta respuesta sobre cómo usar esto con RAII .
fuente
El Boost IO estado de la secuencia de ahorro parece exactamente lo que necesita. :-)
Ejemplo basado en su fragmento de código:
fuente
ios_flags_saver
básicamente solo guarda y establece las banderas como en la respuesta de @ StefanKendall.ios_flags_saver
es solo una.Tenga en cuenta que las respuestas presentadas aquí no restaurarán el estado completo de
std::cout
. Por ejemplo,std::setfill
se "pegará" incluso después de llamar.flags()
. Una mejor solución es usar.copyfmt
:Imprimirá:
más bien que:
fuente
std::ios
siempre está en mal estado porque tieneNULL
rdbuf. Por lo tanto, establecer un estado con excepciones habilitadas provoca el lanzamiento de excepciones debido a un mal estado. Soluciones: 1) Use alguna clase (por ejemplostd::stringstream
) conrdbuf
set en lugar destd::ios
. 2) Guarde el estado de las excepciones por separado en la variable local y deshabilítelas antesstate.copyfmt
, luego restaure la excepción de la variable (y haga esto nuevamente después de restaurar el estado desde eloldState
cual tiene las excepciones deshabilitadas). 3) Conjuntordbuf
parastd::ios
de esta manera:struct : std::streambuf {} sbuf; std::ios oldState(&sbuf);
Creé una clase RAII usando el código de ejemplo de esta respuesta. La gran ventaja de esta técnica viene si tiene múltiples rutas de retorno de una función que establece banderas en un iostream. Cualquiera que sea la ruta de retorno que se use, siempre se llamará al destructor y las banderas siempre se restablecerán. No hay posibilidad de olvidar restaurar las banderas cuando la función regrese.
Luego lo usaría creando una instancia local de IosFlagSaver siempre que quisiera guardar el estado actual de la bandera. Cuando esta instancia salga del alcance, se restaurará el estado de la bandera.
fuente
Con un poco de modificación para que la salida sea más legible:
fuente
Puede crear otra envoltura alrededor del búfer stdout:
En una función:
Por supuesto, si el rendimiento es un problema, esto es un poco más caro porque copia todo el
ios
objeto (pero no el búfer), incluidas algunas cosas por las que está pagando pero que es poco probable que use, como la configuración regional.De lo contrario, siento que si vas a usar
.flags()
es mejor ser coherente y usar.setf()
también en lugar de la<<
sintaxis (pura cuestión de estilo).Como han dicho otros, puede poner lo anterior (y
.precision()
y.fill()
, pero normalmente no las cosas relacionadas con la configuración regional y las palabras que generalmente no se van a modificar y son más pesadas) en una clase por conveniencia y para que sea seguro para excepciones; el constructor debería aceptarstd::ios&
.fuente
std::stringstream
para la parte de formato, como señaló Mark Sherred .std::stringstream
es unstd:ostream
, excepto que el uso de uno introduce un búfer intermedio adicional.std:stringstream
creará su propio independientestd:stringbuf
(unstd::streambuf
derivado), que luego debe verterse enstd::cout.rdbuf()
Me gustaría generalizar un poco la respuesta de qbert220:
Esto debería funcionar para flujos de entrada y otros también.
PD: Me hubiera gustado hacer esto simplemente un comentario a la respuesta anterior, sin embargo, stackoverflow no me permite hacerlo debido a la falta de reputación. Por lo tanto, hazme desordenar las respuestas aquí en lugar de un simple comentario ...
fuente