C++ declara y define cuatro objetos predefinidos, uno de la clase istream, y tres más de la clase ostream_withassign estos objetos están disponibles para cualquier programa C++:
Se trata de un objeto global definido en "iostream.h".
A lo largo de todo el curso hemos usado el objeto cout sin preocuparnos mucho de lo qué se trataba en realidad, ahora veremos más profundamente este objeto.
Ya conocemos el operador <<, lo hemos usado a menudo para mostrar cadenas de caracteres y variables.
ostream &operator<<(int)
El operador está sobrecargado para todos los tipos estándar: char, char *, void *, int, long, short, bool, double y float.
Además, el operador << devuelve una referencia objeto ostream, de modo que puede asociarse. Estas asociaciones se evalúan de izquierda a derecha, y permiten expresiones como:
cout << "Texto: " << variable << "\n";
cout << variable;
C++ reconoce el tipo de la variable y muestra la salida de la forma adecuada, siempre como una cadena de caracteres.
Por ejemplo:
int entero = 10; char caracter = 'c'; char cadena[] = "Hola"; float pi = 3.1416; void *puntero = cadena; cout << "entero=" << entero << endl; cout << "caracter=" << caracter << endl; cout << "cadena=" << cadena << endl; cout << "pi=" << pi << endl; cout << "puntero=" << puntero << endl;
La salida tendrá este aspecto:
entero=10 caracter=c cadena=Hola pi=3.1416 puntero=0x254fdb8
Hay que tener en cuenta que cout es un objeto de la clase "ostream", que a su vez está derivada de la clase "ios", así que heredará todas las funciones y operadores de ambas clases. Se mostrarán todas esas funciones con más detalle en la documentación de las librerías, pero veremos ahora las que se usan más frecuentemente.
El formato de las salidas de cout se puede modificar mediante flags. Estos flags pueden leerse o modificarse mediante las funciones flags, setf y unsetf.
Otro medio es usar manipuladores, que son funciones especiales que sirven para cambiar la apariencia de una operación de salida o entrada de un stream. Su efecto sólo es válido para una operación de entrada o salida. Además devuelven una referencia al stream, con lo que pueden ser insertados en una cadena entradas o salidas.
Por el contrario, modificar los flags tiene un efecto permanente, el formato de salida se modifica hasta que se restaure o se modifique el estado del flag.
Para usar estos manipuladores es necesario incluir el fichero de cabecera iomanip.
Existen seis de estas funciones manipuladoras: setw, setbase, setfill, setprecision, setiosflags y resetiosflags.
Todas trabajan del mismo modo, y afectan sólo a la siguiente entrada o salida.
Permite cambiar la anchura en caracteres de la siguiente salida de cout. Por ejemplo:
#include <iostream> #include <iomanip> using namespace std; int main() { int x = 123, y = 432; cout << "#" << setw(6) << x << "#" << setw(12) << y << "#" << endl; return 0; }
La salida tendrá este aspecto:
# 123# 432#
Permite cambiar la base de numeración que se usará para la salida. Sólo se admiten tres valores: 8, 10 y 16, es decir, octal, decimal y hexadecimal. Por ejemplo:
#include <iostream> #include <iomanip> using namespace std; int main() { int x = 123; cout << "#" << setbase(8) << x << "#" << setbase(10) << x << "#" << setbase(16) << x << "#" << endl; return 0; }
La salida tendrá este aspecto:
#173#123#7b#
Permite especificar el carácter de relleno cuando la anchura especificada sea mayor de la necesaria para mostrar la salida. Por ejemplo:
#include <iostream> #include <iomanip> using namespace std; int main() { int x = 123; cout << "#" << setw(8) << setfill('0') << x << "#" << endl; cout << "#" << setw(8) << setfill('%') << x << "#" << endl; return 0; }
La salida tendrá este aspecto:
#00000123# #%%%%%123#
Permite especificar el número de dígitos significativos que se muestran cuando se imprimen números en punto flotante: float o double. Por ejemplo:
#include <iostream> #include <iomanip> using namespace std; int main() { float x = 121.0/3; cout << "#" << setprecision(3) << x << "#" << endl; cout << "#" << setprecision(1) << x << "#" << endl; return 0; }
La salida tendrá este aspecto:
#40.3# #4e+01#
Permiten activar o desactivar, respectivamente, los flags de formato de salida. Existen quince flags de formato a los que se puede acceder mediante un enum definido en la clase ios:
flag |
Acción |
skipws | ignora espacios en operaciones de lectura |
left | ajusta la salida a la izquierda |
right | ajusta la salida a la derecha |
internal | deja hueco después del signo o el indicador de base |
dec | conversión a decimal |
oct | conversión a octal |
hex | conversión a hexadecimal |
showbase | muestra el indicador de base en la salida |
showpoint | muestra el punto decimal en salidas en punto flotante |
uppercase | muestra las salidas hexadecimales en mayúsculas |
showpos | muestra el signo '+' en enteros positivos |
scientific | muestra los números en punto flotante en notación exponencial |
fixed | usa el punto decimal fijo para números en punto flotante |
unitbuf | vacía todos los buffers después de una inserción |
stdio | vacía los buffers stdout y stderr después de una inserción |
Veamos un ejemplo:
#include <iostream> #include <iomanip> using namespace std; int main() { float x = 121.0/3; int y = 123; cout << "#" << setiosflags(ios::left) << setw(12) << setprecision(4) << x << "#" << endl; cout << "#" << resetiosflags(ios::left | ios::dec) << setiosflags(ios::hex | ios::showbase | ios::right) << setw(8) << y << "#" << endl; return 0; }
La salida tendrá este aspecto:
#40.33 # # 0x7b#
Existe otro tipo de manipuladores que no requieren parámetros, y que ofrecen prácticamente la misma funcionalidad que los anteriores. La diferencia es que los cambios son permanentes, es decir, no sólo afectan a la siguiente salida, sino a todas las salidas hasta que se vuelva a modificar el formato afectado.
inline ios& dec(ios& i) inline ios& hex(ios& i) inline ios& oct(ios& i)
Permite cambiar la base de numeración de las salidas de enteros, supongo que resulta evidente, pero de todos modos lo diré.
Función |
Acción |
dec | Cambia la base de numeración a decimal |
hex | Cambia la base de numeración a hexadecimal |
oct | Cambia la base de numeración a octal |
El cambio persiste hasta un nuevo cambio de base. Ejemplo:
#include <iostream> using namespace std; int main() { int a = 123, c = 432, b = 543; cout << "Decimal: " << dec << a << ", " << b << ", " << c << endl; cout << "Hexadecimal: " << hex << a << ", " << b << ", " << c << endl; cout << "Octal: " << oct << a << ", " << b << ", " << c << endl; ucin.get(); return 0; }
La salida tendrá éste aspecto:
Decimal: 123, 543, 432 Hexadecimal: 7b, 21f, 1b0 Octal: 173, 1037, 660
La función ws sólo es para streams de entrada.
La función ends no tiene sentido en cout, ya que sirve para añadir el carácter nulo de fin de cadena.
ostream& flush(ostream& outs);
Vacía el buffer de salida. Puede ser invocada de dos modos:
cout.flush(); cout << flush;
ostream& endl(ostream& outs);
Vacía el buffer de salida y además cambia de línea. Puede ser invocada de dos modos:
cout.endl(); cout << endl;
Cambia la anchura en caracteres de la siguiente salida de stream:
int width(); int width(int);
La primera forma devuelve el valor de la anchura actual, la segunda permite cambiar la anchura para la siguiente salida, y también devuelve el valor actual de la anchura.
int x = 23; cout << "#"; cout.width(10); cout << x << "#" << x << "#" << endl;
Cambia el carácter de relleno que se usa cuando la salida es más ancha de la necesaria para el dato actual:
int fill(); int fill(char);
La primera forma devuelve el valor actual del carácter de relleno, la segunda permite cambiar el carácter de relleno para la siguiente salida, y también devuelve el valor actual.
int x = 23; cout << "|"; cout.width(10); cout.fill('%'); cout << x << "|" << x << "|" << endl;
Permite cambiar el número de caracteres significativos que se mostrarán cuando trabajemos con números en coma flotante: float o double:
int precision(); int precision(char);
La primera forma devuelve el valor actual de la precisión, la segunda permite modificar la precisión para la siguiente salida, y también devuelve el valor actual.
float x = 23.45684875; cout << "|"; cout.precision(6); cout << x << "|" << x << "|" << endl;
Permite modificar los flags de manipulación de formato:
long setf(long); long setf(long valor, long mascara);
La primera forma activa los flags que estén activos en el parámetro valor y deja sin cambios el resto.
La segunda forma activa los flags que estén activos tanto en valor como en mascara y desactiva los que estén activos en mascara, pero no en valor. Podemos considerar que mascara contiene activos los flags que queremos modificar y valor los flags que queremos activar.
Ambos devuelven el valor previo de los flags.
int x = 235; cout << "|"; cout.setf(ios::left, ios::left | ios::right | ios::internal); cout.width(10); cout << x << "|" << endl;
Permite eliminar flags de manipulación de formato:
void unsetf(long mascara);
Desactiva los flags que estén activos en el parámetro.
Nota: en algunos compiladores he comprobado que esta función tiene como valor de retorno el valor previo de los flags.
int x = 235; cout << "|"; cout.unsetf(ios::left | ios::right | ios::internal); cout.setf(ios::left); cout.width(10); cout << x << "|" << endl;
Permite cambiar o leer los flags de manipulación de formato:
long flags () const;
long flags (long valor);
La primera forma devuelve el valor actual de los flags.
La segunda cambia el valor actual por valor, el valor de retorno es el valor previo de los flags.
int x = 235; long f; cout << "|"; f = flags(); f &= !(ios::left | ios::right | ios::internal); f |= ios::left; cout.flags(f); cout.width(10); cout << x << "|" << endl;
Imprime un carácter:
ostream& put(char);
Ejemplo:
char l = 'l'; unsigned char a = 'a'; cout.put('H').put('o').put(l).put(a) << endl;
Imprime varios caracteres:
ostream& write(char* cad, int n);
Imprime n caracteres desde el principio de la cadena cad. Ejemplo:
char cadena[] = "Cadena de prueba"; cout.write(cadena, 12) << endl;
Imprime expresiones con formato, es análogo al printf de "stdio":
ostream& form(char* format, ...);
Nota: algunos compiladores no disponen de esta función.
Ejemplo:
char l = 'l'; int i = 125; float f = 125.241; char cad[] = "Hola"; cout.form("char: %c, int: %d, float %.2f, char*: %s", l, i, f, cad);
© Noviembre de 2001 Salvador Pozo, salvador@conclase.net