Archivos - Campus Virtual Ort

Preview only show first 6 pages with water mark for full document please download

Transcript

Asignatura Taller de Computación II Módulo III Archivos Elaboración Gabriel F. Stancanelli Aporte del profesor Fabian Gentile al material de este módulo. Este material pertenece a la materia Taller de Computación II de la Carrera de Analista de Sistemas de Computación de Educación a Distancia del INSTITUTO DE TECNOLOGÍA ORT. Todos los derechos reservados. No esta permitida la reproducción total o parcial de este apunte, ni su tratamiento informático, ni la transmisión de ninguna forma o por cualquier medio, ya sea electrónico, mecánico, por fotocopia, por registro u otros métodos, sin el permiso previo de los titulares. 3da edición Agosto de 2010. ver 3.0 - Yatay 240 - Bs As - República Argentina Unidad didáctica III: Archivo Pag. 1 UNIDAD DIDÁCTICA III ÍNDICE UNIDAD DIDÁCTICA III .................................................................................................................... 2 ÍNDICE ................................................................................................................................................................................................. 2 Introducción y orientaciones para el estudio............................................................................................................................ 3 Objetivos ....................................................................................................................................................................................... 3 Aclaraciones previas al estudio............................................................................................................................................. 3 Más tipos de datos ........................................................................................................................................................................... 4 Estructuras ...................................................................................................................................................................................... 4 Conversión de tipos (casts) .......................................................................................................................................................... 6 Archivos .............................................................................................................................................................................................. 8 Primero: Operaciones con archivos ............................................................................................................................................ 8 Segundo: Organización de archivos ........................................................................................................................................... 8 Tercero: Tipo de archivos ............................................................................................................................................................. 8 Cuarto: Almacenamiento en archivos ......................................................................................................................................... 9 Quinto: Modularización de las operaciones ............................................................................................................................. 16 Unidad didáctica III: Archivos Pág. 2 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Introducción y orientaciones para el estudio En el desarrollo de este módulo abordaremos: ƒ ƒ Variables del tipo Estructuras. Archivos. Objetivos Pretendemos que al finalizar de estudiar esta Unidad, el alumno logre: ƒ ƒ Poder manejar estructuras de datos. Tener un manejo básico de archivos secuenciales. Aclaraciones previas al estudio En este módulo, usted encontrará: Contenidos Conceptualizaciones centrales Bibliografía Referencia de material bibliográfico recomendado Actividades Usted debe tener presente que los contenidos presentados en el módulo no ahondan profundamente en el tema, sino que pretenden ser un recurso motivador, para que a través de la lectura del material, la bibliografía sugerida, y el desarrollo de las actividades propuestas alcance los objetivos planteados en el presente módulo. Cada módulo constituye una guía cuya finalidad es facilitar su aprendizaje. ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 3 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Más tipos de datos En este capítulo se revisa la forma como pueden ser creados y usados en C++ tipos de datos más complejos y estructuras. Estructuras En C++ una estructura es una colección de variables que se referencian bajo el mismo nombre. Una estructura proporciona un medio conveniente para mantener junta información que se relaciona. Una definición de estructura forma una plantilla que se puede usar para crear variables de estructura. Las variables que forman la estructura son llamados elementos estructurados. Generalmente, todos los elementos en la estructura están relacionados lógicamente unos con otros. Por ejemplo, se puede representar una lista de nombres de empleados en una estructura. Mediante la palabra clave struct se le indica al compilador que defina una plantilla de estructura. struct Empleado{ char sNombre[30]; int iEdad; char sDomicilio[40]; char sCiudad[20]; char cSexo; int iLegajo; }; Nota: el punto y coma “;” al finalizar la declaración de la estructura es obligatorio, ya que sino el programa no compila. Por convención del curso, le antepondremos “ty_” al nombre de la estructura, para saber que se trata de un tipo de datos. struct ty_Empleado{ char sNombre[30]; int iEdad; char sDomicilio[40]; char sCiudad[20]; char cSexo; int iLegajo; }; ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 4 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Con la porción de código anterior no ha sido declarada ninguna variable, tan sólo se ha definido el formato, con lo cual no ocupamos aún espacio en memoria. Cabe señalar que los campos de una estructura no necesariamente tienen que ser del mismo tipo de datos, observe que en nuestro ejemplo hay campos que son del tipo integer, string, char. Para declarar una variable, se hará de la siguiente manera: struct ty_Empleado tyInfo_empleado; En C++ no es necesario anteponer la palabra struct para indicar que se trata de una estructura. ty_Empleado tyInfo_empleado; Observe que la variable se declara de la misma forma en que lo veníamos realizando: primero el tipo de dato, y luego el nombre de la variable. Observar que ty_Empleado es una etiqueta para la estructura que sirve como una forma breve para futuras declaraciones. Las variables del tipo estructuras, al igual que las variables vistas anteriormente, pueden ser preinicializadas en la declaración: ty_Empleado tyInfo_empleado={"Vicente Fernandez",40,"Corrientes 348","Capital Federal","M",12345}; Recordar que los literales siempre van encerrados entre comillas dobles, por ejemplo: "Corrientes 348" Para referenciar o acceder a un miembro (o campo) de una estructura, C++ proporciona el operador punto “.”. Por ejemplo, para asignar a tyInfo_empleado otro legajo, lo hacemos como: tyInfo_empleado.iLegajo=54321; Por último, es perfectamente válida la asignación de una variable de tipo estructura a otra variable del tipo estructura, siempre que ambas sean del mismo tipo. Por ejemplo: ty_Empleado tyInfo_empleado1, tyInfo_empleado2; ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 5 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II //Dentro del programa principal. . . tyInfo_empleado1.sNombre = "JUAN"; tyInfo_empleado1.iEdad = 33; tyInfo_empleado1.sDomicilio = "MERCEDES"; tyInfo_empleado1.sCiudad = "BS.AS. "; tyInfo_empleado1.cSexo = 'M'; tyInfo_empleado1.iLegajo = 8387; // y luego realizamos la siguiente asignación. . . tyInfo_empleado2 = tyInfo_empleado1; Ahora tyInfo_empleado2 contendrá los mismos valores que tyInfo_empleado1. Actividad 3 - 1: - Declarar una estructura alumno, que contenga los campos matrícula, apellido, sexo y edad. Solicitar al operador que cargue valores por teclado y luego mostrarlos. Desarrollar el ejercicio 1 de la Unidad III que se encuentra en la biblioteca de ejercicios. Conversión de tipos (casts) C++ es uno de los pocos lenguajes que permiten la conversión de tipos, esto es, forzar una variable de un tipo a ser de otro tipo. Lo anterior se presenta cuando variables de un tipo se mezclan con las de otro tipo. Para llevar a cabo esto, se utiliza el operador de conversión (cast) (). Por ejemplo: int iNumeroentero; float fNumeroflotante = 9.87; iNumeroentero = (int) fNumeroflotante; Con lo cuál se asigna 9 a la variable iNumeroentero y la fracción es desechada. El siguiente código: int iNumeroentero = 10; float fNumeroflotante; fNumeroflotante = (float) iNumeroentero; Asigna 10.0 a fNumeroflotante. Como se observa C++ convierte el valor del lado derecho de la asignación al tipo del lado izquierdo. La conversión de tipos puede ser también usada con cualquier tipo simple de datos incluyendo char, por lo tanto: int iNumeroentero; char cLetra = 'A'; iNumeroentero = (int) cLetra; Asigna 65 (que es el código ASCII de 'A') a iNumeroentero. ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 6 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Algunas conversiones de tipos son hechas de forma automática. Esto es, principalmente, por la característica de compatibilidad de tipos. Una buena regla es la siguiente: En caso de duda, conversión de tipos. Una mejor: siempre utilizar conversión de tipos ya que aclara la legibilidad del código. Otro uso es asegurarse que la división de números se comporta como se requiere, ya que si se tienen dos enteros la forma de forzar el resultado a un número flotante es: fNumeroflotante = (float) iNumeroentero / (float) iDenomentero; Con lo que se asegura que la división devolverá un número flotante. Actividad 3 - 2: - Solicitar al usuario el ingreso por teclado de un número entero, y luego mostrarlo por pantalla como un número real. Actividad 3 - 3: - Solicitar al usuario el ingreso por teclado de letras mientras sean distintas de asterisco ' * ', y mostrar el valor ASCII de cada una de ellas. ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 7 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Archivos Si bien es cierto que ya se pueden manejar gran cantidad de datos del mismo y diferente tipo al mismo tiempo, el problema es que al terminar de ejecutarse el programa los datos se pierden. De esta situación nace el concepto de archivos que son medios que facilita el lenguaje para almacenar los datos en forma permanente. En general es necesario entender algunos conceptos elementales de sistemas de archivos tradicionales. Como nota a tomar en cuenta, los datos que se van almacenando en un archivo de disco, se almacenan en renglones consecutivos y cada renglón en disco, se conoce como registro del archivo. Por favor, no confundir el concepto de registro de archivo y registro o estructura como variable ya analizada, son dos cosas totalmente diferentes aunque desafortunadamente se llamen igual. Primero: Operaciones con archivos ABRIR Y CERRAR: Son las operaciones por las cuales el programa se conectará con y desconectará del archivo físico que contendrá los datos a grabar o recuperar. ESCRIBIR O GRABAR: Es la operación mas elemental con un archivo, consiste en tomar un o unos datos en variables de cualquier tipo (variables sueltas, arreglos, estructuras) y almacenarlas en un archivo de datos en disco. LEER: Operación que consiste en recuperar los datos del archivo en disco y mandarlos o cargar la variable respectiva, que se encuentra en memoria. Segundo: Organización de archivos En general existen dos tipos de archivos: Archivos Secuenciales.- En este caso los datos se almacenan en forma consecutiva y no es posible leer ningún registro (de un archivo, recuerdan la nota de arriba) directamente, es decir para leer el registro n se deberá recorrer o acceder los n-1 registros anteriores. Archivos Directos o Random.- Para este caso, sí se puede acceder o leer un registro n cualquiera. Tercero: Tipo de archivos En general existen tantos tipos de archivos como tipos de datos existen, es decir: El paquete Standard de input/output de "C", permite disponer de cuatro métodos o maneras diferentes de leer y escribir los datos a disco. ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 8 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Tres de ellas corresponden exactamente a lo aprendido de leer y escribir datos desde el teclado hacia la pantalla. 1.- Datos a ser grabados o leídos como un carácter a la vez, se utilizarán funciones análogas a getchar() y putchar(). 2.- Datos que pueden ser leídos o grabados como un string, se usarán funciones análogas a gets() y puts(). 3.- Datos que se capturen o desplieguen con formatos parecidos a los usados por scanf() y printf() se usarán funciones similares, es decir serán problemas que involucran mezclas de strings, caracteres, floats, etc. 4.- También se podrán leer y escribir datos de tipo arreglo (tema a tratar en la próxima unidad) y registros utilizando instrucciones apropiadas, en resumen: caracter String Formateado Registros y arreglos Leer getc() fgets() fscanf() fread() Escribir putc() fputs() fprintf() fwrite() ATENCION: Ya que se decide utilizar algún archivo específico de datos (caracteres, strings, formateados, registros o arreglos) sólo utilizar las funciones de escritura y lectura de ese tipo de archivo, por ningún motivo mezcle funciones de lectura y escritura de otro tipo de archivos. Cuarto: Almacenamiento en archivos Modo Texto: en este caso los datos son almacenados usando codificación ASCII y por lo tanto son plenamente visibles usando cualquier editor de textos como ser el edit o notepad. Modo Binario: en este caso los datos son almacenados en notación binaria (tal como se guardan en las variables en memoria) y por lo tanto se ocupa un editor binario para reconocerlos, sin embargo un archivo binario es más compacto que un archivo texto. Estos archivos también son llamados tipificados. Para Proposito De Este Curso, Entonces Nos Concentramos En Archivos De Disco De Registros O Estructuras, Secuenciales, Y Binarios. Existen Otros Tipos De Organización (Relativos, Secuenciales Indexados, Base De Datos), Que Serán Tratados Más Adelante En Otras Materias De Esta Carrera. En este capítulo se mostrará una forma de cómo pueden ser creados y leídos en C++ los archivos secuenciales tipificados (con diseño de registro). ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 9 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Para comenzar la comprensión del tema de archivos vamos a analizar el siguiente código fuente: //Incluimos las siguientes librerías para la utilización de rutinas. #include #include using namespace std; // Se define el tamaño máximo del string para el nombre #define MAXNOM 10 // Recuerde que las sentencias al preprocesador, aquellas que comienzan con #, no // llevan punto y coma “;”, ya que no son parte de C y no cumplen su sintaxis. // Se define el tipo de datos string para la variable strNombre typedef char ty_sNombre[MAXNOM]; //armamos un tipo de datos estructuras para los datos de una persona. typedef struct ty_Persona { int iEdad; char cInicial; ty_sNombre sNombre; }; //declaramos los prototipos de las funciones. void Grabar(ty_Persona p); ty_Persona Leer(); void main(){ //Se crea la variable p del tipo ty_Persona ty_Persona p; system("cls"); //Llenamos a mano el registro p.iEdad = 3; p.cInicial = 'A'; strcpy(p.sNombre, "Juan"); // Llamamos a la rutina para grabar el registro en el archivo Grabar(p); // Llamamos a la rutina que lee del archivo y se // a la variable p para luego mostrar los datos p = Leer(); lo asignamos cout << "Leído iEdad: " << p.iEdad << "\n"; cout << "Leído cInicial: " << p.cInicial << "\n"; cout << "Leído sNombre: " << p.sNombre << "\n"; getchar(); } ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 10 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II //Grabar recibe como parámetro una variable del tipo Ty_Persona void Grabar(ty_Persona dato){ //Creamos la variable ArchSal que es el nombre con el cuál referenciaremos al // archivo Siempre FILE es con mayúsculas y se coloca el asterisco “ * ” FILE * ArchSal; /* A la rutina fopen se le pasa como parámetros la ubicación del archivo y el tipo de apertura que se utilizará, en nuestro caso es de salida, quiere decir que se escribirá en el archivo, esto se lo indica con el switch “w”. Tenga en cuenta que si el archivo no existe lo crea, y en caso contrario lo sobrescribe. La “b” indica que escribiremos en el archivo en modo binario. */ ArchSal = fopen("c:\\Datos.Dat", "wb"); // La siguiente pregunta es para evaluar si se pudo o no crear el archivo if (ArchSal == NULL){ cout << "No se pudo abrir el Archivo de Salida.\n"; }else{ fwrite(&dato, sizeof(dato), 1, ArchSal); /* Parámetros de la rutina fwrite: &dato: se le pasa la estructura a grabar por dirección sizeof(dato): se le indica el largo en bytes de la estructura 1: es la cantidad de repeticiones a grabar ArchSal: en dónde lo graba */ //Cerramos el archivo puesto que no se volverá a utilizar fclose(ArchSal); } } //Esta rutina leerá del archivo y nos devolverá un registro del tipo ty_Persona ty_Persona Leer(){ ty_Persona Aux; //Creamos la variable ArchEnt que es el nombre con el cual // referenciaremos al archivo FILE * ArchEnt; // En este caso a fopen se le pasa como parámetros la ubicación del archivo // y se le indica mediante "r" que será de sólo lectura y "b" del tipo binario ArchEnt = fopen("c:\\Datos.Dat", "rb"); //Se comprueba que se pudo abrir el archivo if (ArchEnt == NULL){ cout << "No se pudo abrir el Archivo de Entrada.\n"; }else{ fread(&Aux, sizeof(Aux), 1, ArchEnt); /* Parámetros de la rutina fread: &Aux: se le pasa la estructura por dirección en donde va a dejar los datos leídos del archivo sizeof(Aux): se le indica el largo en bytes de la estructura 1: es la cantidad de repeticiones a leer ArchEnt: en donde va a leer */ //Cerramos el archivo fclose(ArchEnt); } //Devolvemos el valor leído return Aux; } ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 11 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II En el ejemplo anterior se abrió el archivo para poder grabar en él un registro, luego se cerró el archivo para poder abrirlo de entrada, es decir para poder leer el registro que se grabó y por último lo volvimos a cerrar. Esto se manejó de esta manera porque grabamos sólo un registro para familiarizarnos con los comandos. Tenga en cuenta, además, que al pasar de un modo de apertura a otro, como en nuestro caso del ejemplo anterior, primero se deberá cerrar el archivo. En el siguiente ejemplo grabará registros en el archivo mientras el usuario no ingrese cero (0) en la edad. Luego cerrará el archivo abierto para la grabación y lo abriremos de lectura para mostrar los registros grabados en él por pantalla. En el siguiente ejemplo, a través de un menú de opciones se grabará registros en el archivo de personas, con datos ingresados por pantalla. El proceso de ingreso de datos finaliza cuando el usuario ingrese cero (0) en la edad. La segunda opción es leer todo el archivo y mostrar los datos en la pantalla. //Incluimos las siguientes librerías para la utilización de rutinas. #include using namespace std; //Se define el tamaño máximo del string para el nombre #define MAXNOM 10 // Recuerde que las sentencias al preprocesador, aquellas que // comienzan con #, no llevan punto y coma “;”, ya que no son sintaxis. //Se define un tipo de datos string typedef char ty_sNombre[MAXNOM]; //armamos un tipo de datos estructuras para el archivo, que // en este caso coincide para el ingreso. typedef struct ty_RegPer{ int iEdad; char cInicial; ty_sNombre sNombre; }; //Prototipos de rutinas. bool AbrirArchEscrituraPer(FILE * & Arch); bool AbrirArchLecturaPer(FILE * & Arch); // este proceso abre para void GrabarRegArchPer(ty_RegPer r, FILE * & f); //lectura, void LeerRegArchPer(ty_RegPer& r , bool & bFin, FILE * & f); void CerrarArchPer(FILE *& f); void MostrarPer (ty_RegPer r); void Ingresar_DatosPer(ty_RegPer & rPer, bool & finDatos); void generarArchivoPer () ; void leerArchivoPer () ; char menu() ; ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 12 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II void main(){ char op; do { op = menu() ; switch (op) { case 'g' : { generarArchivoPer() ; break; } case 'l' : { leerArchivoPer() ; break; } default : break ; } } while (op!='f') ; getchar(); } //Desarrollo de Rutinas bool AbrirArchEscrituraPer(FILE *& Arch){ /*Acá le indicamos en que lugar físico del disco rígido va a almacenar el archivo que vamos a generar.*/ Arch = fopen("c:\\DatosPer.Dat", "wb"); /*Si Arch es igual a NULL (se estudiará en el próximo cuatrimestre), no se ha podido abrir el archivo*/ if (Arch == NULL){ cout << "No se pudo abrir el Archivo de Salida.\n"; return false; } else return true; } bool AbrirArchLecturaPer(FILE *& Arch){ // Ídem rutina anterior Arch = fopen("c:\\DatosPer.Dat", "rb"); if (Arch == NULL){ cout << "No se pudo abrir el Archivo de Entrada.\n"; return false; } else return true; } void CerrarArchPer(FILE *& f){ fclose(f); } void GrabarRegArchPer(ty_RegPer r, FILE *& f){ // Acá se graba efectivamente el registro en el archivo fwrite(&r, sizeof(r), 1, f); /* Parámetros: &p: paso la estructura sizeof(p): el largo en bytes de la struct 1: la cantidad de repeticiones ArchSal: en donde lo graba */ } void LeerRegArchPer(ty_RegPer &r , bool &bFin, FILE *&f){ // Rutina que lee los registros del archivo (uno por vez) fread(&r, sizeof(r), 1, f); //Preguntamos si leyó que es fin de archivo o leyó un registro if (feof(f)) bFin = true; else bFin = false; } ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 13 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II void Ingresar_DatosPer(ty_RegPer & r, bool & finDatos){ do{ cout << "Ingrese la Edad (0=FIN): "; cin >> r.iEdad; }while (r.iEdad < 0); if (r.iEdad !=0){ finDatos = false; do{ cout << "Ingrese la Inicial: "; cin >> r.cInicial; } while (((r.cInicial < 'a') || (r.cInicial > 'z')) && ((r.cInicial < 'A') || (r.cInicial > 'Z'))); cout << "Ingrese el Nombre: "; cin >> r.sNombre; } else finDatos = true; } void MostrarPer (ty_RegPer r){ cout << "\nEdad: " << r.iEdad; cout << "\nInicial: " << r.cInicial; cout << "\nNombre: " << r.sNombre; } void generarArchivoPer () { /*Variable para recibir datos de entrada, que coincide con el formato del archivo que tenemos que crear.*/ ty_RegPer rPer; bool finDatos; bool bFin; //Variable booleana de Fin de ingreso de datos por // el usuario (cero en la edad) bool bPudeAbrirArch; //Variable para controlar las aperturas //de los archivos. FILE * fPer; //Variable para el manejo del Archivo system("cls"); //Se abre el archivo para poder enviarle datos para almacenar bPudeAbrirArch = AbrirArchEscrituraPer(fPer); //Consultamos si fue posible la apertura if (bPudeAbrirArch) { /*En esta rutina, el usuario ingresará los datos y por tratarse de una función, se la asignamos a la variable p que esdel mismo tipo que definimos la función.*/ Ingresar_DatosPer(rPer, finDatos); /*Mientras el usuario no ingrese cero, grabamos el registro ingresado por el usuario a través del teclado*/ while (!finDatos){ GrabarRegArchPer(rPer, fPer); Ingresar_DatosPer(rPer, finDatos); } /*Al finalizar el ingreso de datos, como ya no guardaremos más datos en el archivo, lo cerramos para luego abrirlo de lectura para ver los resultados.*/ CerrarArchPer(fPer); } } ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 14 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II void leerArchivoPer () { /*Abrimos el archivo de lectura y le asignamos el resultado de esta operación a bPudeAbrirArch */ ty_RegPer rPer; bool finDatos; bool bFin; //Variable booleana de Fin de ingreso de datos por // el usuario (cero en la edad) bool bPudeAbrirArch; //Variable para controlar las aperturas //de los archivos. FILE * fPer; //Variable para el manejo del Archivo bPudeAbrirArch = AbrirArchLecturaPer(fPer); /* Traemos un registro para mostrarlo siempre que no sea fin de archivo, es decir que aún haya mas información.*/ if (bPudeAbrirArch) { LeerRegArchPer(rPer, bFin, fPer); // Mientras no sea bFin (variable creada por nosotros para controlar // el fin de archivo) while (!bFin) { MostrarPer(rPer); LeerRegArchPer(rPer, bFin, fPer); } CerrarArchPer(fPer); getchar(); } } char menu() { char op ; do { cout<<"ingrese opcion (f=fin/l=leer/g=grabar)"<>op; } while ((op!='f') && (op!='l') && (op!='g')) ; return op; } Se podrán utilizar para cualquier ejercicio que se necesite manejar archivos. Sólo bastará con modificar el registro del archivo. Dichas rutinas serán colocadas en internet. Actividad optativa: 1) Puede implementar la solución, y escribir con sus propias palabras qué hace cada procedimiento. 2) Puede escribir cuál es la sintaxis de cada instrucción relacionada con los archivos (fopen, fclose, fread, fwrite). Para esto último debe utilizar la ayuda en línea del IDE. 3) Puede modificar el programa para que trabaje con un archivo cuyos campos sean: nombre (30 caracteres, fecha de nacimiento (8 caracteres), sexo (un carácter ‘v’, ‘m’), y que grabe dos archivos, uno por cada sexo. 4) Puede modificar el listado preguntando que sexo quiere listar, y procesar el archivo correspondientes. ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 15 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II Actividad 3 - 4: - Realizar los cambios necesarios al programa recientemente explicado, para que grabe un archivo con los registros erróneos validados en el ingreso. Dejando solamente en el archivo de datos, aquellos registros que cumplen correctamente con las validaciones, y en un archivo llamado errores.dat sólo aquellos registros que no cumplieron con las validaciones. Nótese que al usuario ya no se le volverá a solicitar si por ejemplo ingresó mal la edad y /o la inicial, esto se deberá validar al momento de grabar, por lo tanto se analizará el ingreso de los datos una vez que hayan sido ingresados en su totalidad y optaremos por grabarlos en el archivo de datos o bien en el archivo de errores según corresponda. Aclaración: A pesar que en los ejemplos vistos hemos trabajado con un solo archivo, muchos programas trabajan con varios archivos, por lo tanto un programa podrá tener abiertos simultáneamente tantos archivos como sean necesarios. Proponemos revisar los programas realizados en las evaluaciones del taller anterior e identificar los archivos utilizados. Quinto: Modularización de las operaciones Como podemos observar en el ejemplo anterior hemos utilizado módulos (procedimientos o funciones) para el desarrollo de las herramientas de manejo de los archivos: ABRIR, CERRAR, LEER, GRABAR. El objetivo de utilizar estas herramientas está dado en el hecho de modularizar, esto es no utilizar las instrucciones de manejo de archivos directamente en los programas. Cuáles son las ventajas de trabajar con esta modalidad: 1. 2. 3. Si tenemos varios programas que utilizan el mismo archivo (es lo habitual) podemos generar “librerías”, en el sentido del módulo I, en las cuales agrupamos el diseño del registro y las cuatro operaciones básicas. Así, cuando debamos modificar el diseño, o el tipo de acceso, simplemente lo hacemos en un único archivo (nnnnn.h, nnnnn.cpp) y al compilar los programas “importan” las modificaciones realizadas. Si cambiamos de lenguaje de programación o de versión de C++ y las instrucciones son incompatibles con las que tenemos desarrolladas, podremos modificar únicamente en estas librerías. Qué debemos tener en cuenta a la hora de modularizar y armar librerías: 1. Por cada archivo que utilicemos en nuestros programas debemos armar una librería (nnnn.h, nnnn.cpp) 2. En el archivo de extensión “h” debemos incluir el diseño del regsitro (struct), y los prototipos de las 4 operaciones básicas 3. En el archivo de extensión “cpp” debemos incluir la línea #include “nnnn.h”, y el desarrollo de los prototipos descriptos en el archivo de extensión “h”. 4. Para definir el nombre de la estructura del registro debemos utilizar reglas nmotécnicas: por ejemplo para el archivo “alumnos” podemos utilizar typedef struct recAlu {} ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 16 NSTITUTO de TECNOLOGÍA O. R. T. Instituto Incorporado a la Enseñanza Oficial (A-763) Analista de Sistemas de Computación Taller de Computación II 5. Para definir el nombre de los procedimientos de archivos debemos utilizar nombres nmotécnicos: por ejemplo para el archivo “alumnos”, el procedimiento leer es: “leerAlu(….) 6. Los programas de aplicación deben utilizar los archivos a través de la implementación de librerías, y de las herramientas correspondientes. Por lo tanto no debemos escribir: fopen, fclose, fread, fwrite y feof en los programas de aplicación. Actividad 3 - 5: - Realizar los cambios necesarios al programa recientemente explicado, para que utilice librerías con los archivos, con el manejo de pantalla y con todo aquello que considere que es de uso general. . ver 3.0 - Yatay 240 - Bs As - República Argentina Pag. 17