Apéndice E Streams

Las operaciones de entrada y salida nunca formaron parte de C ni tampoco lo forman de C++. En ambos lenguajes, todas las operaciones de entrada y salida se hacen mediante bibliotecas externas.

En el caso de C, esa biblioteca es stdio, que agrupa todas las funciones de entrada y salida desde teclado, pantalla y ficheros de disco. En el caso de C++ se dispone de varias clases: streambuf, ios, istream, ostream y fstream.

Dejar fuera del lenguaje todas las operaciones de entrada y salida tiene varias ventajas:

  1. Independencia de la plataforma: cada compilador dispone de diferentes versiones de cada biblioteca para cada plataforma. Tan sólo se cambia la definición de las clases y bibliotecas, pero la estructura, parámetros y valores de retorno son iguales. Los mismos programas, compilados para diferentes plataformas funcionan del mismo modo.
  2. Encapsulación: para el programa todos los dispositivos son de entrada y salida se tratan del mismo modo, es indiferente usar la pantalla, el teclado o ficheros.
  3. Buffering: el acceso a dispositivos físicos es lento, en comparación con el acceso a memoria. Las operaciones de lectura y escritura se agrupan, haciéndolas en memoria, y las operaciones físicas se hacen por grupos o bloques, lo cual ahorra mucho tiempo.

Clases predefinidas para streams

Un stream es una abstracción para referirse a cualquier flujo de datos entre una fuente y un destinatario. Los streams se encargan de convertir cualquier tipo de objeto a texto legible por el usuario, y viceversa. Pero no se limitan a eso, también pueden hacer manipulaciones binarias de los objetos y cambiar la apariencia y el formato en que se muestra la salida.

C++ declara varias clases estándar para el manejo de streams:

  • streambuf: manipulación de buffers.
  • ios: entradas y salidas, incluye en su definición un objeto de la clase streambuf.
  • istream: derivada de ios, clase especializada en entradas.
  • ostream: derivada de ios, clase especializada en salidas.
  • iostream: derivada de istream y ostream, se encarga de encapsular las funciones de entrada y salida por teclado y pantalla.
  • fstream: entrada y salida desde ficheros.

Las clases base son streambuf e ios, las demás se derivan de estas dos.

La clase streambuf proporciona un interfaz entre la memoria y los dispositivos físicos.

streambuf

streambuf

La clase ios contiene además un puntero a un objeto de la clase streambuf. Proporciona soporte para entradas y salidas con validación y formato usando un streambuf.

ios

ios

Veremos ahora algunas de las funciones que forman parte de las principales clases relacionadas con los streams.

No es necesario estudiar en profundidad estas clases, puede usarse este capítulo como consulta para el uso de streams. Con la práctica se aprende a usar las funciones necesarias en cada caso.

Clase streambuf

Es la clase base para todas las clases con buffer, proporciona el interfaz entre los datos y las áreas de almacenamiento como la memoria o los dispositivos físicos.

Si las aplicaciones necesitan acceder al buffer de un stream, lo hacen a través del puntero almacenado en la clase ios. Pero normalmente el acceso se hace a alto nivel, directamente desde funciones de ios y sus clases derivadas, y casi nunca directamente a través de streambuf.

Por eso veremos muy pocas funciones de la clase streambuf, ya que la mayoría tienen escasa utilidad en programación normal.

Por otra parte, he consultado bastante documentación al respecto de las estructuras de las clases, y varias implementaciones de distintos compiladores, y no parece existir gran unanimidad al respecto de las funciones que deben incluir ciertas clases. El caso de streambuf es de los más heterogéneos, de modo que sólo incluiré algunas de las funciones más frecuentes.

Funciones protegidas

Función allocate (no siempre disponible)

int allocate();

Prepara el área del buffer.

Función base (no siempre disponible)

char *base();

Devuelve la dirección de comienzo del área del buffer.

Función blen (no siempre disponible)

int blen();

Devuelve la longitud del área del buffer.

Función unbuffered (no siempre disponible)

void unbuffered(int);
int unbuffered();

La primera forma modifica el estado del buffer, la segunda devuelve un valor no nulo si no está activado el buffer.

Funciones públicas

Función in_avail

int in_avail();

Devuelve el número de caracteres que permanecen en el buffer de entrada interno disponibles para su lectura.

Función out_waiting

int out_waiting();

Devuelve el número de caracteres que permanecen en el buffer interno de salida.

Función seekoff

virtual streampos seekoff(streamoff offset,
   ios::seek_dir, int mode);

Cambia la posición relativa del puntero del fichero desde el punto definido por seek_dir, el valor de offset.

Para seek_dir se usan los valores definidos en el enum de la clase ios:

Valor Significado
ios::beg Desplazamiento desde el principio del fichero
ios::cur Desplazamiento desde la posición actual del puntero
ios::end Desplazamiento desde el final del fichero

El valor de offset puede ser positivo o negativo, si es negativo, el desplazamiento es en la dirección del principio del fichero.

El parámetro mode especifica que el movimiento puede ser en el área de entrada, salida o ambos, especificado por ios::in, ios::out o los dos.

Se trata de una función virtual, cuando se redefine en clases derivadas, puede funcionar con respecto al stream, y no sobre el buffer interno de streambuf:

