5.9. Manipuladores

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).

5.9.1. Manipuladores con argumentos

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