Prácticas de C++ Practica Nº 11 Informática II Fundamentos de Programación Prof. Dr. Paul Bustamante Practica Nº 11 Programación en C++ Pág. 1 ÍNDICE ÍNDICE ........................................................................................................................................ 1 1. Introducción. .................................................................................................................... 1 1.1 Ejercicio 1: Agregando datos al final del Fichero................................................................1 1.2 Ejercicio 2: Acceso aleatorio de Lectura .............................................................................2 1.3 Ejercicio 3: Acceso Aleatorio de Escritura ..........................................................................3 1.4 Ejercicio 4: Escribiendo y Leyendo Objetos de disco .........................................................3 1.5 Ejercicio 5: Más Objetos al/del disco ..................................................................................5 1. Introducción. Después de haber aprendido cómo se leen y escriben los ficheros, tanto en formato binario como de texto, en esta práctica vamos a aprender cómo acceder a los ficheros de forma aleatoria y cómo escribir y leer objetos al disco. Los ejercicios 1 al 3 corresponden a un solo ejercicio, pero tiene que ser realizado en etapas. La finalidad de estos ejercicios es llegar a acceder de forma aleatoria un fichero para poder ver y cambiar sus datos. 1.1 Ejercicio 1: Agregando datos al final del Fichero. En este caso vamos a crear una aplicación que permita “agregar” datos al final del fichero, con el fin de no perder los datos anteriores. El siguiente código debe ser copiado en el fichero Ejer1.cpp del proyecto. #include <fstream.h> #include <string.h> #include <iomanip.h> void Leer(char*); //declaración de funciones void Agregar(char*); void main() { int opc; char fname[40]; cout << "File:?"; cin >> fname; strcat(fname,".dat"); while(true){ cout << "** Menu **\n1. Agregar\n2. Leer\n3. Salir\n\tOpc:?"; cin >> opc; switch(opc){ case 1: Agregar(fname); break; case 2: Leer(fname); break; case 3: return; } } } void Leer(char *fname) { char nombre[40]; int carnet,edad,curso; } //leer secuencialmente fstream fin(fname,ios::in|ios::binary); if (!fin) { cout << "Error.." << endl; return; } cout.setf(ios::left); while(1){ if(!fin.read((char*)&carnet,sizeof(int))) break; fin.read((char*)nombre,40); . . .//leer la edad y el curso, en ese orden cout<<setw(8)<<carnet<<setw(40)<<nombre<<setw(5)<<edad<<setw(5)<<curso<<endl; } fin.close(); Informática II – Fundamentos de Programación - Tecnun Practica Nº 11 Programación en C++ Pág. 2 void Agregar(char *fname) { char nombre[40]; int carnet,edad,curso; cout << "Carnet:?"; cin>>carnet; cin.ignore(); cout << "Nombre:?"; cin.getline(nombre,40); cout << "Edad:?"; cin>>edad; cout << "Curso:?"; cin>>curso; fstream fout(fname,ios::app|ios::binary); if (!fout) { cout << "error..."<<endl; return;} fout.write((char*)&carnet,sizeof(int)); . . . // Escribir en disco el nombre, la edad y el curso, en ese orden fout.close(); } Compile el programa y ejecútelo, tiene que poder agregar datos al fichero, cada vez que empiece de nuevo el programa. Además desde la opción 2 puede consultar los datos grabados. Sino logra estos objetivos, no debe pasar al siguiente ejercicio. 1.2 Ejercicio 2: Acceso aleatorio de Lectura En este ejercicio vamos a ver cómo podemos acceder de forma aleatorio a un fichero. Supongo que ya sabéis que es eso no? Sino, repasar los apuntes de clase. Para este ejercicio debéis crear un fichero nuevo Ejer2.cpp en el mismo proyecto y copiar el código del fichero Ejer1.cpp. Una vez hecho esto, podéis quitar el fichero Ejer1.cpp del proyecto. Los cambios a hacer son: • Agregar una opción más al menú: Opción 3, Buscar, la cual llamará a la función Buscar() que se encargará de abrir el fichero de forma aleatoria. • Agregar la función Buscar, cuyo código es el siguiente: int Buscar(char *fname) { int carnet, car; char nombre[40]; //acceso aleatorio de lectura cout << "Dar Carnet a buscar:?"; cin >> car; fstream fin(fname,ios::in|ios::binary); //obtener el tamaño de los registros int cont=0; int dr=3*4+40; //len de cada registro int num=0; while(!fin.eof()){ fin.seekg(cont,ios::beg); //inicio del fichero fin.read((char*)&carnet,4); //el "int" es 4 bytes if (car==carnet){ cout.setf(ios::left); fin.read(nombre,40); //leer nombre cout << setw(8) << car <<setw(40)<<nombre<< endl; // leer el resto de datos de este registro, edad y curso y // y sacarlos por pantalla. fin.close(); return num; //termina la funcion } cont+=dr; num++; } cout << "No existe el carnet..."<<endl; fin.close(); return -1; } Informática II – Fundamentos de Programación - Tecnun Practica Nº 11 Programación en C++ Pág. 3 Como puede observar, esta función devuelve la posición del registro, si lo encuentra claro, sino devuelve -1. Esto se hace con el fin de utilizarla en el siguiente ejercicio. 1.3 Ejercicio 3: Acceso Aleatorio de Escritura En este ejercicio vamos a aprender cómo cambiar los datos guardados en un fichero. Para esto el fichero se debe abrir en modo de aleatorio para escritura, usando ios::in | ios::out a la vez. Para este ejercicio debéis crear un fichero nuevo Ejer3.cpp en el mismo proyecto y copiar el código del fichero Ejer2.cpp. Una vez hecho esto, podéis quitar el fichero Ejer2.cpp del proyecto. Los cambios a hacer son: • Agregar una opción más al menú: Opción 4, Cambiar, la cual llamará a la función Cambiar() que se encargará de abrir el fichero de forma aleatoria para escritura. • Agregar la función Cambiar, cuyo código es el siguiente: void Cambiar(char *fname) //acceso aleatorio de escritura { int carnet,edad,curso; char nombre[40]; int dr=3*4+40; //len de cada registro int reg=Buscar(fname); //busca si existe cout << "Reg:"<<reg<<endl; if (reg>=0){ //nuevos datos cout << "Carnet:?"; cin>>carnet; cin.ignore(); cout << "Nombre:?"; cin.getline(nombre,40); cout << "Edad:?"; cin>>edad; cout << "Curso:?"; cin>>curso; fstream fout(fname,ios::in|ios::out|ios::binary); fout.seekp(reg*dr,ios::beg); //posicionarse desde el inicio //sobrescribir los nuevos datos fout.write((char*)&carnet,sizeof(int)); . . .//escribir el nombre, la edad y el curso, en ese orden fout.close(); } } 1.4 Ejercicio 4: Escribiendo y Leyendo Objetos de disco Ya hemos hecho bastantes ejercicios de ficheros. Como punto final a los ficheros, vamos a ver cómo se escriben los objetos en el disco (se pueden hacer en formato texto o binario). Este ejercicio consiste en hacer un programa que permita grabar los objetos tipo Fecha en formato binario. Para ello vamos a utilizar un objeto estático (tanto para lectura como para escritura), con lo cual no es necesario crear los objetos con el operador new. A continuación podemos ver el código: //Escribir y leer objetos //File Fecha.h class Fecha{ short dia,mes,anyo; public: Fecha(short d=1, short m=1, short a=99): dia(d),mes(m),anyo(a){ ; } Informática II – Fundamentos de Programación - Tecnun Practica Nº 11 Programación en C++ }; Pág. 4 friend ostream &operator<<(ostream& co, Fecha &f){ co.fill('0'); co <<setw(2)<<f.dia <<"/"<<setw(2)<<f.mes<<"/"<<f.anyo; return co; } friend fstream& operator<<( fstream& fo, Fecha &f){ fo.write( (char*)&f, sizeof(Fecha)); return fo; } friend fstream& operator>>( fstream &fi, Fecha &f){ fi.read((char*)&f,sizeof(Fecha)); return fi; } //File Ejer4.cpp #include <fstream.h> #include <iomanip.h> void Leer(char *); void Escribir(char *); void main() { char name[80]; int opc; while(1){ cout<<"\n** Objetos Fecha **\nLeer(1), Escribir(2), Salir(3):?"; cin>> opc; if (opc==3) break; else{ //pedir nombre del fichero cout << "Nombre del Fichero:?"; cin >> name; if (opc==1) Leer(name); else if(opc==2) Escribir(name); } } } void Leer(char *fname) { fstream fin(fname,ios::in|ios::nocreate|ios::binary); if (!fin) { cerr << "Error"; return;} Fecha f; cout << "Las fechas guardadas en " << fname << " son:"<<endl; while(true){ fin >> f; if (fin.eof())break; cout << f << endl; } } void Escribir(char *fname) { int d,m,a; cout << "Introd. Fecha (d m a):"; cin >> d >> m >> a; Fecha f1(d,m,a); //asignar objeto Anónimo cout << "Se va a guardar: " << f1 << endl; //escribir a disco fstream fout(fname , ios::app|ios::binary); //para agregar + fechas fout << f1; fout.close(); } Informática II – Fundamentos de Programación - Tecnun Practica Nº 11 Programación en C++ 1.5 Ejercicio 5: Más Objetos al/del disco Este ejercicio consiste en repetir el ejercicio 1 al 3 pero usando objetos. Para ello tenéis que usar la clase Alumno, que se da a continuación. El programa debe permitir Leer, Escribir, Buscar o Cambiar datos de un fichero, usando objetos de la clase Alumno, para lo cual debe sobrecargar los operadores “>>” y “<<”, tanto para hacerlo desde los ficheros como para consola y teclado (puede verlos en la definición de la clase). En el siguiente código sólo se ha implementado la opción 1 (escribir los objetos). Ud. Debe implementar el resto de opciones. #include <fstream.h> #include <string.h> class Alumno { int carnet; char nombre[40]; int edad; int curso; public: Alumno(int car=0, char*name="", int ed=0, int cur=0); //consola y teclado friend istream& operator>>( istream& ci, Alumno &al){ cout << "Carnet:?"; cin>>al.carnet; cin.ignore(); cout << "Nombre:?"; cin.getline(al.nombre,40); cout << "Edad:?"; cin>>al.edad; cout << "Curso:?"; cin>>al.curso; return ci; } friend ostream& operator<<( ostream& co, Alumno &al); // Disco friend fstream& operator<<( fstream& fo, Alumno &al){ fo.write((char*)&al, sizeof(Alumno)); return fo; } friend fstream& operator>>( fstream& fi, Alumno &al); }; //Programa Principal void main() { int opc; char fname[40]; fstream file; Alumno al; //objeto para lectura y escritura //objeto estatico para lectura cout << "File:?"; cin >> fname; strcat(fname,".dat"); while(true){ cout << "** Menu **\n1. Agregar\n2. Leer\n3. Buscar \n4. Cambiar Registros\n5. Salir\n\tOpc:?"; cin >> opc; switch(opc){ case 1: cin >> al; file.open(fname,ios::app|ios::binary); //abrir file file << al; //escribir file.close(); //cerrar file break; case 2: /*agregar código aqui*/ break; case 3: /*agregar código aqui*/ break; case 4: /*agregar código aqui*/ break; case 5: return; } } } Informática II – Fundamentos de Programación - Tecnun Pág. 5