Función seekpos

virtual streampos seekpos(streampos,
   int = (ios::in | ios::out));

Cambia o lee la posición del puntero del buffer interno de streambuf a una posición absoluta streampos.

También es una función virtual, de modo que puede ser redefinida en clases derivadas para modificar la posición en un stream de entrada o salida.

Función setbuf

streambuf* setbuf(unsigned char*, int);

Especifica el array para ser usado como buffer interno.

Función sgetc

int sgetc();

Toma el siguiente carácter del buffer interno de entrada.

Función sgetn

int sgetn(char*, int n);

Toma los siguientes n caracteres del buffer interno de entrada.

Función snextc

int snextc();

Avanza y toma el siguiente carácter del buffer interno de entrada.

Función sputbackc

int sputbackc(char);

Devuelve un carácter al buffer de entrada interno.

Función sputc

int sputc(int);

Coloca un carácter en el buffer de salida interno.

Función sputn

int sputn(const char*, int n);

Coloca n caracteres en el buffer de salida interno.

Función stossc

void stossc();

Avanza al siguiente carácter en el buffer de entrada interno.

Clase ios

La clase ios está diseñada para ser la clase base de otras clases derivadas como istream, ostream, iostream, fstreambase y strstreambase. Proporciona operaciones comunes de entrada y salida

Enums

Dentro de la clase ios se definen varios tipos enumerados que son útiles para modificar flags y opciones o para el tratamiento de errores o estados de un stream.

Todos los miembros de enums definidos en la clase ios son accesibles mediante el operador de ámbito. Por ejemplo:

ios::eofbit
ios::in
ios::beg
ios::uppercase

io_state

enum io_state { goodbit, eofbit, failbit, badbit }; 

open_mode

enum open_mode { in, out, ate, app, trunc, nocreate,
   noreplace, binary };

seek_dir

enum seek_dir { beg, cur, end }; 

Flags de modificadores de formato

enum { skipws, left, right, internal,
   dec, oct, hex, showbase, showpoint,
   uppercase, showpos, scientific,
   fixed, unitbuf, stdio };

Máscaras de modificadores

Permiten trabajar con grupos de modificadores afines.

enum {
   basefield = dec+oct+hex,
   floatfield = scientific+fixed,
   adjustfield = left+right+internal
};

Funciones

No nos interesan todas las funciones de las clases que vamos a estudiar, algunas de ellas raramente las usaremos, y en general son de poca o ninguna utilidad.

Función bad

int bad();

Devuelve un valor distinto de cero si ha ocurrido un error.

Sólo se comprueba el bit de estado ios::badbit, de modo que esta función no equivale a !good().

Función clear

void clear(iostate state=0);

Sirve para modificar los bits de estado de un stream, normalmente para eliminar un estado de error. Se suelen usar constantes definidas en el enum io_state definido en ios, usando el operador de bits OR para modificar varios bits a la vez.

Función eof

int eof();

Devuelve un valor distinto de cero si se ha alcanzado el fin de fichero.

Esta función únicamente comprueba el bit de estado ios::eofbit.

Función fail

int fail();

Devuelve un valor distinto de cero si una operación sobre el stream ha fallado.

Comprueba los bits de estado ios::badbit y ios::failbit.

Función fill

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 las siguientes salidas, y también devuelve el valor actual.

Ejemplo:

  int x = 23;
  cout << "|";
  cout.width(10);
  cout.fill('%');
  cout << x << "|" << x << "|" << endl;

Función flags

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.

Ejemplo:

   int x = 235;
   long f;

   cout << "|";
   f = flags();
   f &= !(ios::adjustfield);
   f |= ios::left;
   cout.flags(f);
   cout.width(10);
   cout << x << "|" << endl;

Función good

int good();

Devuelve un valor distinto de cero si no ha ocurrido ningún error, es decir, si ninguno de los bits de estado está activo.

Aunque pudiera parecerlo, (good significa bueno y bad malo, en inglés) esta función no es exactamente equivalente a !bad().

En realidad es equivalente a rdstate() == 0.

Función precision

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 las siguientes salidas, y también devuelve el valor actual.

   float x = 23.45684875;

   cout << "|";
   cout.precision(6);
   cout << x << "|" << x << "|" << endl;

Función rdbuf

streambuf* rdbuf();

Devuelve un puntero al streambuf asignado a este stream.

Función rdstate

int rdstate();

Devuelve el estado del stream. Este estado puede ser una combinación de cualquiera de los bits de estado definidos en el enum ios::io_state, es decir ios::badbit, ios::eofbit, ios::failbit e ios::goodbit. El goodbit no es en realidad un bit, sino la ausencia de todos los demás. De modo que para verificar que el valor obtenido por rdstate es ios::goodbit tan sólo hay que comparar. En cualquier caso es mejor usar la función good().

En cuanto a los restantes bits de estado se puede usar el operador & para verificar la presencia de cada uno de los bits. Aunque de nuevo, es preferible usar las funciones bad(), eof() o fail().

Función setf

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 tanto en el parámetro y deja sin cambios el resto.

La segunda forma activa los flags que estén activos tanto en valor como en máscara y desactiva los que estén activos en mask, pero no en valor. Podemos considerar que mask 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;

Función tie

