5.8. Formateo de stream de salida

El objetivo del diseño de los iostream es permitir que usted pueda mover y/o formatear carácteres fácilmente. Ciertamente no podria ser de mucha utilidad si no se pudiera hacer la mayoria de los formateos provistos por la familia de funciones de printf() en C. Es esta sección, usted aprenderá todo sobre las funciones de formateo de salida que estan disponibles para iostream, con lo que puede formatear los bytes de la manera que usted quiera.

Las funciones de formateo en iostream pueden ser algo cunfusas al principio porque a menudo existe más de una manera de controlar el formateo: a través de funciones miembro y manipuladores. Para confundir más las cosas, una función miembro genérica pone banderas de estado para controlar el formateo, como la justificación a la derecha o izquierda, el uso de letras mayúsculas para la notación hexadecimal, para siempre usar un punto decimal para valores de coma flotante, y cosas así. En el otro lado, funciones miembro separadas activan y leen valores para el caracter de relleno, la anchura del campo, y la precisión.

En un intento de clarificar todo esto, primero examinaremos el formateo interno de los datos de un iostream, y las funciones miembro que pueden modificar estos datos. (Todo puede ser controlado por funciones miembro si se desea). Cubriremos los manipuladores aparte.

5.8.1. Banderas de formateo

La clase ios contiene los miembros de datos para guardar toda la información de formateo perteneciente a un stream. Algunos de estos datos tiene un rango de valores de datos y son guardados en variables: la precisión de la coma flotante, la anchura del campo de salida, y el carácter usado para rellenar la salida (normalmente un espacio). El resto del formateo es determinado por banderas, que generalmente están combinadas para ahorrar espacio y se llaman colectivamente banderas de formateo. Puede recuperar los valores de las banderas de formateo con la función miembro ios::flag(), que no toma argumentos y retorna un objeto de tipo fmtflags (usualmente un sinónimo de long) que contiene las banderas de formateo actuales. El resto de funciones hacen cambios en las banderas de formateo y retornan el valor previo de las banderas de formateo.

fmtflags ios::flags(fmtflags newflags);
  fmtflags ios::setf(fmtflags ored_flag);
  fmtflags ios::unsetf(fmtflags clear_flag);
  fmtflags ios::setf(fmtflags bits, fmtflags field);

La primera función fuerza que todas las banderas cambien, que a veces es lo que usted quiere. Más a menudo, usted cambia una bandera cada vez usando las otras tres funciones.

El uso de setf() puede parecer algo confusa. Para conocer qué versión sobrecargada usar, debe conocer el tipo de la bandera que está cambiando. Existen dos tipos de banderas: las que simplemente estan activadas o no, y aquellas que trabajan en grupo con otras banderas. La banderas que estan encendidas/apagadas son las más simples de entender por que usted las enciende con setf(fmtflags) y las apaga con unsetf(fmtflags). Estas banderas se muestran en la siguiente tabla:

bandera activa/inactiva

Efecto

ios::skipws

Se salta los espacios en blanco. ( Para la entrada esto es por defecto).

ios::showbase

Indica la base numérica (que puede ser, por ejemplo, decimal, octal o hexadecimal) cuando imprimimos el valor entero. Los stream de entrada tambié reconocen el prefijo de base cuando showbase está activo.

ios::showpoint

Muestra el punto decimal insertando ceros para valores de coma flotante.

ios::uppercase

Muestra A-F mayúsculas para valores hexadecimales y E para científicos.

ios::showpos

Muestra el signo de sumar (+) para los valores positivos

ios::unitbuf

'Unit buffering.' El stream es borrado después de cada inseción.

Por ejemplo, para mostrar el signo de sumar para cout, puede usar cout.setf(ios::showpos). Para dejar de mostrar el signo de sumar, escriba cout.unsetf(ios::showpos).

La bandera de unitbuf controla el almacenamiento unitario, que significa que cada inserción es lanzada a su stream de salida inmediatamente. Esto es útil para hacer recuento de errores, ya que en caso de fallo del programa, sus datos son todavía escritos al fichero de log. El siguiente programa ilustra el almacenamiento unitario.

//: C04:Unitbuf.cpp {RunByHand}
#include <cstdlib>  // For abort()
#include <fstream>
using namespace std;

int main() {
  ofstream out("log.txt");
  out.setf(ios::unitbuf);
  out << "one" << endl;
  out << "two" << endl;
  abort();
} ///:~

Listado 5.15. C04/Unitbuf.cpp


Es necesario activar el almacenamiento unitario antes de que cualquier inserción sea hecha en el stream. Cuando hemos descomentado la llamada a setf(), un compilador en particular ha escrito solo la letra 'o' en el fichero log.txt. Con el almacenamiento unitario, ningun dato se perdió.

El stream de salida estándar cerr tiene el almacenamiento unitario activado por defecto. Hay un coste para el almacenamiento unitario, asi que si un stream de salida se usa intensivamente, no active el almacenamiento unitario a menos que la eficiencia no sea una consideración.