Como puede ver en el programa previo, llamar a funciones miembro para operaciones de formateo de stream
puede ser un poco tedioso. Para hacer las cosas mas fáciles de leer y escribir, existe un conjunto de manipuladores para duplicar
las acciones previstas por las funciones miembro. Las manipuladores son convenientes por que usted puede insertarlos para que actuen
dentro de una expresion contenedora; no necesita crear una sentencia de llamada a función separada.
Los manipuladores cambian el estado de un stream
en vez de (o además de) procesar los datos. Cuando
insertamos un endl
en una expresión de salida, por ejemplo, no solo inserta un carácter de nueva linea,
sino que ademas termina el stream
(esto es, saca todos los carácteres pendientes que han sido almacenadas
en el buffer interno del stream
pero todavia no en la salida). Puede terminar el stream
simplemente asi:
cout << flush;
Lo que causa una llamada a la función miembro flush()
, como esta:
cout.flush();
como efecto lateral (nada es insertado dentro de stream
). Adicionalmente los manipuladores
básicos cambirán la base del número a oct (octal), dec (decimal) o hex (hexadecimal).
cout << hex << "0x" << i << endl;
En este caso, la salida numérica continuará en modo hexadecimal hasta que usted lo cambie insertando o dec o oct en el
stream
de salida.
También existe un manipulador para la extracción que se 'come' los espacios en blanco:
cin >> ws;
Los manipuladores sin argumentos son provistos en <iostream>. Esto incluye dec, oct,y hex, que hacen las
mismas acciones que, respectivamente, setf(ios::dec, ios::basefield)
,
setf(ios::oct, ios::basefield)
, y setf(ios::hex, ios::basefield)
, aunque
más sucintamente. La cabecera <iostream> también incluye ws, endl, y flush y el conjunto adicional mostrado aquí:
Manipulador
Efecto
showbase noshowbase
Indica la base numérica (dec, oct, o hex) cuando imprimimos un entero.
showpos noshowpos
Muestra el signo más (+) para valores positivos.
uppercase nouppercase
Muestra mayúsculas A-F para valores hexadecimales, y muestra E para valores científicos.
showpoint noshowpoint
Muestra punto decimal y ceros arrastrados para valores de coma flotante.
skipws noskipws
Escapa los espacios en blanco en la entrada.
left right internal
Alineación izquierda, relleno a la derecha. Alineación derecha, relleno a la izquierda. Rellenar entre el signo o el indicador de base y el valor.
scientific fixed
Indica la preferencia al mostrar la salida para coma flotante (notación científica versus coma flotante decimal).
Existen seis manipuladores estándar, como setw()
, que toman argumentos. Están definidos en el fichero de cabecera <iomanip>, y están enumerados en la siguiente tabla:
Manipulador
Efecto
setiosflags(fmtflags n)
Equivalente a una llamada a setf(n)
. La activación continua hasta el siguiente cambio,
como ios::setf()
.
resetiosflags(fmtflags n)
Limpia solo las banderas de formato especificadas por n. La activación permanece hasta el siguiente
cambio, como ios::unsetf()
.
setbase(base n)
Cambia la base a n, donde n es 10, 8 o 16. (Caulquier otra opción resulta en 0). Si n es cero, la salida es base 10, pero la entrada usa convenciones de C: 10 es 10, 010 es 8, y 0xf es 15. Puede usar también dec, oct y hex para la salida.
setfill(char n)
Cambia el carácter de relleno a n, como ios::fill()
.
setprecision(int n)
Cambia la precision a n, como ios::precision()
.
setw(int n)
Cambia la anchura del campo a n, como en ios::width()
Si está usando mucho el formateo, usted puede ver como usar los manipuladores en vez de llamar a funciones miembro de stream puede limpiar su código. Como ejemplo, aquí tiene un programa de la sección previa reescrito para usar los manipuladores. (La macro D() ha sido borrada para hacerlo más fácil de leer).
//: C04:Manips.cpp // Format.cpp using manipulators. #include <fstream> #include <iomanip> #include <iostream> using namespace std; int main() { ofstream trc("trace.out"); int i = 47; float f = 2300114.414159; char* s = "Is there any more?"; trc << setiosflags(ios::unitbuf | ios::showbase | ios::uppercase | ios::showpos); trc << i << endl; trc << hex << i << endl << oct << i << endl; trc.setf(ios::left, ios::adjustfield); trc << resetiosflags(ios::showbase) << dec << setfill('0'); trc << "fill char: " << trc.fill() << endl; trc << setw(10) << i << endl; trc.setf(ios::right, ios::adjustfield); trc << setw(10) << i << endl; trc.setf(ios::internal, ios::adjustfield); trc << setw(10) << i << endl; trc << i << endl; // Without setw(10) trc << resetiosflags(ios::showpos) << setiosflags(ios::showpoint) << "prec = " << trc.precision() << endl; trc.setf(ios::scientific, ios::floatfield); trc << f << resetiosflags(ios::uppercase) << endl; trc.setf(ios::fixed, ios::floatfield); trc << f << endl; trc << f << endl; trc << setprecision(20); trc << "prec = " << trc.precision() << endl; trc << f << endl; trc.setf(ios::scientific, ios::floatfield); trc << f << endl; trc.setf(ios::fixed, ios::floatfield); trc << f << endl; trc << f << endl; trc << setw(10) << s << endl; trc << setw(40) << s << endl; trc.setf(ios::left, ios::adjustfield); trc << setw(40) << s << endl; } ///:~
Listado 5.17. C04/Manips.cpp
Puede ver que un montón de sentencias múltiples han sido condensadas dentro de una sola inserción encadenada. Nótese
que la llamada a setiosflags() en que se pasa el OR binario de las banderas. Esto se podría haber hecho también con
setf()
y unsetf()
como en el ejemplo previo.
//: C04:InputWidth.cpp // Shows limitations of setw with input. #include <cassert> #include <cmath> #include <iomanip> #include <limits> #include <sstream> #include <string> using namespace std; int main() { istringstream is("one 2.34 five"); string temp; is >> setw(2) >> temp; assert(temp == "on"); is >> setw(2) >> temp; assert(temp == "e"); double x; is >> setw(2) >> x; double relerr = fabs(x - 2.34) / x; assert(relerr <= numeric_limits<double>::epsilon()); } ///:~
Listado 5.18. C04/InputWidth.cpp