Algunos streams de entrada están enlazados a otros. Cuando un stream de entrada tiene caracteres que deben ser leídos, o un stream de salida necesita más caracteres, el buffer del fichero enlazado se vacía automáticamente.

Por defecto, cin, err y clog están enlazados con cout. Cuando se usa cin, el buffer de cout se vacía automáticamente.

ostream* tie();
ostream* tie(ostream* val);

La primera forma devuelve el stream (enlazado), o cero si no existe. La segunda enlaza otro stream al actual y devuelve el previo, si existía.

Función unsetf

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;

Función width

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 las siguientes salidas, y también devuelve el valor actual de la anchura.

   int x = 23;

   cout << "#";
   cout.width(10);
   cout << x << "#" << x << "#" << endl;

Función xalloc

static int xalloc();

Devuelve un índice del array de las palabras no usadas que pueden ser utilizadas como flags de formatos definidos por el usuario.

Función init (protegida)

void init(streambuf *);

Asocia el objeto de la clase ios con el streambuf especificado.

Función setstate (protegida)

void setstate(int);

Activa los bits de estado seleccionados. El resto de los bits de estado no se ven afectados, si llamamos a setstate(ios::eofbit), se añadirá ese bit, pero no se eliminarán los bits ios::badbit o ios::failbit si ya estaban activos.

Clase filebuf

La declaración de esta clase está en el fichero fstream.

Esta clase se base en la clase streambuf, y le proporciona las funciones necesarias para manipular entrada y salida de caracteres en ficheros.

Las funciones de entrada y salida de istream y ostream hacen llamadas a funciones de filebuf, mediante el puntero a filebuf que existe en la clase ios.

Constructores

filebuf::filebuf();
filebuf::filebuf(int fd);
filebuf::filebuf(int fd, char *, int n);

La primera forma crea un filebuf que no está asociado a ningún fichero.

La segunda forma crea un filebuf asociado a un fichero mediante el descriptor fd.

La tercera forma crea un filebuf asociado a un fichero especificado mediante el descriptor fd y asociado a un buffer buf de tamaño n bytes. Si n es cero o negativo, el filebuf es sin buffer.

Nota:

He comprobado que algunos compiladores sólo disponen de la primera versión del constructor.

Funciones

Función attach (no siempre disponible)

filebuf* attach(int fd);

El filebuf debe estar cerrado, esta función asocia el filebuf a otro fichero especificado mediante el descriptor fd.

Función close

filebuf* close();

Actualiza la información actualmente en el buffer y cierra el fichero. En caso de error, retorna el valor 0.

Función fd (no siempre disponible)

int fd();

Devuelve el descriptor de fichero o EOF.

Función is_open

int is_open();

Si el fichero está abierto devuelve un valor distinto de cero.

Función open

filebuf* open(const char *name, int mode,
   int prot = filebuf::openprot);

Abre un fichero para un objeto de una clase específica, con el nombre name. Para el parámetro mode se puede usar el enum open_mode definido en la clase ios.

Parámetro mode Efecto
ios::app (append) Se coloca al final del fichero antes de cada operación de escritura.
ios::ate (at end) Se coloca al final del stream al abrir el fichero.
ios::binary Trata el stream como binario, no como texto.
ios::in Permite operaciones de entrada en un stream.
ios::out Permite operaciones de salida en un stream.
ios::trunc (truncate) Trunca el fichero a cero al abrirlo.

El parámetro prot se corresponde con el permiso de acceso DOS y es usado siempre que no se indique el modo ios::nocreate. Por defecto se usa el permiso para leer y escribir. En algunas versiones de las bibliotecas de streams no existe este parámetro, ya que está íntimamente asociado al sistema operativo.

Función overflow

virtual int overflow(int = EOF);

Vacía un buffer a su destino. Todas las clases derivadas deben definir las acciones necesarias a realizar.

Función seekoff

virtual streampos seekoff(streamoff offset,
   ios::seek_dir, int mode);

Mueve el cursor del fichero a una posición relativa offset a la posición actual en la dirección indicada por seek_dir.

Para seek_dir se usan los valores definidos en el enum seek_dir de la clase ios.

Valor Significado
ios::beg Desplazamiento desde el principio del fichero
ios::cur Desplazamiento desde la posición actual del puntero
ios::end Desplazamiento desde el final del fichero

Cuando se especifica un valor negativo como desplazamiento, éste se hace en la dirección del comienzo del fichero desde la posición actual o desde el final del fichero.

El parámetro mode indica el tipo de movimiento en el área de entrada o salida del buffer interno mediante los valores ios::in, ios::out o ambos.

Cuando esta función virtual se redefine en una clase derivada, debe desplazarse en el stream, y no en el buffer del miembro streambuffer interno.

Función setbuf

virtual streambuf* setbuf(char*, int);

Especifica un buffer del tamaño indicado para el objeto. Cuando se usa como un strstreambuf y la función se sobrecarga, el primer argumento no tiene sentido, y debe ponerse a cero.

Función sync

virtual int sync();

Sincroniza las estructuras de datos internas y externas del stream.

Función underflow

virtual int underflow();

Hace que la entrada esté disponible. Se llama a esta función cuando no hay más datos disponibles en el buffer de entrada. Todas las clases derivadas deben definir las acciones a realizar.

