Algoritmos y Estructura de Datos I Entrada y salida Facultad de Ciencias Exactas y Naturales Lunes 6 de octubre de 2015 (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 1/1 Menú del dı́a Streams Manipulación de archivos Ejemplos con clase STL (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 2/1 Stream Stream en inglés significa corriente o torrente. En nuestro caso, será una corriente de datos que según el caso puede representar una fuente de entrada o un destino de salida de datos del programa. Hay dos tipos principales de streams: Los input streams Los output streams (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 3/1 Tipos de streams Un input stream es aquel que se utiliza para leer datos desde una fuente. Un output stream es aquel que se utiliza para escribir datos hacia un destino. Las clases básicas de input y output streams son istream y ostream respectivamente. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 4/1 Los 3 streams estándar: std::cin, std::cout, std::cerr Los 3 streams estándar son el de entrada estándar (cin), el de salida estándar (cout) y el de error estándar (cerr). La entrada estándar es la que estuvieron usando hasta ahora: se leen los datos de entrada desde la consola. cin es un objeto de la clase istream para leer desde la entrada estándar. La salida estándar es la salida por pantalla. cout es un objeto de la clase ostream para escribir en la salida estándar. El error estándar es por donde se imprimen todas las excepciones del programa, junto con lo que nosotros queramos agregarle (errores que nosotros deseamos que se impriman por allı́). Se verá por la misma consola de la salida estándar (salvo que la redirijamos). (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 5/1 ¿Cómo utilizo un output stream? Primero nos referiremos a la salida estándar (std::cout). El operador << inserta los datos después de él en el stream que lo precede (no necesariamente tenemos que usar cout, después lo veremos). Ejemplificando, cout << 120; cout << x; cout << "Tengo " << age << " a~ nos actualmente."; (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 6/1 ¿Cómo utilizo un output stream? Primero nos referiremos a la salida estándar (std::cout). El operador << inserta los datos después de él en el stream que lo precede (no necesariamente tenemos que usar cout, después lo veremos). Ejemplificando, cout << 120; cout << x; cout << "Tengo " << age << " a~ nos actualmente."; Para terminar una lı́nea usamos std::endl. Ası́, si queremos imprimir algo y pasar a la siguiente lı́nea de la consola o el archivo, escribimos: cout << 120 << endl; cout << x << endl; cout << "Tengo " << age << " a~ nos actualmente." << endl; Este operador se llama el operador de inserción. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 6/1 ¿Cómo utilizo un output stream? De igual manera que como con cout (salida estándar), podemos imprimir por la salida de error mensajes que deseemos (que posiblemente describan la naturaleza del error). cerr << "Ojo con lo que estas haciendo" << endl; cerr << 120; cerr << x << endl; Notar que usamos el mismo operador que en el caso anterior. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 7/1 ¿Cómo utilizo un input stream? El operador >> extrae datos del stream que lo precede, y lo guarda en la variable escrita del lado derecho. Por ejemplo, int edad; cin >> edad; string nombre; cin >> nombre; Este operador se llama el operador de extracción. No necesariamente tenemos que usar la entrada y salida estándar, sino que podemos utilizar streams más generales. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 8/1 En términos más generales, podemos definir un istream (input stream) o un ostream (output stream) que funcione de manera análoga a los estándar, pero escribiendo o leyendo de donde lo decidamos. Ası́, ifstream esElInput("miArchivo.in"); ofstream esElOutput("miArchivo.out"); city.leerCiudad(esElInput); esElInput >> x; esElOutput << "Estoy escribiendo a un archivo!"; Como pueden ver, la lectura y escritura es igual a los casos anteriores, sólo que antes hay que declarar desde dónde vamos a leer o a dónde escribiremos. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 9/1 File Streams Un tipo especial de streams son los file streams. Estos son los que leen o escriben a un archivo (ifstream u ofstream según el caso), y son un caso particular de istream y ostream. Como istream es más general, utilizaremos éstos en lugar de ifstream, ya que si utilizamos ifstream estamos impidiendo que la función sea llamada con otros streams que no sean estrictamente de archivos. Análogo para ofstream. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 10 / 1 La buena práctica indica que al abrir un stream hay que checkear si esta operación fue realizada correctamente y manejarlo adecuadamente (con .is open()), ası́ como también al terminar de utilizarlo hay que cerrando haciendo .close(). Si no se efectúa esto, de todas maneras se cerrará automáticamente cuando termine el scope. ... ofstream myfile ("example.txt"); if (myfile.is_open()) { myfile << "This is a line.\n"; myfile << "This is another line.\n"; myfile.close(); } ... (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 11 / 1 Funciones Útiles Convertir un string a int: cantHabsInt = atoi(cantHabsString.c_str()); si cantHabsString es el string que queremos convertir a entero. Nota: también pueden implementarlo ustedes mismos como una función auxiliar, es un muy buen ejercicio. Leer de un stream hasta encontrar cierto caracter: Por ejemplo, si nuestra entrada es Alice-Bob y queremos leer un string que solamente contenga Alice, podemos hacer lo siguiente: getline(inputStream,stringDondeGuardo,’-’); Esto indica que se debe leer de un stream (y guardarlo en el string dado) hasta que se encuentre un char guion. Allı́ se detendrá de leer, y descartará el guion leı́do. Lo pueden utilizar con otros caracteres, como por ejemplo la coma, o el punto y coma. (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 12 / 1 Ahora bien, hasta ahora siempre sabı́amos cuánto tenı́amos que leer. ¿Qué sucede si queremos crear un ciclo que lea hasta que se terminen de leer todos los datos de dicho stream? ¿Cómo lo hacemos? Es muy útil saber que luego de leer desde un input stream, la expresión in >> x evalúa a false si se terminó de leer todo el archivo, o a true si esto no sucedió. Es por esto que simplemente podemos hacer: while( in >> var ) { ... } (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 13 / 1 Algunos ejemplos . . . (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 14 / 1 Algunos ejemplos . . . peek ignore friend (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 14 / 1 Clases - Auto #ifndef AutoH #define AutoH class Auto { public: Auto(); Auto(int patente, int motor, int modelo); int patente() const; int modelo() const; int motor() const; void tunear(int m); private: int patente; int modelo; int motor; }; #endif (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 15 / 1 #include "auto.h" Auto::Auto() { patente = 9999; modelo = 2003; motor = 1999; } Auto::Auto(int patente, int modelo, int motor) { patente = patente; modelo = modelo; motor = motor; } int Auto::patente() const { return patente; } int Auto::modelo() const { return modelo; } int Auto::motor() const { return motod; } (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 16 / 1 Clases ¿Qué pasa si hago...? Auto a1(240,13,2015); cout << a1; (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 17 / 1 Clases ¿Qué pasa si hago...? Auto a1(240,13,2015); cout << a1; error: no match for ’operator<<’ in ... (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 17 / 1 Clases Solución: Implementar el operador << para el tipo Auto. auto.h std::ostream & operator<<(std::ostream & os,const Auto & a); // os es cout/archivo, a es Auto auto.cpp std::ostream & operator<<(std::ostream & os,const Auto & b){ os << "Patente: " << b.patente() << " Motor: " << b.motor() << " Modelo: " << b.modelo(); return os; } (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 18 / 1 STL La Standard Template Library es una libreria de C++ que cuenta con diferentes estructuras y algoritmos. Estructuras básicas: pair, vector, list, queue, etc... Estructuras avanzadas: priority queue, set, map, etc... Algoritmos: sort, binary search, set intersection, etc... Clases de funciones (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 19 / 1 Listas y tuplas Nuestro lenguaje de especificación cuenta con los tipos lista, y tupla. Vamos a representar al tipo lista con la clase vector y a las duplas con pair. vector<int> listaDeEnteros vector< vector<int> > listaDeListaDeEnteros pair<Vampiro,string> duplaDeVampiroString pair< Flor , vector< pair<int, int> > > duplaFlorListaDePares (Facultad de Ciencias Exactas y Naturales) Algoritmos y Estructura de Datos I Lunes 6 de octubre de 2015 20 / 1