Entrada/Salida en C++
Programación Orientada a Objeto Ing. Civil en Telecomunicaciones
Flujos en C++ (Streams)
• Hasta aquí, hemos usado cin y cout para leer desde teclado y escribir a consola
• C++ no incluye comandos de entrada/salida en el lenguaje
Definidos en bibliotecas de E/S
Objetivo: tratar todas las fuentes de datos (teclado, archivos, redes) de la misma forma:
como flujos de bytes de largo indefinido
Clases de entrada/salida
• Biblioteca de entrada/salida de C++
define una jerarquía de clases
Flujos y buffers
• Escribir a pantalla o a archivos es lento
• Sistema mantiene buffers en memoria para acoplar velocidades
Datos se reciben del teclado a un buffer, donde quedan disponibles hasta que el programa los necesita
Datos se escriben en un buffer en vez de escribir directamente en un archivo
Buffer se escribe al archivo cuando está lleno
Flujos y buffers
• No todos los flujos utilizan buffers
• En algunos casos, se escriben los datos directamente al destino sin pasar por el buffer intermedio
Ejemplo: cout y clog usan buffers, cerr no usa buffers
Clase abstracta streambuf
• La clase base abstracta streambuf maneja el buffer
Sus funciones miembro permiten leer, escribir, sincronizar, vaciar y escribir a memoria los flujos
Funciones no se invocan directamente
Clases derivadas son stringbuf y filebuf
Clases de entrada/salida
• La clase ios es la clase base para los flujos de entrada y salida
• Define todas las funciones comunes a flujos de entrada y de salida
Contiene un objeto streambuf
Métodos manipuladores de formato
Maneja los bits de estado del flujo
eofbit, badbit, failbit, goodbit
Estado de un flujo
•goodbit indica que todo está OK
•failbit es 1 si una operación no se procesó correctamente pero el flujo está OK
•badbit es 1 si el flujo está corrupto o si se han perdido datos
•eofbit es 1 si se detectó el fin de flujo
Generalmente se activa con failbit
Clase de entrada istream
• Clase istream representa objetos usados para leer secuencias de caracteres
Datos con formato son accedidos usando el operador istream::operator>>
double a, b, c;
cin >> a >> b >> c;
Datos sin formato son accedidos a través de otras operaciones
get(), getline(), read()
Clase de salida ostream
• Clase ostream representa objetos usados para escribir secuencias de caracteres
Datos con formato son accedidos usando el operador istream::operator<<
double a, b, c;
cout << a << b << c;
Datos sin formato son accedidos a través de otras operaciones
put(), write()
Clases generales de entrada/salida
• Clases generales de entrada/salida
<iostream>: entrada/salida estándar
<fstream>: entrada/salida de archivos
<sstream>: entrada/salida hacia/desde strings
• Clase para manipulación de flujos
<iomanip>: manipulación de flujos
Clase de entrada/salida iostream
• Clase iostream deriva métodos de istream y de ostream
Define 4 flujos estándar
cin: entrada estándar de teclado
cout: salida estándar a consola
cerr: salida estándar de error
clog: salida estándar de bitácora
Estos flujos pueden ser manipulados por operadores >>, << o por otras funciones
Función istream::get() (I)
•int get() lee el siguiente caracter desde un flujo de entrada y lo retorna
Retorna el siguiente caracter en el flujo, o retorna EOF
char c = cin.get();
Función istream::get() (II)
•iostream& get(char& c) lee un caracter desde un flujo de entrada y lo almacena en el caracter c
Retorna el flujo de entrada, por lo que puede ser usado en concatenaciones
cin.get(a).get(b).get(c);
cin.get(a) >> b >> c;
Función istream::get() (II)
•iostream& get(char* p, int n, char delim) lee n - 1 caracteres desde un flujo de entrada y los almacena a partir del puntero p dado, retornando el flujo de entrada
Función almacena caracter NULL en el último byte del área destino
Lectura se detiene al llegar al delimitador
Si se omite delimitador, asume ‘\n’
Delimitador queda en flujo de entrada
Función istream::getline()
•iostream& getline(char* p, int n, char delim) lee n - 1 caracteres desde un flujo de entrada y los almacena a partir del puntero p dado, retornando el flujo de entrada
Función almacena caracter NULL en el último byte del área destino
Lectura se detiene al llegar al delimitador
Si se omite delimitador, asume ‘\n’
Caracter delimitador es removido del flujo
Función istream::read()
• Función istream& read(char *p, n) lee n bytes desde el flujo de entrada, y los almacena a partir del puntero p dado
Retorna el flujo de entrada
Termina anticipadamente al encontrar EOF
En ese caso, se activa failbit y eofbit
gcount() retorna número de caracteres leídos
Función istream::readsome()
•streamsize readsome(char *p, n) lee n bytes desde el flujo de entrada, y los almacena a partir del puntero p dado
Lee todos los bytes disponibles en el buffer
Retorna el número de caracteres leídos
No termina anticipadamente con EOF
gcount() retorna número de caracteres leídos
Función istream::ignore()
•iostream& ignore(int n, char delim) lee n caracteres desde un flujo de entrada y los ignora
Lectura se detiene si encuentra delim
Delimitador es removido del flujo de entrada
Si éste se omite, el delimitador por omisión es EOF
Retorna el flujo de entrada
istream::ignore() ignora un caracter
Función istream::gcount()
• Función gcount() retorna el número de caracteres extraídos del flujo por la operación de lectura anterior
Aplicable a funciones : get(), getline(), ignore(), peek(), read(), readsome(), putback() y unget()
En los casos de unget() y putback(), gcount() siempre retorna 0
Función istream::peek()
•int peek() lee el siguiente caracter desde el flujo de entrada, y luego lo retorna al flujo
int a = cin.peek();
En caso de error, retorna EOF
Siguiente caracter queda entonces
disponible en el flujo para la siguiente lectura
Función istream::unget()
•istream& unget() devuelve el último caracter leído al flujo de entrada, y decrementa el puntero de lectura get pointer en 1
Función retorna el flujo de entrada
Llamada posterior a gcount() retorna 0
Función istream::putback()
•istream& putback(char c) retorna caracter c al flujo, y decrementa el puntero de lectura en el flujo get pointer en 1
cin.putback(c);
La función retorna el flujo de entrada
Similar a unget(), pero es posible definir el caracter a retornar al flujo
Si c no fue el último carácter extraído, se activa badbit
Función istream::sync()
• Fuerza el vaciado de los buffers del flujo de entrada, sincronizando su contenido
• Aplicable a flujos istream
• Caracteres aún no leídos en el flujo de entrada son descartados
Función ostream::put()
• La función ostream& put(char c) escribe el caracter c en el flujo de salida
Aplicable a flujos de salida ostream
Incrementa el put pointer en 1
Retorna el flujo de salida
El estado del flujo indica si la operación fue exitosa
Función ostream::write()
• Función ostream& write(char *p, n) escribe n bytes a partir del puntero p dado en el flujo de salida
Retorna el flujo de salida
El estado del flujo indica si la operación fue exitosa
Función ostream::flush()
• Función ostream& flush() fuerza la escritura de los buffers del flujo, sincronizando su contenido
• Aplicable a flujos ostream
• Función retorna el flujo de salida
• Fin de línea endl también fuerza un flush de los buffers
Funciones de estado
• Para determinar estado del flujo
bad() es true si hubo falla en operación de lectura ó escritura
fail() es true si hubo falla en lectura ó escritura, u error de otro tipo
Ejemplo: conversión de formatos
eof() es true si se llegó al fin del flujo
good() es true si todas las funciones anteriores son false
clear() limpia el estado del flujo
Punteros a flujos
• Objetos de la biblioteca mantienen punteros a flujos para lectura y/o escritura
Clase istream incluye el get pointer, que apunta a la próxima posición a leer
Clase ostream incluye el put pointer, que apunta a la próxima posición donde escribir
Clase iostream incluye ambos punteros
Posiciones están dadas en caracteres
Lectura de punteros a flujos
• Funciones tellg() y tellp() retornan un entero representando la posición absoluta de get pointer y put pointer, respectivamente
Posición está dada en caracteres
Falla es indicada por resultado -1
Función retorna el flujo asociado
tellg() pertenece a clase istream
tellp() pertenece a clase ostream
Movimiento de punteros
• Funciones seekg() y seekp() definen nuevas posiciones del get pointer y put pointer
istream& seekg(offset, pos)
Posición pos está dada en caracteres
• No todos los flujos admiten funciones seekg() y seekp()
No son válidas para flujos estándares cin, cout y cerr
Movimiento de punteros
• Posición puede ser relativa al comienzo del flujo o relativa a otra posición
seekg(offset, pos), donde offset es
ios::beg: comienzo del flujo
ios::end: final del flujo
ios::cur:posición actual del flujo
• Comportamiento ante accesos fuera del flujo no está definido
Movimiento de punteros
#include <fstream>
. . .
ifstream if(“archivo.txt”, istream::binary);
if (is) {
is.seekg(0, is.end);
int largo = is.tellg(); // Calcula el largo is.seekg(0, is.beg);
char *buffer = new char[largo];
is.read(buffer, largo); // Lee todo el archivo if (is)
cout << “Se leyeron ” << is.gcount() << “bytes”
<< endl;
is.close() }
Manejo de archivos
• Hay 3 clases para manipular archivos
ifstream: usada para leer desde un archivo
ofstream: usada para escribir a un archivo
fstream: usada para leer y escribir a un archivo
• Archivos pueden ser abiertos en modo texto o modo binario
Modo texto: interpreta caracteres especiales
Modo binario: no hay caracteres especiales
Manejo de archivos: open() y close()
fstream f;
f.open(nombre, modo)
nombre es el nombre del archivo como un string de C
modo indica el modo de operación con el archivo
• Flujo se cierra con f.close()
Flujo también se cierra al destruir el objeto
Modos de open()
• Modos de open()
ios::in: abrir para entrada de datos
ios::out: abrir para salida de datos
ios::binary: abrir en modo binario
ios::ate: abrir con posición inicial al final del archivo (at end)
ios::app: abrir para agregar datos (append). Se usa en conjunto con ios::out
ios::trunc: abrir con posición inicial el comienzo del archivo, y se borra su contenido
Modos por omisión
• Modos se deducen del tipo de archivo
ifstream arch1(“entrada.txt”);
Se agrega modo ios::in automáticamente ofstream arch2(“salida.txt”);
Se agrega ios::out automáticamente fstream arch3(“datos.txt”);
Se agregan modos ios::in y ios::out automáticamente
Creación y apertura de archivos
• Constructor por omisión de flujos de archivos también abren el flujo
ofstream arch1;
arch1.open(“datos.txt", ios::out | ios::app | ios::binary);
Equivale a
ofstream arch1(“datos.txt", ios::out | ios::app | ios::binary);
Nótese cómo combinar modos usando |
Archivos binarios
• No se reconocen caracteres especiales
No se consideran delimitadores, espacios, ó saltos de línea
• Acceso mediante read() y write()
char buffer[1000];
f.read(buffer, 1000);
f.write(buffer, 1000);
Manipuladores de entrada/salida
• Objetos especiales para manipular flujos
Usados con operadores << y >>
Manipuladores de salida (clase ostream)
endl: escribe ‘\n’ y sincroniza buffer de salida
ends: escribe ‘\0’ en el buffer de salida
flush: escribe el buffer de salida a su destino
Manipuladores de entrada (clase istream)
ws: lee y descarta espacios en blanco
♣Muchos flujos tienen esta opción activada por omisión
Manipuladores de formato
• Definidos en <iomanip>
setbase: define la base de los números a desplegar. Puede ser 8, 10 ó 16
cout << setbase(16) << 100 << endl;
oct, dec, hex: definen la base a usar cout << hex << 100 << endl;
setw: Define el ancho del próximo campo cout << setw(7) << 100 << endl;
Manipuladores de formato
setprecision: define la precisión decimal del siguiente número
cout << setprecision(7) << 3.1415;
setfill: define el caracter a usar como relleno en un número
cout << setw(7) << setfill(‘a’) <<
433;
Tiene como salida aaaa433
Manipuladores de formato
• Definidos en ios
boolalpha/noboolalpha: Imprime true o false para valores booleanos.
showpos/noshowpos: Controla impresión de signo + para los números positivos
uppercase/nouppercase: Usa mayúsculas en números de punto flotante
showpoint/noshowpoint: Siempre imprime el punto en números de punto flotante
Manipuladores de formato
• Definidos en ios
showbase/noshowbase: Siempre imprime la base de un número
skipws/noskipws: Ignora los espacios en blanco al leer del flujo
unitbuf/nounitbuf: Siempre sincroniza el flujo después de cada operación inserción en éste
fixed/scientific: tipo de notación a usar en el flujo
Manipuladores de formato
• Definidos en ios
left: alinea número a la izquierda en el campo de largo dado por setw y rellena el campo con el caracter dado por setfill
right: alinea número a la derecha en el campo de largo dado por setw y rellena el campo con el caracter dado por setfill
internal: alinea número en el campo de acuerdo a un valor interno, y rellena el campo con el caracter dado por setfill
Manipuladores de formato
• Definidos en iomanip
setiosflags: activa los flags de formato del flujo de acuerdo a una máscara
resetiosflags: desactiva los flags de formato del flujo de acuerdo a una máscara
cout << hex <<
setiosflags(ios_base::showbase | ios_base::uppercase) << 100 << endl;
Imprime 0X64
Funciones de formato
• Todo lo que se hace con manipuladores de flujo puede realizarse con funciones de manejo de formato
• Definidas en ios_base
Ejemplo:
cout << showbase;
Equivale a
cout.setf(ios::showbase);
Funciones de formato
flags(): retorna un entero indicando los flags de formato
flags(newflags): asigna un nuevo valor a los flags de formato, y retorna un entero conteniendo los flags de formato antiguos
setf(newflag): asigna un nuevo valor a los flags de formato, y retorna un entero
conteniendo los flags de formato antiguos
unsetf(newflag): limpia los flags de formato especificados