Clase istream

La declaración de esta clase está en el fichero iostream.h.

Proporciona entrada con y sin formato desde una clase derivada de streambuf via ios::bp.

El operador >> está sobrecargado para todos los tipos fundamentales, y puede formatear los datos.

La clase istream proporciona el código genérico para formatear los datos después de que son extraídos desde el stream de entrada.

Constructor

istream(streambuf *);

Asocia una clase derivada dada de streambuf a la clase que proporciona un stream de entrada. Esto se hace asignando ios::bp al parámetro del constructor.

Función rdbuf (protegida)

void eatwhite();

Extrae espacios en blanco consecutivos.

Función gcount

int gcount();

Devuelve el número de caracteres sin formato de la última lectura. Las lecturas sin formato son las realizadas mediante las funciones get, getline y read.

Función get

int get();
istream& get(char*, int len, char = '\n');
istream& get(char&);
istream& get(streambuf&, char = '\n');

La primera forma extrae el siguiente carácter o EOF si no hay disponible ninguno.

La segunda forma extrae caracteres en la dirección proporcionada en el parámetro char* hasta que se recibe el delimitador del tercer parámetro, el fin de fichero o hasta que se leen len-1 bytes. Siempre se añade un carácter nulo de terminación en la cadena de salida. El delimitador no se extrae desde el stream de entrada. La función sólo falla si no se extraen caracteres.

La tercera forma extrae un único carácter en la referencia a char proporcionada.

La cuarta forma extrae caracteres en el streambuf especificado hasta que se encuentra el delimitador.

Función getline

istream& getline(char*, int, char = '\n');

Extrae caracteres hasta que se encuentra el delimitador y los coloca en el buffer, elimina el delimitador del stream de entrada y no lo añade al buffer.

Función ignore

istream& ignore(int n = 1, int delim = EOF);

Hace que los siguientes n caracteres en el stream de entrada sean ignorados; la extracción se detiene antes si se encuentra el delimitador delim.

El delimitador también es extraído del stream.

Función ipfx

istream& ipfx(int n = 0);

Esta función es previamente llamada por las funciones de entrada para leer desde un stream de entrada. Las funciones que realizan entradas con formato la llaman como ipfx(0); las que realizan entradas sin formato la llaman como ipfx(1).

Función peek

int peek();

Devuelve el siguiente carácter sin extraerlo del stream.

Función putback

istream& putback(char);

Devuelve un carácter al stream.

Función read

istream& read(char*, int);

Extrae el número indicado de caracteres en el array char*. Se puede usar la función gcount() para saber el número de caracteres extraídos si ocurre algún error.

Función seekg

istream& seekg(streampos pos);
istream& seekg(streamoff offset, seek_dir dir);

La primera forma se mueve a posición absoluta, tal como la proporciona la función tellg.

La segunda forma se mueve un número offset de bytes la posición del cursor del stream relativa a dir. Este parámetro puede tomar los valores definidos en el enum seek_dir: {beg, cur, end};

Para streams de salida usar ostream::seekp.

Usar seekpos o seekoff para moverse en un buffer de un stream.

Función tellg

long tellg();

Devuelve la posición actual del stream.

Clase ostream

La declaración de esta clase está en el fichero iostream.h.

Proporciona salida con y sin formato a un streambuf.

Un objeto de la clase ostream no producirá la salida actual, pero sus funciones miembro pueden llamar a las funciones miembro de la clase apuntada por bp para insertar caracteres en el stream de salida.

El operador << da formato a los datos antes de enviarlos a bp.

La clase ostream proporciona el código genérico para formatear los datos antes de que sean insertados en el stream de salida.

Constructor

ostream(streambuf *buf);

Asocia el streambuf dado a la clase, proporcionando un stream de salida. Esto se hace asignando el puntero ios::bp a buf.

Función flush

ostream& flush();

Vacía el buffer asociado al stream. Procesa todas las salidas pendientes.

Función opfx

int opfx();

Esta función es llamada por funciones de salida para antes de hacer una inserción en un stream de salida. Devuelve cero si el ostream tiene un estado de error distinto de cero. En caso contrario, opfx devuelve un valor distinto de cero.

Función osfx

void osfx();

Realiza operaciones de salida (post?). Si está activado ios::unitbuf, osfx vacía el buffer de ostream. En caso de error, osfx activa el flag ios::failbit.

Función put

ostream& put(char ch);

Inserta un carácter en el stream de salida.

Función seekp

ostream& seekp(streampos);
ostream& seekp(streamoff, seek_dir);

La primera forma mueve el cursor del stream a una posición absoluta, tal como la devuelve la función tellp.

La segunda forma mueve el cursor a una posición relativa desde el punto indicado mediante el parámetro seek_dir, que puede tomar los valores del enum seek_dir: beg, cur, end.

Función tellp

streampos tellp();

Devuelve la posición absoluta del cursor del stream.

Función write

ostream& write(const char*, int n);

Inserta n caracteres (aunque sean nulos) en el stream de salida.

Clase iostream

La declaración de esta clase está en el fichero iostream.h.

Esta clase está derivada de istream y ostream, es una mezcla de sus clases base, y permite realizar tanto entradas como salidas en un stream. Además es la base para otras clases como fstream y strstream.

