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 couta su estado original después de regresar de la función. (Algo así como std::boolalphay 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_saverbásicamente solo guarda y establece las banderas como en la respuesta de @ StefanKendall.ios_flags_saveres solo una.Tenga en cuenta que las respuestas presentadas aquí no restaurarán el estado completo de
std::cout. Por ejemplo,std::setfillse "pegará" incluso después de llamar.flags(). Una mejor solución es usar.copyfmt:Imprimirá:
más bien que:
fuente
std::iossiempre está en mal estado porque tieneNULLrdbuf. 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) conrdbufset 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 eloldStatecual tiene las excepciones deshabilitadas). 3) Conjuntordbufparastd::iosde 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
iosobjeto (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::stringstreampara la parte de formato, como señaló Mark Sherred .std::stringstreames unstd:ostream, excepto que el uso de uno introduce un búfer intermedio adicional.std:stringstreamcreará su propio independientestd:stringbuf(unstd::streambufderivado), 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