Sobrecarga de Operadores y E/S en C++

Anuncio
Sobrecarga de Operadores y
E/S en C++
Antonio LaTorre de la Fuente
Índice
•  Sobrecarga de Funciones
•  Sobrecarga de Operadores
•  Entrada/Salida sobre streams básicos
•  Entrada/Salida sobre streams de fichero
•  Entrada/Salida sobre streams de cadena
Sobrecarga de Funciones
•  Nuevo con respecto a C
•  Funciones con el mismo nombre pero distinto
prototipo: número y/o tipo de argumentos
•  Útil si se quiere poder realizar una misma
operación sobre distintos tipos de datos
Sobrecarga de Funciones
void print (double number) {cout << number << endl;}
void print (int number) {cout << number << endl;}
void print (int number, string s = “hola”) {
cout << number << “, “ << s << endl;
}
Ambigüedad
•  ¿Qué pasa si incluimos en nuestro código…?
unsigned num = 3;
print (num);
•  El compilador no sabe a qué función llamar:
func_over.cc:18: error: call of overloaded print(unsigned int&) is ambiguous
func_over.cc:6: note: candidates are: void print(int)
func_over.cc:7: note:
void print(int, std::string)
func_over.cc:8: note:
void print(double)
Ambigüedad
•  Se soluciona usando static_cast
unsigned num = 3;
print (static_cast<double>(num));
•  ¿Qué pasaría si hiciéramos…?
int num = 3;
print (num);
Name Mangling
•  Estrategia que usa el compilador para poder
diferenciar dos funciones con el mismo nombre
int f (void) {return 1;}
int f (int) {return 0;}
void g (void) {int i = f (), j = f (0);}
•  Esto se traduciría en:
int __f_v (void) {return 1;}
int __f_i (int) {return 0;}
void __g_v (void) {int i = __f_v (), j = __f_i (0);}
Índice
•  Sobrecarga de Funciones
•  Sobrecarga de Operadores
•  Entrada/Salida sobre streams básicos
•  Entrada/Salida sobre streams de fichero
•  Entrada/Salida sobre streams de cadena
Operadores en C++
•  Lista de operadores válidos en C++
+
-
*
/
%
^
&
|
~
!
,
=
<
>
<=
>=
++
--
<<
>>
==
!=
&&
||
+=
-=
*=
/=
%=
^=
&=
|=
<<=
>>=
[]
()
->
->*
new
delete
•  Se declaran de la siguiente forma:
tipo operator operador([argumentos])
Operadores en C++
•  Hay algunos operadores especiales que no
pueden ser sobrecargados
• 
• 
• 
• 
• 
• 
:: (resolución de ámbito)
. (selección de un miembro)
.* (selección de un miembro referenciado por un puntero)
?: (operador condicional)
sizeof (tamaño de)
typeid (identificación del tipo)
Precedencia de Operadores
•  Los operadores en C++ tienen distinta
precedencia, y a veces no es obvio
•  Lo mejor es usar () en casa de no estar seguro
•  Tabla de precedencias:
Inglés: http://www.cplusplus.com/doc/tutorial/operators/
Español: http://es.wikipedia.org/wiki/Operadores_en_C_y_C%2B%2B
Sobrecarga de operadores
•  Podemos sobrecargar tanto operadores unarios
como binarios
tipo_ret operator op_unario (tipo1 arg1);
tipo_ret operator op_binario (tipo1 arg1, tipo2 arg2);
•  En este caso, ambos argumentos se muestran de
manera explícita
Sobrecarga de operadores
•  Ambas notaciones son equivalentes
C operator- (C n) {…}
C operator- (C n, C m) {…}
int main (void) {
int main (void) {
C a, b, c, d;
c = -b;
d = b – a;
}
C a, b, c, d;
c = operator- (b);
d = operator- (b, a);
}
Sobrecarga de operadores
•  Si los operadores son métodos de una clase, uno
de los argumentos es implícito (aquél que invoca
al operador)
class C {
public:
C operator- ();
C operator- (C);
}
Sobrecarga de operadores
•  Estas dos notaciones son
equivalentes
int main (void) {
int main (void) {
C a, b, c, d;
C a, b, c, d;
c = -b;
c = b.operator-();
d = b – a;
d = b.operator-(a);
}
}
Sobrecarga de operadores
•  Ejemplo: Números Complejos
class Complejo {
public:
Complejo (double r, double i) : real(r), imag(i) {}
…
private:
double real;
double imag;
}
Operadores Aritméticos
•  Suma de números complejos:
Complejo Complejo::operator+ (const Complejo& z2) const {
Complejo res (0, 0);
res.real = this->real + z2.real;
res.img = this->img + z2.img;
return res;
}
Operadores Relacionales
•  Comparación de números complejos:
bool Complejo::operator== (const Complejo& z2) const {
return this->real == z2.real && this->imag == z2.imag;
}
Operadores de auto-incremento
•  Son operadores unarios
•  Permiten pre-incrementar y post-incrementar el
valor de una variable
Pre-incremento: C C::operator++()
Post-incremento: C C::operator++(int x)
Complejo Complejo::operator++() {
real += 1;
return *this;
}
Funciones “Amigas”
•  Son funciones ajenas a una clase que pueden
acceder a los elementos privados de esa clase
•  Ejemplo:
•  Tenemos dos clases: Vector y Matriz
•  Queremos definir el producto vectorial entre
ambas clases
•  El contenido de los objetos es privado
Funciones “Amigas”
class Vector {
class Matriz {
friend operator* (const Matriz&
matriz, const Vector& vector);
friend operator* (const Matriz&
matriz, const Vector& vector);
public:
public:
…
…
private:
int size;
int* data;
}
private:
int rows, columns;
int** data;
}
Vector operator* (const Matriz& matriz, const Vector& vector) {…}
Operadores de asignación
•  Se sobrecargan para evitar la copia binaria de
objetos
class Vector {
public:
Vector& operator= (const Vector& vector) {
size = vector.size;
data = new int[vector.size];
for (unsigned i = 0; i < size; i++)
data[i] = vector.data[i];
return *this;
}
private:
int size;
int* data;
}
class Vector {
public:
Vector& operator= (const Vector&
vector) {
size = vector.size;
data = vector.data;
return *this;
}
private:
int size;
int* data;
}
Operadores de inserción y extracción
•  Permiten escribir / leer en la salida / entrada
estándar
•  Hay que sobrecargar los operadores:
ostream& operator<< (ostream& os, const T& arg)
istream& operator>> (istream& is, T& arg)
•  Podemos hacer que estos métodos sean amigos
de nuestra clase o implementar un método
público que imprima los datos
Operadores de inserción y extracción
class Complejo {
public:
void printComplejo(ostream & os);
…
private:
double real;
double imag;
}
ostream& operator<< (ostream& os,
const Complejo& c) {
c.printComplejo(os);
return os;
}
class Complejo {
public:
friend ostream& operator<<
(ostream& os, const Complejo& c);
…
private:
double real;
double imag;
}
ostream& operator<< (ostream& os,
const Complejo& c) {
os << c.real << …
}
Operador de Indexación
•  Es el operador []
•  Es un operador binario y de clase: recibe el
objeto donde se aplica y el índice facilitado
•  Útil, p.ej., para acceso seguro a datos:
int Vector::operator[] (int i) {
if (i >= 0 && i < this->size)
return data[i];
else {
cout << “Posición incorrecta: “ << i << endl;
return 0;
}
}
Conversión de tipos
•  Hay dos posibilidades para llevar a cabo
conversiones entre tipos definidos por el
usuario:
•  Los constructores de conversión
•  Los operadores de conversión
•  Son útiles para hacer, por ejemplo:
Complejo a (2, 3), b (0, 0);
b = a + 5;
Constructores de conversión
•  Hay que añadir un constructor que nos permita
crear el objeto a partir de un objeto del tipo que
queramos convertir
class Complejo {
public:
Complejo (double r, double i) : real(r), imag(i) {}
Complejo (int r) : real(r), imag(0) {}
Complejo operator+ (const Complejo& z2) const;
…
private:
double real, imag;
}
Complejo a (2, 3), b (0, 0);
b = a + 5;
Operadores de conversión
•  Se usan para proporcionar una conversión de un
tipo de usuario a otro tipo (de usuario o no)
•  Tiene la sintaxis:
C::operator T();
•  Donde C es el tipo de usuario que queremos
convertir y T es el tipo en el que queremos
convertir C
Operadores de conversión
class Complejo {
public:
Complejo (double r, double i) : real(r), imag(i) {}
operator double() {return real;}
Complejo operator+ (const Complejo& z2) const;
…
private:
double real, imag;
}
Complejo a (2, 3);
double b = a + 5;
double c = a.operator double() + 5;
double d = static_cast<double>(a) + 5;
Ambigüedades en la conversión
Surgen si hay varias conversiones implícitas posibles
class Complejo {
public:
Complejo (double r = 0, double i = 0)
: real(r), imag(i) {}
operator double() {return real;}
Complejo operator+ (const Complejo& z2) const;
…
private:
double real, imag;
}
Complejo a(2, 3), c(0,0);
double b = 5;
c = a + b;
El compilador no sabe si
convertir “b” a
“Complejo” y realizar
la suma o convertir
“a” a “double”, hacer
la suma y convertir el
resultado a Complejo.
Operador de llamada a función
•  Es el operador ()
•  Siempre debe ser definido dentro de una clase
•  x (y, z) se interpreta como x.operator (y, z)
•  Útil para implementar callbacks (pasar código
como argumento de una función). Los
denominados Objetos Función
•  También para el acceso a matrices
multidimensionales
Operador de llamada a función
class Inicializar {
private:
double val;
public:
Inicializar (double x = 0) : val(x) {}
void operator() (Vector& v);
};
void Inicializar::operator() (Vector& v) {
for (unsigned i = 0; i < vector.size(); i++)
v[i] = this->val;
}
int main (void) {
Vector v(5);
Inicializar ini(1);
ini(v);
}
Operador new
• 
• 
Al reservar memoria con new y new[] se invoca a las
funciones operator new y operator new[]:
void* operator new (size_t tamaño);
void* operator new[] (size_t tamaño);
• 
Estas funciones reservan y memoria y luego llaman el
constructor correspondiente
Se pueden sobrecargar para una clase C:
• 
• 
void* C::operator new (size_t tamaño);
void* C::operator new[] (size_t tamaño);
Son funciones estáticas aunque no se declaren como tal
(static), porque se invocan antes que el constructor
Primero se busca en la clase (y clases base) y luego la global
Operador new
void* Vector::operator new (size_t tam) {
reservarMemoria (tam, 0);
}
void* Vector::operator new[] (size_t tam) {
reservarMemoria (tam, 0);
}
void* Vector::reservarMemoria (size_t tam, char c) {
void* p = malloc (tam);
if (p == 0) {
cout << “Error reservando memoria.” << endl;
exit(-1);
}
memset (p, c, tam);
return p;
}
Operador delete
• 
• 
Al liberar memoria con delete y delete[] se invoca a las
funciones operator delete y operator delete[]:
void operator delete (void*);
void operator delete[] (void*);
• 
Estas funciones llaman al destructor y luego liberan la memoria
del objeto
Se puede sobrecargar para una clase C:
• 
• 
void C::operator delete (void*, [size_t]);
void C::operator delete[] (void*, [size_t]);
Son funciones estáticas aunque no se declaren como tal
(static), porque se invocan después del destructor
Primero se busca en la clase (y clases base) y luego la global
Operador delete
void Vector::operator delete (void* p, size_t tam) {
if (p)
memset (p, 0, tam);
free (p);
}
void Vector::operator delete[] (void* p, size_t tam) {
if (p)
memset (p, 0, tam);
free (p);
}
Índice
•  Sobrecarga de Funciones
•  Sobrecarga de Operadores
•  Entrada/Salida sobre streams básicos
•  Entrada/Salida sobre streams de fichero
•  Entrada/Salida sobre streams de cadena
Visión General de la E/S en C++
•  Streams y Buffers
•  Especializaciones según el tipo de operación y el
origen/destino de los datos
Clases istream y ostream
•  Derivan de la clase ios
•  Deben ser conectadas a un buffer (del tipo que
sea)
•  cin y cout son de tipo istream y ostream
•  Normalmente, para hacer E/S sobre ficheros o
cadenas se usan las clases especializadas, pero se
podrían usar estas clases básicas
•  Para usarlas: #include <iostream>
Clases istream y ostream
•  Los Manipuladores nos permiten cambiar las
opciones de formato de los streams (#include
<iomanip>)
•  Son funciones especialmente diseñadas para
trabajar junto con los operadores de inserción
(<<) y extracción (>>)
•  Se modifica el formato encadenándolos al objeto
que representa el stream
cout << hex << showbase << 20 << endl;
Clases istream y ostream
•  Manipuladores sin parámetros:
(no)boolapha: Mostrar booleanos como true y false
(no)showbase: Mostrar prefijo de tipo (0x, 0, etc.)
(no)showpoint: Forzar la escritura del punto decimal
(no)showpos: Forzar la escritura de un ‘+’ para valores positivos
(no)skipws: Permite ignorar caracteres de espaciado
(no)unitbuf: Forzar el vaciado del buffer tras cada operación
(no)uppercase: Mostrar caracteres alfabéticos en mayúsculas
dec, hex, oct: Cambiar base (decimal, hexadecimal y octal)
fixed, scientific: Usar notación de coma fija o científica
internal, left, right: Alinear el texto
endl, ends, flush: Finalizar línea, cadena y vaciar buffer
Clases istream y ostream
•  Manipuladores con parámetros
setprecision (int): Fija la precisión en coma flotante
setw (int): Fija el tamaño de un campo (que se rellena
automáticamente en caso de ser necesario)
setfill (char): Selecciona el carácter para el relleno
setbase (int): Fija la base numérica a usar (8, 10 ó 16)
setiosflags (mask): Fija cualquiera de los anteriores flags
resetiosflags (mask): Reinicia los flags a los valores por defecto
•  Otra forma de hacer lo mismo
• 
• 
Manipuladores sin parámetros: métodos setf y unsetf
Manipuladores con parámetros: métodos propios (fill, width,
precision, etc.)
Clases istream y ostream
•  Ejemplos
cout << fixed << setprecision(5) << setw(10)
<< setfill(‘*’) << 2.87 << endl;
cout.setf(ios::fixed);
cout.precision(5);
cout.width(10);
cout.fill(‘*’);
cout << 2.87 << endl;
•  Ambas imprimen el mismo resultado
***2.87000
Clase ostream
•  Permite hacer operaciones de escritura con y sin
formato
•  Sin formato: put y write
•  Con formato: operator<<
•  Permite manejar distintas situaciones de error
•  También se puede posicionar el puntero de
escritura en posiciones determinadas del flujo de
salida
Clase ostream
•  La sobrecarga del operador de inserción permite
realizar escritura con formato
•  Se puede sobrecargar para cualquier tipo
ostream& operator<< (ostream& os, const T& data)
•  Y usar los manipuladores vistos anteriormente
Clase ostream
•  El método put permite escribir un carácter en el
stream
ostream& put (char ch)
•  El método write permite escribir n caracteres de
un array en el stream
ostream& write (const char* pch, int n)
•  El método flush fuerza el vaciado del buffer
asociado al stream
ostream& flush ()
Clase ostream
•  El método tellp permite obtener la posición en
el stream de salida (principalmente ficheros)
pos_type tellp ()
•  Los métodos seekp permiten cambiar la posición
de escritura en relación a la posición actual…
ostream& seekp (pos_type pos)
•  …o en relación a una posición de referencia
ostream& seekp (off_type des, ios_base::seekdir pos)
Clase ostream
•  Ejemplos:
const char* cadena = “Hola mundo”;
cout << cadena << endl;
cout.write (cadena, 10);
cout.write (“\n”, 1);
cout.flush ();
for (unsigned i = 0; i < 10; i++)
cout.put (cadena[i]);
cout.put (‘\n’);
cout.flush ();
Clase istream
•  Permite realizar operaciones de lectura con y sin
formato:
•  Sin formato: get, getline, read, ignore, peek,
gcount, unget, putback
•  Con formato: operator>>
•  Al igual que la clase ostream, permite gestionar
errores y reposicionar el puntero de lectura
Clase istream
•  La sobrecarga del operador de extracción
permite realizar lectura con formato
•  Se puede sobrecargar para cualquier tipo
istream& operator>> (istream& is, T& data)
•  Y usar los manipuladores vistos anteriormente
(aunque algunos pueden tener sentido
únicamente para la clase ostream)
Clase istream
•  El método get permite leer un carácter del
stream:
istream& get (char& ch)
•  El método getline permite leer una línea, con una
longitud máxima hasta encontrar un delimitador
istream& getline (char* ch, int n, char delim = “\n”)
•  El método read permite leer n caracteres
istream& read (char* ch, int n)
Clase istream
•  El método ignore extrae y descarta una cadena
de hasta n caracteres, mientras no encuentre un
delimitador dado
istream& ignore (int n = 1, int delim = eof ())
•  El método peek devuelve el siguiente carácter
del stream sin extraerlo
int peek () const
Clase istream
•  El método gcount devuelve el número de
caracteres leídos en la última extracción sin
formato
int gcount () const
•  El método unget devuelve el último carácter
extraído al stream
istream& unget ()
•  El método putback devuelve c al stream
istream& putback (char c)
Clase istream
•  El método tellg permite obtener la posición en el
stream de entrada (principalmente ficheros)
pos_type tellg ()
•  Los métodos seekg permiten cambiar la posición
de lectura en relación a la posición actual…
istream& seekg (pos_type pos)
•  …o en relación a una posición de referencia
istream& seekg (off_type des, ios_base::seekdir pos)
Clase istream
•  Ejemplos
char c, cad [100], cad2[10];
cin >> cad;
// Introducimos por teclado Hola mundo cin.get(c);
// cad = Hola , c= cin.getline (cad, 100, \n );
// cad= mundo cin.read (cad2, 10); // Introducimos por teclado
// Hola mundo cruel.Adios cout << cin.gcount() << endl; // cad2= Hola mundo . Imprime 10
cin.ignore (10, '.');
// Ignora cruel. cin.putback('!');
// Inserta ! en el stream
cin >> cad;
// cad= !Adios! Clase iostream
•  Clase derivada tanto de istream como de ostream
•  Proporciona acceso de lectura/escritura a
streams
•  Presenta los mismos métodos que las clases de
las que deriva
Gestión de errores
•  Los streams manejan 4 bits de error:
• 
• 
• 
• 
eofbit: Se alcanzó el final del fichero en una operación de E/S
failbit: El método de E/S falló
badbit: Hubo un problema con el stream al realizar la
operación
goodbit: Ninguno de los anteriores bits está activado
•  Los métodos eof, fail, bad y good devuelven el
valor de estos bits
Índice
•  Sobrecarga de Funciones
•  Sobrecarga de Operadores
•  Entrada/Salida sobre streams básicos
•  Entrada/Salida sobre streams de
fichero
•  Entrada/Salida sobre streams de cadena
E/S sobre streams de fichero
•  Proporcionada por el fichero de cabecera:
#include <fstream>
•  Provee de las clases ofstream (salida), ifstream
(entrada) y fstream (entrada/salida)
•  Distintos modos para abrir un fichero:
ios::in, ios::out, ios::trunc, ios::app, ios::binary, ios::ate
•  El fichero se puede abrir en el constructor o con
el método open
Métodos de apoyo
•  El método eof indica si se alcanzó el final del
fichero:
bool eof () const
•  El método is_open indica si existe un fichero
abierto asociado con el stream
bool is_open () const
•  El método close cierra el fichero abierto y lo
desliga del stream
bool close () Clase ofstream
•  Clase derivada de ostream especializada en
realizar escrituras sobre ficheros
•  El fichero se puede abrir al construir un objeto
de tipo ofstream o con el método open
ofstream (const char* nombre_fichero,
ios_base::openmode modo = ios::out | ios::trunc)
void open (const char* nombre_fichero,
ios_base::openmode modo = ios::out | ios::trunc)
Clase ofstream
•  Ejemplo:
ofstream of ( fichero.txt");
of.write ("Hola mundo\n", 11);
of << "Adios mundo" << endl;
for (char c = 'a'; c <= 'z'; c++) {
of.put(c);
of << ", ";
}
of << endl;
of.close();
Clase ifstream
•  Clase derivada de istream especializada en
realizar lecturas desde ficheros
•  El fichero se puede abrir al construir un objeto
de tipo ifstream o con el método open
ifstream (const char* nombre_fichero,
ios_base::openmode modo = ios::in)
void open (const char* nombre_fichero,
ios_base::openmode modo = ios::in)
Clase ifstream
•  Ejemplo:
ifstream f ( fichero.txt");
char buffer[100];
f.getline (buffer, 100);
cout << buffer << endl;
f.ignore(100, '\n');
for (unsigned i = 1; i <= 26; i++) {
char c;
f >> c;
cout << c << endl;
f.ignore(2, ',');
}
Clase fstream
•  Combina las funcionalidades de ifstream y
ofstream
•  El fichero se puede abrir al construir un objeto
de tipo fstream o con el método open
fstream (const char* nombre_fichero,
ios_base::openmode modo = ios::in | ios::out)
void open (const char* nombre_fichero,
ios_base::openmode modo = ios::in | ios::out)
E/S usando Registros
•  Podemos escribir estructuras de datos complejas
•  Los datos se guardan en formato binario, en
lugar de escribirse carácter a carácter
•  Podemos hacerlo con los métodos read y write
•  Requiere una conversión de la estructura en un
array de caracteres
•  Uso de reinterpret_cast<char*>()
E/S usando Registros
struct nodo_agenda {
char nombre[30];
char direccion[40];
long telefono;
};
nodo_agenda persona;
cin.getline (30, persona.nombre);
cin.getline (40, persona.direccion);
cin >> persona.telefono;
ofstream ofs (“agenda”);
ofs.write (reinterpret_cast<char*>(&persona), sizeof(nodo_agenda));
ofs.close ();
Índice
•  Sobrecarga de Funciones
•  Sobrecarga de Operadores
•  Entrada/Salida sobre streams básicos
•  Entrada/Salida sobre streams de fichero
•  Entrada/Salida sobre streams de
cadena
La clase String
•  Clase que sirve para trabajar con cadenas de
caracteres
•  También almacena el tamaño de la cadena
•  Gestiona automáticamente la memoria dinámica
asociada a la cadena
•  Facilita las operaciones más habituales con
cadenas de caracteres
•  Hace falta incluir el siguiente fichero de
cabecera: #include <string>
La clase String
•  Cómo construimos un objeto de tipo string:
string cad1;
// Construye una cadena vacía
string cad2 (cad1);
// Constructor de copia
char arr[] = “Hola mundo”);
string cad3 (arr);
// Constructor a partir de un array de char
•  Podemos consultar el tamaño de una cadena:
cout << “El tamano de cad1 es: “ << cad1.size() << endl;
•  Podemos acceder carácter a carácter:
for (unsigned i = 0; i < cad1.size(); i++)
cout << cad1[i];
La clase String
•  Podemos asignar cadenas sin miedo (la memoria
la gestiona la propia clase):
string cad1 = “Hola mundo”;
string cad2 = “Adios mundo”;
cad2 = cad1;
•  Si nos interesa, podemos recuperar el array de
caracteres asociado al objeto string
string cad1 = “abcdefgh”;
const char* arr1 = cad1.c_str(); // Sí añade ‘\0’
const char* arr2 = cad1.data(); // No añade ‘\0’
char buffer[80];
cad1.copy (buffer, cad1.size(), 0);
La clase String
•  También podemos realizar las operaciones de
comparación habituales: ==, !=, <, >, <= y >=
•  Se comparan letra por letra y se usa el orden
alfabético
string str1 = “abcdefg”, str2 = “Abcdefg”;
if (str1 < str2)
cout << str1 << endl;
else
cout << str2 << endl;
La clase String
•  Se pueden insertar caracteres en una cadena:
string cad = “Hola”;
cad += “ mundo”;
// Añade “ mundo” al final
cad.append (“ cruel”); // Añade “ cruel” al final
cad.insert (11, “nada “); // Inserta “nada “ en la posición 11
cout << cad << endl; // Imprime “Hola mundo nada cruel”;
•  Y concatenar dos cadenas:
string cad1 = “Hola”;
string cad2 = “ mundo”;
string cad3 = cad1 + cad2;
cout << cad3 << endl;
// Imprime “Hola mundo”
La clase String
•  También podemos buscar subcadenas:
int pos;
string cad = “abcdefghijk”;
pos = cad.find (“efg”); // pos = 4
pos = cad.find (“i”); // pos = 8
•  Reemplazar subcadenas:
cad.replace (cad.find (“efg”), 2, “ zyx ”); // cad = “abcd zyx ghijk”
•  Y extraer subcadenas:
string cad1 = “Esto es una cadena”;
string cad2 = cad1.substr (12, 6); // cad2 = “cadena”
Entrada/Salida sobre streams de cadena
•  Proporcionada por el fichero de cabecera:
#include <sstream>
•  Provee de las clases ostringstream (salida),
istringstream (entrada) y stringstream (e/s)
•  Permite realizar operaciones de E/S sobre
objetos de tipo string (parecido al sprintf de C)
•  Se pueden usar los métodos de las clases básicas
istream, ostream y stream (respectivamente)
Entrada/Salida sobre streams de cadena
•  Definen dos métodos adicionales:
string str ( ) const
void str (const string & s)
•  Permiten recuperar e inicializar la cadena
asociada al stream
•  También se les puede asociar una cadena en el
constructor
istringstream (const string& str,
ios_base::openmode modo = ios_base::in)
Ejemplo con ostringstream
ostringstream buffer;
string nombre = "Antonio";
int edad = 27;
char aficion[] = "leer";
buffer << "Hola. Me llamo " << nombre << ", tengo " << edad
<< " tacos y me gusta " << aficion << endl;
cout << buffer.str() << endl;
Ejemplo con istringstream
string nombre2;
int edad2 = 0;
char aficion2[80];
istringstream buffer2 ("Antonio , 27 , leer");
buffer2 >> nombre2; // nombre2 = Antonio buffer2.ignore(100, ','); // Descartamos la ,
buffer2 >> edad2;
// edad2 = 27
buffer2.ignore(100, ','); // Descartamos la ,
buffer2 >> aficion2;
// aficion2 = leer 
Descargar