El stream se implementa mediante la clase ios::bp a la que apunta. Dependiendo del tipo de clase derivada a la que apunta bp, se determina si los streams de entrada y salida pueden ser el mismo.

Por ejemplo, si iostream usa un filebuf podrá hacer entradas y salidas en el mismo fichero. Si iostream usa un strstreambuf podrá hacer entradas y salidas en la misma o en diferentes zonas de memoria.

Constructor

iostream(streambuf *);

Asocia el streambuf dado a la clase.

Clase fstreambase

La declaración de esta clase está en el fichero fstream.

Esta clase proporciona acceso a funciones de filebuf inaccesibles a través de ios::bp tanto para fstreambase como para sus clases derivadas.

La una función miembro de filebuf no en un miembro virtual de la clase base filebuf (streambuf), ésta no será accesible. Por ejemplo: attach, open y close no lo son.

Los constructores de fstreambase inicializan el dato ios::bp para que apunte al filebuf.

Constructores

fstreambase();
fstreambase(const char *name,
   int mode, int = filebuf::openprot);
fstreambase(int fd);
fstreambase(int fd, char *buf, int len);

La primera forma crea un fstreambase que no está asociando a ningún fichero.

La segunda forma crea un fstreambase, abre el fichero especificado por name en el modo especificado por mode y lo conecta a ese fichero.

La tercera forma crea un fstreambase y lo conecta a un descriptor de fichero abierto y especificado por fd.

La cuarta forma crea un fstreambase y lo conecta a un descriptor de fichero abierto especificado por fd y usando un buffer especificado por buf con el tamaño indicado por len.

Función attach

void attach(int); 

Conecta con un descriptor de fichero abierto.

Función close

void close();

Cierra el filebuf y el fichero asociados.

Función open

void open(const char *name, int mode,
   int prot=filebuf::openprot);

Abre un fichero para el objeto especificado.

Para el parámetro mode se pueden usar los valores del enum open_mode definidos en la clase ios.

Clase Parámetro mode
fstream ios::in
ofstream ios::out

El parámetro prot se corresponde con el permiso de acceso DOS, y se usa salvo que se use el valor ios::nocreate para el parámetro mode. Por defecto se usa el valor de permiso de lectura y escritura.

Función rdbuf

filebuf* rdbuf();

Devuelve el buffer usado.

Función setbuf

void setbuf(char*, int);

Asigna un buffer especificado por el usuario al filebuf.

Clase ifstream

La declaración de esta clase está en el fichero fstream.h.

Proporciona un stream de entrada para leer desde un fichero usando un filebuf.

Constructores

ifstream();
ifstream(const char *name, int mode = ios::in,
   int = filebuf::openprot);
ifstream(int fd);
ifstream(int fd, char *buf, int buf_len);

La primera forma crea un ifstream que no está asociando a ningún fichero.

La segunda forma crea un ifstream, abre un fichero de entrada en modo protegido y se conecta a él. El contenido del fichero, si existe, se conserva; los nuevos datos escritos se añaden al final. Por defecto, el fichero no se crea si no existe.

La tercera forma crea un ifstream, y lo conecta a un descriptor de un fichero fd abierto previamente.

La cuarta forma crea un ifstream conectado a un fichero abierto especificado mediante su descriptor, fd. El ifstream usa el buffer especificado por buf de longitud buf_len.

Función open

void open(const char *name, int mode,
   int prot=filebuf::openprot);

Abre un fichero para el objeto especificado.

Para el parámetro mode se pueden usar los valores del enum open_mode definidos en la clase ios.

Clase Parámetro mode
fstream ios::in
ofstream ios::out

El parámetro prot se corresponde con el permiso de acceso DOS, y se usa salvo que se use el valor ios::nocreate para el parámetro mode. Por defecto se usa el valor de permiso de lectura y escritura.

Función rdbuf

filebuf* rdbuf();

Devuelve el buffer usado.

Clase ofstream

La declaración de esta clase está en el fichero fstream.

Proporciona un stream de salida para escribir a un fichero usando un filebuf.

Constructores

ofstream();
ofstream(const char *name, int mode = ios::out,
   int = filebuf::openprot);
ofstream(int fd);
ofstream(int fd, char *buf, int buf_len);

La primera forma crea un ofstream que no está asociando a ningún fichero.

La segunda forma crea un ofstream, abre un fichero de salida y se conecta a él.

La tercera forma crea un ofstream, y lo conecta a un descriptor de un fichero fd abierto previamente.

La cuarta forma crea un ofstream conectado a un fichero abierto especificado mediante su descriptor, fd. El ofstream usa el buffer especificado por buf de longitud buf_len.

Función open

void open(const char *name, int mode,
  int prot=filebuf::openprot);

Abre un fichero para el objeto especificado.

Para el parámetro mode se pueden usar los valores del enum open_mode definidos en la clase ios.

Clase Parámetro mode
fstream ios::in
ofstream ios::out

El parámetro prot se corresponde con el permiso de acceso DOS, y se usa salvo que se use el valor ios::nocreate para el parámetro mode. Por defecto se usa el valor de permiso de lectura y escritura.

Función rdbuf

filebuf* rdbuf();

Devuelve el buffer usado.

Clase fstream

