12.07.2015 Views

Sobrecarga de Operadores y E/S en C++

Sobrecarga de Operadores y E/S en C++

Sobrecarga de Operadores y E/S en C++

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Sobrecarga</strong> <strong>de</strong> <strong>Operadores</strong> yE/S <strong>en</strong> <strong>C++</strong> Antonio LaTorre <strong>de</strong> la Fu<strong>en</strong>te


Índice • <strong>Sobrecarga</strong> <strong>de</strong> Funciones • <strong>Sobrecarga</strong> <strong>de</strong> <strong>Operadores</strong> • Entrada/Salida sobre streams básicos • Entrada/Salida sobre streams <strong>de</strong> fichero • Entrada/Salida sobre streams <strong>de</strong> ca<strong>de</strong>na


<strong>Sobrecarga</strong> <strong>de</strong> Funciones • Nuevo con respecto a C • Funciones con el mismo nombre pero distintoprototipo: número y/o tipo <strong>de</strong> argum<strong>en</strong>tos • Útil si se quiere po<strong>de</strong>r realizar una mismaoperación sobre distintos tipos <strong>de</strong> datos


<strong>Sobrecarga</strong> <strong>de</strong> Funciones void print (double number) {cout


Ambigüedad • ¿Qué pasa si incluimos <strong>en</strong> nuestro código…? unsigned num = 3; print (num); • El compilador no sabe a qué función llamar: func_over.cc:18: error: call of overloa<strong>de</strong>d print(unsigned int&) is ambiguous func_over.cc:6: note: candidates are: void print(int) func_over.cc:7: note:func_over.cc:8: note:void print(int, std::string) void print(double)


Ambigüedad • Se soluciona usando static_cast unsigned num = 3; print (static_cast(num)); • ¿Qué pasaría si hiciéramos…? int num = 3; print (num);


Name Mangling • Estrategia que usa el compilador para po<strong>de</strong>rdifer<strong>en</strong>ciar 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 <strong>en</strong>: int __f_v (void) {return 1;} int __f_i (int) {return 0;} void __g_v (void) {int i = __f_v (), j = __f_i (0);}


<strong>Operadores</strong> <strong>en</strong> <strong>C++</strong>• Lista <strong>de</strong> operadores válidos <strong>en</strong> <strong>C++</strong> + - * / % ^ & |~ ! , = < > =++ -- > == != && ||+= -= *= /= %= ^= &= |== [] () -> ->* new <strong>de</strong>lete• Se <strong>de</strong>claran <strong>de</strong> la sigui<strong>en</strong>te forma: tipo operator operador([argum<strong>en</strong>tos])


<strong>Operadores</strong> <strong>en</strong> <strong>C++</strong>• Hay algunos operadores especiales que nopue<strong>de</strong>n ser sobrecargados • :: (resolución <strong>de</strong> ámbito) • . (selección <strong>de</strong> un miembro) • .* (selección <strong>de</strong> un miembro refer<strong>en</strong>ciado por un puntero) • ?: (operador condicional) • sizeof (tamaño <strong>de</strong>) • typeid (i<strong>de</strong>ntificación <strong>de</strong>l tipo)


Prece<strong>de</strong>ncia <strong>de</strong> <strong>Operadores</strong>• Los operadores <strong>en</strong> <strong>C++</strong> ti<strong>en</strong><strong>en</strong> distintaprece<strong>de</strong>ncia, y a veces no es obvio • Lo mejor es usar () <strong>en</strong> casa <strong>de</strong> no estar seguro • Tabla <strong>de</strong> prece<strong>de</strong>ncias: Inglés: http://www.cplusplus.com/doc/tutorial/operators/ Español: http://es.wikipedia.org/wiki/<strong>Operadores</strong>_<strong>en</strong>_C_y_C%2B%2B


<strong>Sobrecarga</strong> <strong>de</strong> operadores• Po<strong>de</strong>mos sobrecargar tanto operadores unarioscomo binarios tipo_ret operator op_unario (tipo1 arg1); tipo_ret operator op_binario (tipo1 arg1, tipo2 arg2); • En este caso, ambos argum<strong>en</strong>tos se muestran <strong>de</strong>manera explícita


<strong>Sobrecarga</strong> <strong>de</strong> operadores• Ambas notaciones son equival<strong>en</strong>tes C operator- (C n) {…} C operator- (C n, C m) {…} int main (void) { } C a, b, c, d;c = -b;d = b – a; int main (void) { } C a, b, c, d;c = operator- (b);d = operator- (b, a);


<strong>Sobrecarga</strong> <strong>de</strong> operadores• Si los operadores son métodos <strong>de</strong> una clase, uno<strong>de</strong> los argum<strong>en</strong>tos es implícito (aquél que invocaal operador) class C { } public: C operator- ();C operator- (C);


<strong>Sobrecarga</strong> <strong>de</strong> operadores• Estas dos notaciones son equival<strong>en</strong>tes int main (void) { C a, b, c, d; c = -b; d = b – a; } int main (void) { C a, b, c, d; c = b.operator-(); d = b.operator-(a); }


<strong>Sobrecarga</strong> <strong>de</strong> operadores• Ejemplo: Números Complejos class Complejo { } public:Complejo (double r, double i) : real(r), imag(i) {}… private:double real;double imag;


<strong>Operadores</strong> Aritméticos• Suma <strong>de</strong> 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;


<strong>Operadores</strong> Relacionales• Comparación <strong>de</strong> números complejos: bool Complejo::operator== (const Complejo& z2) const { } return this->real == z2.real && this->imag == z2.imag;


<strong>Operadores</strong> <strong>de</strong> auto-increm<strong>en</strong>to• Son operadores unarios • Permit<strong>en</strong> pre-increm<strong>en</strong>tar y post-increm<strong>en</strong>tar elvalor <strong>de</strong> una variable Pre-increm<strong>en</strong>to:C C::operator++() Post-increm<strong>en</strong>to: C C::operator++(int x) Complejo Complejo::operator++() { } real += 1;return *this;


Funciones “Amigas”• Son funciones aj<strong>en</strong>as a una clase que pue<strong>de</strong>nacce<strong>de</strong>r a los elem<strong>en</strong>tos privados <strong>de</strong> esa clase • Ejemplo: • T<strong>en</strong>emos dos clases: Vector y Matriz • Queremos <strong>de</strong>finir el producto vectorial <strong>en</strong>treambas clases • El cont<strong>en</strong>ido <strong>de</strong> los objetos es privado


Funciones “Amigas”class Vector { fri<strong>en</strong>d operator* (const Matriz&matriz, const Vector& vector); } public: … private:int size;int* data; class Matriz { fri<strong>en</strong>d operator* (const Matriz&matriz, const Vector& vector); } public: … private:int rows, columns;int** data; Vector operator* (const Matriz& matriz, const Vector& vector) {…}


<strong>Operadores</strong> <strong>de</strong> asignación• Se sobrecargan para evitar la copia binaria <strong>de</strong>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;


<strong>Operadores</strong> <strong>de</strong> inserción y extracción• Permit<strong>en</strong> escribir / leer <strong>en</strong> la salida / <strong>en</strong>tradaestándar • Hay que sobrecargar los operadores: ostream& operator> (istream& is, T& arg) • Po<strong>de</strong>mos hacer que estos métodos sean amigos<strong>de</strong> nuestra clase o implem<strong>en</strong>tar un métodopúblico que imprima los datos


<strong>Operadores</strong> <strong>de</strong> inserción y extracciónclass Complejo { } public:void printComplejo(ostream & os);… private:double real;double imag; ostream& operator


Operador <strong>de</strong> In<strong>de</strong>xación• Es el operador [] • Es un operador binario y <strong>de</strong> clase: recibe elobjeto don<strong>de</strong> 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


Conversión <strong>de</strong> tipos• Hay dos posibilida<strong>de</strong>s para llevar a caboconversiones <strong>en</strong>tre tipos <strong>de</strong>finidos por elusuario: • Los constructores <strong>de</strong> conversión • Los operadores <strong>de</strong> conversión • Son útiles para hacer, por ejemplo: Complejo a (2, 3), b (0, 0); b = a + 5;


Constructores <strong>de</strong> conversión• Hay que añadir un constructor que nos permitacrear el objeto a partir <strong>de</strong> un objeto <strong>de</strong>l tipo quequeramos 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;


<strong>Operadores</strong> <strong>de</strong> conversión• Se usan para proporcionar una conversión <strong>de</strong> untipo <strong>de</strong> usuario a otro tipo (<strong>de</strong> usuario o no) • Ti<strong>en</strong>e la sintaxis: C::operator T(); • Don<strong>de</strong> C es el tipo <strong>de</strong> usuario que queremosconvertir y T es el tipo <strong>en</strong> el que queremosconvertir C


<strong>Operadores</strong> <strong>de</strong> conversiónclass 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(a) + 5;


Ambigüeda<strong>de</strong>s <strong>en</strong> la conversiónSurg<strong>en</strong> 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 siconvertir “b” a“Complejo” y realizarla suma o convertir“a” a “double”, hacerla suma y convertir elresultado a Complejo.


Operador <strong>de</strong> llamada a función• Es el operador () • Siempre <strong>de</strong>be ser <strong>de</strong>finido <strong>de</strong>ntro <strong>de</strong> una clase • x (y, z) se interpreta como x.operator (y, z) • Útil para implem<strong>en</strong>tar callbacks (pasar códigocomo argum<strong>en</strong>to <strong>de</strong> una función). Los<strong>de</strong>nominados Objetos Función • También para el acceso a matricesmultidim<strong>en</strong>sionales


Operador <strong>de</strong> llamada a funciónclass 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 lasfunciones 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 elconstructor correspondi<strong>en</strong>te • Se pue<strong>de</strong>n 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 <strong>de</strong>clar<strong>en</strong> como tal(static), porque se invocan antes que el constructor • Primero se busca <strong>en</strong> la clase (y clases base) y luego la global


Operador newvoid* 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


Operador <strong>de</strong>lete• Al liberar memoria con <strong>de</strong>lete y <strong>de</strong>lete[] se invoca a lasfunciones operator <strong>de</strong>lete y operator <strong>de</strong>lete[]: void operator <strong>de</strong>lete (void*); void operator <strong>de</strong>lete[] (void*); • Estas funciones llaman al <strong>de</strong>structor y luego liberan la memoria<strong>de</strong>l objeto • Se pue<strong>de</strong> sobrecargar para una clase C: void C::operator <strong>de</strong>lete (void*, [size_t]); void C::operator <strong>de</strong>lete[] (void*, [size_t]); • Son funciones estáticas aunque no se <strong>de</strong>clar<strong>en</strong> como tal(static), porque se invocan <strong>de</strong>spués <strong>de</strong>l <strong>de</strong>structor • Primero se busca <strong>en</strong> la clase (y clases base) y luego la global


Operador <strong>de</strong>letevoid Vector::operator <strong>de</strong>lete (void* p, size_t tam) { if (p) memset (p, 0, tam); free (p); } void Vector::operator <strong>de</strong>lete[] (void* p, size_t tam) { if (p) memset (p, 0, tam); free (p); }


Índice • <strong>Sobrecarga</strong> <strong>de</strong> Funciones • <strong>Sobrecarga</strong> <strong>de</strong> <strong>Operadores</strong> • Entrada/Salida sobre streams básicos • Entrada/Salida sobre streams <strong>de</strong> fichero • Entrada/Salida sobre streams <strong>de</strong> ca<strong>de</strong>na


Visión G<strong>en</strong>eral <strong>de</strong> la E/S <strong>en</strong> <strong>C++</strong>• Streams y Buffers • Especializaciones según el tipo <strong>de</strong> operación y elorig<strong>en</strong>/<strong>de</strong>stino <strong>de</strong> los datos


Clases istream y ostream• Derivan <strong>de</strong> la clase ios • Deb<strong>en</strong> ser conectadas a un buffer (<strong>de</strong>l tipo quesea) • cin y cout son <strong>de</strong> tipo istream y ostream • Normalm<strong>en</strong>te, para hacer E/S sobre ficheros oca<strong>de</strong>nas se usan las clases especializadas, pero sepodrían usar estas clases básicas • Para usarlas: #inclu<strong>de</strong>


Clases istream y ostream• Los Manipuladores nos permit<strong>en</strong> cambiar lasopciones <strong>de</strong> formato <strong>de</strong> los streams (#inclu<strong>de</strong>) • Son funciones especialm<strong>en</strong>te diseñadas paratrabajar junto con los operadores <strong>de</strong> inserción() • Se modifica el formato <strong>en</strong>ca<strong>de</strong>nándolos al objetoque repres<strong>en</strong>ta el stream cout


Clases istream y ostream• Manipuladores sin parámetros:(no)boolapha: Mostrar booleanos como true y false(no)showbase: Mostrar prefijo <strong>de</strong> tipo (0x, 0, etc.)(no)showpoint: Forzar la escritura <strong>de</strong>l punto <strong>de</strong>cimal(no)showpos: Forzar la escritura <strong>de</strong> un ‘+’ para valores positivos(no)skipws: Permite ignorar caracteres <strong>de</strong> espaciado(no)unitbuf: Forzar el vaciado <strong>de</strong>l buffer tras cada operación(no)uppercase: Mostrar caracteres alfabéticos <strong>en</strong> mayúsculas<strong>de</strong>c, hex, oct: Cambiar base (<strong>de</strong>cimal, hexa<strong>de</strong>cimal y octal)fixed, sci<strong>en</strong>tific: Usar notación <strong>de</strong> coma fija o ci<strong>en</strong>tíficainternal, left, right: Alinear el texto<strong>en</strong>dl, <strong>en</strong>ds, flush: Finalizar línea, ca<strong>de</strong>na y vaciar buffer


Clases istream y ostream• Manipuladores con parámetrossetprecision (int): Fija la precisión <strong>en</strong> coma flotantesetw (int): Fija el tamaño <strong>de</strong> un campo (que se rell<strong>en</strong>aautomáticam<strong>en</strong>te <strong>en</strong> caso <strong>de</strong> ser necesario)setfill (char): Selecciona el carácter para el rell<strong>en</strong>osetbase (int): Fija la base numérica a usar (8, 10 ó 16)setiosflags (mask): Fija cualquiera <strong>de</strong> los anteriores flagsresetiosflags (mask): Reinicia los flags a los valores por <strong>de</strong>fecto• Otra forma <strong>de</strong> 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


Clase ostream• Permite hacer operaciones <strong>de</strong> escritura con y sinformato • Sin formato: put y write • Con formato: operator


Clase ostream• La sobrecarga <strong>de</strong>l operador <strong>de</strong> inserción permiterealizar escritura con formato • Se pue<strong>de</strong> sobrecargar para cualquier tipo ostream& operator


Clase ostream• El método put permite escribir un carácter <strong>en</strong> elstream ostream& put (char ch) • El método write permite escribir n caracteres <strong>de</strong>un array <strong>en</strong> el stream ostream& write (const char* pch, int n) • El método flush fuerza el vaciado <strong>de</strong>l bufferasociado al stream ostream& flush ()


Clase ostream• El método tellp permite obt<strong>en</strong>er la posición <strong>en</strong>el stream <strong>de</strong> salida (principalm<strong>en</strong>te ficheros) pos_type tellp () • Los métodos seekp permit<strong>en</strong> cambiar la posición<strong>de</strong> escritura <strong>en</strong> relación a la posición actual… ostream& seekp (pos_type pos) • …o <strong>en</strong> relación a una posición <strong>de</strong> refer<strong>en</strong>cia ostream& seekp (off_type <strong>de</strong>s, ios_base::seekdir pos)


Clase ostream• Ejemplos: const char* ca<strong>de</strong>na = “Hola mundo”; cout


Clase istream• Permite realizar operaciones <strong>de</strong> lectura con y sinformato: • Sin formato: get, getline, read, ignore, peek,gcount, unget, putback • Con formato: operator>> • Al igual que la clase ostream, permite gestionarerrores y reposicionar el puntero <strong>de</strong> lectura


Clase istream• La sobrecarga <strong>de</strong>l operador <strong>de</strong> extracciónpermite realizar lectura con formato • Se pue<strong>de</strong> sobrecargar para cualquier tipo istream& operator>> (istream& is, T& data) • Y usar los manipuladores vistos anteriorm<strong>en</strong>te(aunque algunos pue<strong>de</strong>n t<strong>en</strong>er s<strong>en</strong>tidoúnicam<strong>en</strong>te para la clase ostream)


Clase istream• El método get permite leer un carácter <strong>de</strong>lstream: istream& get (char& ch) • El método getline permite leer una línea, con unalongitud máxima hasta <strong>en</strong>contrar un <strong>de</strong>limitador istream& getline (char* ch, int n, char <strong>de</strong>lim = “\n”) • El método read permite leer n caracteres istream& read (char* ch, int n)


Clase istream• El método ignore extrae y <strong>de</strong>scarta una ca<strong>de</strong>na<strong>de</strong> hasta n caracteres, mi<strong>en</strong>tras no <strong>en</strong>cu<strong>en</strong>tre un<strong>de</strong>limitador dado istream& ignore (int n = 1, int <strong>de</strong>lim = eof ()) • El método peek <strong>de</strong>vuelve el sigui<strong>en</strong>te carácter<strong>de</strong>l stream sin extraerlo int peek () const


Clase istream• El método gcount <strong>de</strong>vuelve el número <strong>de</strong>caracteres leídos <strong>en</strong> la última extracción sinformato int gcount () const • El método unget <strong>de</strong>vuelve el último carácterextraído al stream istream& unget () • El método putback <strong>de</strong>vuelve c al stream istream& putback (char c)


Clase istream• El método tellg permite obt<strong>en</strong>er la posición <strong>en</strong> elstream <strong>de</strong> <strong>en</strong>trada (principalm<strong>en</strong>te ficheros) pos_type tellg () • Los métodos seekg permit<strong>en</strong> cambiar la posición<strong>de</strong> lectura <strong>en</strong> relación a la posición actual… istream& seekg (pos_type pos) • …o <strong>en</strong> relación a una posición <strong>de</strong> refer<strong>en</strong>cia istream& seekg (off_type <strong>de</strong>s, 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 cad; // cad=!Adios!


Clase iostream• Clase <strong>de</strong>rivada tanto <strong>de</strong> istream como <strong>de</strong> ostream • Proporciona acceso <strong>de</strong> lectura/escritura astreams • Pres<strong>en</strong>ta los mismos métodos que las clases <strong>de</strong>las que <strong>de</strong>riva


Gestión <strong>de</strong> errores• Los streams manejan 4 bits <strong>de</strong> error: • eofbit: Se alcanzó el final <strong>de</strong>l fichero <strong>en</strong> una operación <strong>de</strong> E/S • failbit: El método <strong>de</strong> E/S falló • badbit: Hubo un problema con el stream al realizar laoperación • goodbit: Ninguno <strong>de</strong> los anteriores bits está activado • Los métodos eof, fail, bad y good <strong>de</strong>vuelv<strong>en</strong> elvalor <strong>de</strong> estos bits


Índice • <strong>Sobrecarga</strong> <strong>de</strong> Funciones • <strong>Sobrecarga</strong> <strong>de</strong> <strong>Operadores</strong> • Entrada/Salida sobre streams básicos • Entrada/Salida sobre streams <strong>de</strong>fichero • Entrada/Salida sobre streams <strong>de</strong> ca<strong>de</strong>na


E/S sobre streams <strong>de</strong> fichero• Proporcionada por el fichero <strong>de</strong> cabecera:#inclu<strong>de</strong> • Provee <strong>de</strong> las clases ofstream (salida), ifstream(<strong>en</strong>trada) y fstream (<strong>en</strong>trada/salida) • Distintos modos para abrir un fichero: ios::in, ios::out, ios::trunc, ios::app, ios::binary, ios::ate • El fichero se pue<strong>de</strong> abrir <strong>en</strong> el constructor o conel método op<strong>en</strong>


Métodos <strong>de</strong> apoyo• El método eof indica si se alcanzó el final <strong>de</strong>lfichero: bool eof () const • El método is_op<strong>en</strong> indica si existe un ficheroabierto asociado con el stream bool is_op<strong>en</strong> () const • El método close cierra el fichero abierto y lo<strong>de</strong>sliga <strong>de</strong>l stream bool close ()


Clase ofstream• Clase <strong>de</strong>rivada <strong>de</strong> ostream especializada <strong>en</strong>realizar escrituras sobre ficheros • El fichero se pue<strong>de</strong> abrir al construir un objeto<strong>de</strong> tipo ofstream o con el método op<strong>en</strong> ofstream (const char* nombre_fichero,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios::out | ios::trunc) void op<strong>en</strong> (const char* nombre_fichero,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios::out | ios::trunc)


Clase ofstream• Ejemplo: ofstream of (fichero.txt"); of.write ("Hola mundo\n", 11); of


Clase ifstream• Clase <strong>de</strong>rivada <strong>de</strong> istream especializada <strong>en</strong>realizar lecturas <strong>de</strong>s<strong>de</strong> ficheros • El fichero se pue<strong>de</strong> abrir al construir un objeto<strong>de</strong> tipo ifstream o con el método op<strong>en</strong> ifstream (const char* nombre_fichero,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios::in) void op<strong>en</strong> (const char* nombre_fichero,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios::in)


Clase ifstream• Ejemplo: ifstream f (fichero.txt"); char buffer[100]; f.getline (buffer, 100); cout


Clase fstream• Combina las funcionalida<strong>de</strong>s <strong>de</strong> ifstream yofstream • El fichero se pue<strong>de</strong> abrir al construir un objeto<strong>de</strong> tipo fstream o con el método op<strong>en</strong> fstream (const char* nombre_fichero,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios::in | ios::out) void op<strong>en</strong> (const char* nombre_fichero,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios::in | ios::out)


E/S usando Registros• Po<strong>de</strong>mos escribir estructuras <strong>de</strong> datos complejas• Los datos se guardan <strong>en</strong> formato binario, <strong>en</strong>lugar <strong>de</strong> escribirse carácter a carácter • Po<strong>de</strong>mos hacerlo con los métodos read y write • Requiere una conversión <strong>de</strong> la estructura <strong>en</strong> unarray <strong>de</strong> caracteres • Uso <strong>de</strong> reinterpret_cast()


E/S usando Registrosstruct nodo_ag<strong>en</strong>da {char nombre[30];char direccion[40];long telefono; }; nodo_ag<strong>en</strong>da persona; cin.getline (30, persona.nombre); cin.getline (40, persona.direccion); cin >> persona.telefono; ofstream ofs (“ag<strong>en</strong>da”); ofs.write (reinterpret_cast(&persona), sizeof(nodo_ag<strong>en</strong>da)); ofs.close ();


Índice • <strong>Sobrecarga</strong> <strong>de</strong> Funciones • <strong>Sobrecarga</strong> <strong>de</strong> <strong>Operadores</strong> • Entrada/Salida sobre streams básicos • Entrada/Salida sobre streams <strong>de</strong> fichero • Entrada/Salida sobre streams <strong>de</strong>ca<strong>de</strong>na


La clase String• Clase que sirve para trabajar con ca<strong>de</strong>nas <strong>de</strong>caracteres • También almac<strong>en</strong>a el tamaño <strong>de</strong> la ca<strong>de</strong>na • Gestiona automáticam<strong>en</strong>te la memoria dinámicaasociada a la ca<strong>de</strong>na • Facilita las operaciones más habituales conca<strong>de</strong>nas <strong>de</strong> caracteres • Hace falta incluir el sigui<strong>en</strong>te fichero <strong>de</strong>cabecera: #inclu<strong>de</strong>


La clase String• Cómo construimos un objeto <strong>de</strong> tipo string: string cad1; // Construye una ca<strong>de</strong>na vacía string cad2 (cad1); // Constructor <strong>de</strong> copia char arr[] = “Hola mundo”); string cad3 (arr); // Constructor a partir <strong>de</strong> un array <strong>de</strong> char • Po<strong>de</strong>mos consultar el tamaño <strong>de</strong> una ca<strong>de</strong>na: cout


La clase String• Po<strong>de</strong>mos asignar ca<strong>de</strong>nas sin miedo (la memoriala gestiona la propia clase): string cad1 = “Hola mundo”; string cad2 = “Adios mundo”; cad2 = cad1; • Si nos interesa, po<strong>de</strong>mos recuperar el array <strong>de</strong>caracteres asociado al objeto string string cad1 = “abc<strong>de</strong>fgh”; const char* arr1 = cad1.c_str(); // Sí aña<strong>de</strong> ‘\0’ const char* arr2 = cad1.data(); // No aña<strong>de</strong> ‘\0’ char buffer[80]; cad1.copy (buffer, cad1.size(), 0);


La clase String• También po<strong>de</strong>mos realizar las operaciones <strong>de</strong>comparación habituales: ==, !=, , = • Se comparan letra por letra y se usa el or<strong>de</strong>nalfabético string str1 = “abc<strong>de</strong>fg”, str2 = “Abc<strong>de</strong>fg”; if (str1 < str2) cout


La clase String• Se pue<strong>de</strong>n insertar caracteres <strong>en</strong> una ca<strong>de</strong>na: string cad = “Hola”; cad += “ mundo”; // Aña<strong>de</strong> “ mundo” al final cad.app<strong>en</strong>d (“ cruel”); // Aña<strong>de</strong> “ cruel” al final cad.insert (11, “nada “); // Inserta “nada “ <strong>en</strong> la posición 11 cout


La clase String• También po<strong>de</strong>mos buscar subca<strong>de</strong>nas: int pos; string cad = “abc<strong>de</strong>fghijk”; pos = cad.find (“efg”); // pos = 4 pos = cad.find (“i”); // pos = 8 • Reemplazar subca<strong>de</strong>nas: cad.replace (cad.find (“efg”), 2, “ zyx ”); // cad = “abcd zyx ghijk” • Y extraer subca<strong>de</strong>nas: string cad1 = “Esto es una ca<strong>de</strong>na”; string cad2 = cad1.substr (12, 6); // cad2 = “ca<strong>de</strong>na”


Entrada/Salida sobre streams <strong>de</strong> ca<strong>de</strong>na• Proporcionada por el fichero <strong>de</strong> cabecera:#inclu<strong>de</strong> • Provee <strong>de</strong> las clases ostringstream (salida),istringstream (<strong>en</strong>trada) y stringstream (e/s) • Permite realizar operaciones <strong>de</strong> E/S sobreobjetos <strong>de</strong> tipo string (parecido al sprintf <strong>de</strong> C) • Se pue<strong>de</strong>n usar los métodos <strong>de</strong> las clases básicasistream, ostream y stream (respectivam<strong>en</strong>te)


Entrada/Salida sobre streams <strong>de</strong> ca<strong>de</strong>na• Defin<strong>en</strong> dos métodos adicionales: string str ( ) constvoid str (const string & s) • Permit<strong>en</strong> recuperar e inicializar la ca<strong>de</strong>naasociada al stream • También se les pue<strong>de</strong> asociar una ca<strong>de</strong>na <strong>en</strong> elconstructor istringstream (const string& str,ios_base::op<strong>en</strong>mo<strong>de</strong> modo = ios_base::in)


Ejemplo con ostringstreamostringstream buffer; string nombre = "Antonio"; int edad = 27; char aficion[] = "leer"; buffer


Ejemplo con istringstreamstring 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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!