La declaración de esta clase está en el fichero fstream.h.

Proporciona un stream de salida y salida a un fichero usando un filebuf.

La entrada y la salida se inicializan usando las funciones de las clases base istream y ostream. Por ejemplo, fstream puede usar la función istream::getline() para extraer caracteres desde un fichero.

Constructores

fstream();
fstream(const char *name, int mode = ios::in,
   int = filebuf::openprot);
fstream(int fd);
fstream(int fd, char *buf, int buf_len);

La primera forma crea un fstream que no está asociando a ningún fichero.

La segunda forma crea un fstream, abre un fichero con el acceso especificado por mode y se conecta a él.

La tercera forma crea un fstream, y lo conecta a un descriptor de un fichero fd abierto previamente.

La cuarta forma crea un fstream conectado a un fichero abierto especificado mediante su descriptor, fd. El fstream usa el buffer especificado por buf de longitud buf_len. Si buf es NULL o n no es positivo, el fstream será sin buffer.

Función open

void open(const char *name, int mode,
   int prot=filebuf::openprot);

Abre un fichero para el objeto especificado.

Para el parámetro mode se pueden usar los valores del enum open_mode definidos en la clase ios.

Clase Parámetro mode
fstream ios::in
ofstream ios::out

El parámetro prot se corresponde con el permiso de acceso DOS, y se usa salvo que se use el valor ios::nocreate para el parámetro mode. Por defecto se usa el valor de permiso de lectura y escritura.

Función rdbuf

filebuf* rdbuf();

Devuelve el buffer usado.

Clase strstreambuf

La declaración de esta clase está en el fichero strstrea.h.

Clase base para especializar la clase ios para el manejo de streams de cadenas, esto se consigue inicializando ios::bp de modo que apunte a un objeto strstreambuf. Esto proporciona las comprobaciones necesarias para cualquier operación de entrada y salida de cadenas en memoria. Por ese motivo, la clase strstreambase está protegida y sólo es accesible para clases derivadas que realicen entradas y salidas.

Constructores

strstreambase();
strstreambase(const char*, int, char *start);

La primera forma crea un strstreambase con el buffer de su dato streambuf en memoria dinámica reservada la primera vez que se usa. Las zonas de lectura y escritura son la misma.

La segunda forma crea un strstreambase con el buffer y la posición de comienzo especificados.

Función rdbuf

strstreambuf * rdbuf();

Devuelve un puntero a strstreambuf asociado con este objeto.

Clase strstreambase

La declaración de esta clase está en el fichero strstrea.h.

Especialización de la clase ios para streams de cadena inicializando ios::bp para que apunte a un strstreambuf. Esto proporciona la condición necesaria para cualquier operación de entrada/salida en memoria. Por esa razón, strstreambase está diseñada completamente protegida y accesible sólo para clases derivadas que realicen entradas y salidas. Hace uso virtual de la clase ios.

Constructores

strstreambase();
strstreambase(const char*, int, char *start);

La primera forma crea un strstreambase con el buffer de streambuf creado dinámicamente la primera vez que se usa. Las áreas de lectura y escritura son la misma.

La segunda forma crea un strstreambase con el buffer especificado y al posición de comienzo start.

Función rdbuf

strstreambuf* rdbuf();

Devuelve un puntero al strstreambuf asociado con este objeto.

Clase istrstream

La declaración de esta clase está en el fichero strstrea.

Proporciona las operaciones de entrada en un strstreambuf.

El bloque formado por ios, istream, ostream, iostream y streambuf, proporciona una base para especializar clases que trabajen con memoria.

Constructores

istrstream(char *);
istrstream(char *str, int n);

La primera forma crea un istrstream con la cadena especificada (el carácter nulo nunca se extrae).

La segunda forma crea un istrstream usando n bytes para str.

Clase ostrfstream

La declaración de esta clase está en el fichero strstrea.h.

Proporciona un stream de salida para inserción desde un array usando un strstreambuf.

Constructores

ostrstream();
ostrstream(char *buf, int len, int mode = ios::out);

La primera forma crea un ostrstream con un array dinámico como stream de entrada.

La segunda forma crea un ostrstream con un buffer especificado por buf y un tamaño especificado por len. Si mode es ios::app o ios::ate, los punteros de lectura/escritura se colocan en la posición del carácter nulo de la cadena.

Función pcount

int pcount();

Devuelve el número de caracteres actualmente almacenados en el buffer.

Función str

char *str();

Devuelve y bloquea el buffer. El usuario debe liberar el buffer si es dinámico.

Clase strstream

La declaración de esta clase está en el fichero strstrea.h.

Proporciona entrada y salida simultanea en un array usando un strstreambuf. La entrada y la salida son realizadas usando las funciones de las clases base istream y ostream.

Por ejemplo, strstream puede usar la función istream::getline() para extraer caracteres desde un buffer.

Constructores

strstream();
strstream(char*, int sz, int mode);

La primera forma crea un strstream con el buffer del dato miembro strambuf de la clase base strstreambase creado dinámicamente la primera vez que se usa. Las áreas de entrada y salida son la misma.

La segunda forma crea un strstream con un buffer del tamaño especificado. Si el parámetro mode es ios::app o ios::ate, el puntero de entrada/salida se coloca en el carácter nulo que indica el final de la cadena.

Función str

char *str();

Devuelve y bloquea el buffer. El usuario debe liberar el buffer si es dinámico.

Objetos predefinidos

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++:

  • cin: entrada estándar: teclado.
  • cout: salida estándar: pantalla.
  • cerr: salida sin buffer a pantalla, la salida es inmediata, no es necesario vaciar el buffer.
  • clog: igual que cerr, aunque suele redirigirse a un fichero log en disco.

Objeto cout

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.

El operador <<

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";

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

Funciones interesantes de cout

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 bibliotecas, pero veremos ahora las que se usan más frecuentemente.

Formatear la salida

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.

Funciones manipuladoras con parámetros

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.

Manipulador setw

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#
Manipulador setbase

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#
Manipulador setfill

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#
Manipulador setprecision

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#
Manipuladores setiosflags y resetiosflags

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#

Manipuladores sin parámetros

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.

Manipuladores dec, hex y oct
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;

   return 0;
}

La salida tendrá éste aspecto:

Decimal:     123, 543, 432
Hexadecimal: 7b, 21f, 1b0
Octal:       173, 1037, 660
Funciones ws y ends

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.

Función flush
ostream& flush(ostream& outs);

Vacía el buffer de salida. Puede ser invocada de dos modos:

cout.flush();
cout << flush;
Función endl
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;
Función width

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;
Función fill

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;
Función precision

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;
Función setf

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;
Función unsetf

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;
Función flags

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;
Función put

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;
Función write

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;
Función form

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

Objeto cin

Se trata de un objeto global definido en "iostream.h".

En ejemplos anteriores ya hemos usado el operador >>.

El operador >>

Ya conocemos el operador >>, lo hemos usado para capturar variables.

istream &operator>>(int&)

Este operador está sobrecargado en cin para los tipos estándar: int&, short&, long&, double&, float&, charamp;& y char*.

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:

cin >> var1 >> var2;
cin >> variable;

Cuando se usa el operador >> para leer cadenas, la lectura se interrumpe al encontrar un carácter '\0', ' ' o '\n'.

Hay que tener cuidado, ya que existe un problema cuando se usa el operador >> para leer cadenas: cin no comprueba el desbordamiento del espacio disponible para el almacenamiento de la cadena, del mismo modo que la función gets tampoco lo hace. De modo que resulta poco seguro usar el operador >> para leer cadenas.

Por ejemplo, declaramos:

char cadena[10];
cin >> cadena;

Si el usuario introduce más de diez caracteres, los caracteres después de décimo se almacenarán en una zona de memoria reservada para otras variables o funciones.

Existe un mecanismo para evitar este problema, consiste en formatear la entrada para limitar el número de caracteres a leer:

char cadena[10];
cin.width(sizeof(cadena));
cin >> cadena;

De este modo, aunque el usuario introduzca una cadena de más de diez caracteres sólo se leerán diez.

Funciones interesantes de cin

Hay que tener en cuenta que cin es un objeto de la clase "istream", 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 bibliotecas, pero veremos ahora las que se usan más frecuentemente.

Formatear la entrada

El formato de las entradas de cin, al igual que sucede con 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.

Funciones manipuladoras con parámetros

Para usar estos manipuladores es necesario incluir el fichero de cabecera iomanip.

Existen cuatro de estas funciones manipuladoras aplicables a cin: setw, setbase, setiosflags y resetiosflags.

Todas trabajan del mismo modo, y afectan sólo a la siguiente entrada o salida.

En el caso de cin, no todas las funciones manipuladoras tienen sentido, y algunas trabajan de un modo algo diferentes que con streams de salida.

Manipulador setw

Permite establecer el número de caracteres que se leerán en la siguiente entrada desde cin. Por ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
   char cad[10];

   cout << "Cadena:"
   cin >> setw(10) >> cad;

   cout << cad << endl
   return 0;
}

La salida tendrá este aspecto, por ejemplo:

Cadena: 1234567890123456
123456789

Hay que tener en cuenta que el resto de los caracteres no leídos por sobrepasar los diez caracteres, se quedan en el buffer de entrada de cin, y serán leídos en la siguiente operación de entrada que se haga. Ya veremos algo más abajo cómo evitar eso, cuando veamos la función "ignore".

El manipulador setw no tiene efecto cuando se leen números, por ejemplo:

#include >iostream>
#include >iomanip>
using namespace std;

int main() {
   int x;

   cout >> "Entero:"
   cin >> setw(3) >> x

   cout >> x >> endl
   return 0;
}

La salida tendrá este aspecto, por ejemplo:

Entero: 1234567
1234567
Manipulador setbase

Permite cambiar la base de numeración que se usará para la entrada de números enteros. 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;

   cout << "Entero: ";
   cin >> setbase(16) >> x;

   cout << "Decimal: " << x << endl;
   return 0;
}

La salida tendrá este aspecto:

Entero: fed4

Decimal: 65236
Manipuladores setiosflags y resetiosflags

Permiten activar o desactivar, respectivamente, los flags de formato de entrada. 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

De los flags de formato listados, sólo tienen sentido en cin los siguientes: skipws, dec, oct y hex.

Veamos un ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
   char cad[10];

   cout << "Cadena: ";
   cin >> setiosflags(ios::skipws) >> cad;
   cout << "Cadena: " << cad << endl;

   return 0;
}

La salida tendrá este aspecto:

Cadena:         prueba
Cadena: prueba

Manipuladores sin parámetros

Existen 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 entrada, sino a todas las entradas hasta que se vuelva a modificar el formato afectado.

Manipuladores dec, hex y oct
inline ios& dec(ios& i)
inline ios& hex(ios& i)
inline ios& oct(ios& i)

Permite cambiar la base de numeración de las entradas de enteros:

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 x, y, z;

   cout << "Entero decimal (x y z): ";
   cin >> dec >> x >> y >> z;
   cout << "Enteros: " << x << ", "
        << y << ", " << z << endl;
   cout << "Entero octal (x y z): ";
   cin >> oct >> x >> y >> z;
   cout << "Enteros: " << x << ", "
        << y << ", " << z << endl;
   cout << "Entero hexadecimal (x y z): ";
   cin >> hex >> x >> y >> z;
   cout << "Enteros: " << x << ", "
        << y << ", " << z << endl;

   return 0;
}

La salida tendrá éste aspecto:

Entero decimal (x y z): 10 45 25
Enteros: 10, 45, 25
Entero octal (x y z): 74 12 35
Enteros: 60, 10, 29
Entero hexadecimal (x y z): de f5 ff
Enteros: 222, 245, 255
Función ws
extern istream& ws(istream& ins);

Ignora los espacios iniciales en una entrada de cadena. Ejemplo:

#include <iostream>
using namespace std;

int main() {
   char cad[10];

   cout << "Cadena: ";
   cin >> ws >> cad;
   cout << "Cadena: " << cad << endl;

   return 0;
}

La salida tendrá éste aspecto:

Cadena:      hola
Cadena: hola
Función width()

Cambia la anchura en caracteres de la siguiente entrada 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 entrada, y también devuelve el valor actual de la anchura. Esta función no tiene efecto con variables que no sean de tipo cadena.

   char cadena[10];

   cin.width(sizeof(cadena));
   cin >> cadena;
Función setf()

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 tanto en el parámetro y deja sin cambios el resto.

La segunda forma activa los flags que estén activos tanto en valor como en máscara y desactiva los que estén activos en mask, pero no en valor. Podemos considerar que mask contiene activos los flags que queremos modificar y valor los flags que queremos activar.

Ambos devuelven el valor previo de los flags.

   int x;

   cin.setf(ios::oct, ios::dec | ios::oct | ios::hex);
   cin >> x;
Función unsetf()

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;

   cin.unsetf(ios::dec | ios::oct | ios::hex);
   cin.setf(ios::hex);
   cin >> x;
Función flags()

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;
   long f;

   f = flags();
   f &= !(ios::hex | ios::oct | ios::dec);
   f |= ios::dec;
   cin.flags(f);
   cin >> x;

Función get

La función get() tiene tres formatos:

int get();
istream& get(char& c);
istream& get(char* ptr, int len, char delim = '\n');

Sin parámetros, lee un carácter, y lo devuelve como valor de retorno:

Nota:

Esta forma de la función get() se considera obsoleta.

Con un parámetro, lee un carácter:

En este formato, la función puede asociarse, ya que el valor de retorno es una referencia a un stream. Por ejemplo:

char a, b, c;

cin.get(a).get(b).get(c);

Con tres parámetros: lee una cadena de caracteres:

En este formato la función get lee caracteres hasta un máximo de 'len' caracteres o hasta que se encuentre el carácter delimitador.

char cadena[20];

cin.get(cadena, 20, '#');
Función getline

Funciona exactamente igual que la versión con tres parámetros de la función get(), salvo que el carácter delimitador también se lee, en la función get() no.

istream& getline(char* ptr, int len, char delim = '\n');
Función read

Lee n caracteres desde el cin y los almacena a partir de la dirección ptr.

istream& read(char* ptr, int n);
Función ignore

Ignora los caracteres que aún están pendientes de ser leídos:

istream& ignore(int n=1, int delim = EOF);

Esta función es útil para eliminar los caracteres sobrantes después de hacer una lectura con el operador >>, get o getline; cuando leemos con una achura determinada y no nos interesa el resto de los caracteres introducidos. Por ejemplo:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
   char cad[10];
   int i;

   cout << "Cadena: ";
   cin >> setw(10) >> cad;
   cout << "Entero: ";
   cin.ignore(100, '\n') >> i;
   cout << "Cadena: " << cad << endl;
   cout << "Entero: " << i << endl;

   cin.get();
   return 0;
}

La salida podría tener este aspecto:

Cadena: cadenademasiadolarga
Entero: 123
Cadena: cadenadem
Entero: 123
Función peek

Esta función obtiene el siguiente carácter del buffer de entrada, pero no lo retira, lo deja donde está.

int peek();
Función putback

Coloca un carácter en el buffer de entrada:

istream& putback(char);
Función scan

Lee variables con formato, es análogo al scanf de "stdio":

istream& scan(char* format, ...);
Nota:

Algunos compiladores no disponen de esta función.

Ejemplo:

   char l;
   int i;
   float f;
   char cad[15];

   cin.scan("%c%d%f%s", &l, &i, &f, cad);