7
Laboratorio de Programación I Página 126 Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23 UNIVERSIDAD CATÓLICA DE SANTA MARÍA PROGRAMA PROFESIONAL DE INGENIERÍA DE SISTEMAS SESIÓN 23: Ficheros de Acceso Aleatorio II en C/C++ I OBJETIVOS Comprender los conceptos de operaciones complejas sobre archivos de acceso directo o aleatorio. Aplicar las operaciones complejas sobre archivos de acceso directo para la gestión de registros. Valorar las ventajas y recursos que proporcionan las funciones para operación sobre archivos de acceso directo. II TEMAS A TRATAR Introducción. Operaciones complejas en registros y archivos directos Resumen. III MARCO TEORICO 1. INTRODUCCIÓN Los archivos de acceso aleatorio son más versátiles, permiten acceder a cualquier parte del fichero en cualquier momento, como si fueran arrays en memoria. Las operaciones de lectura y/o escritura pueden hacerse en cualquier punto del archivo. Estos existen para que los datos puedan ser guardados y que no se borren cuando acaben la ejecución del programa. Para eso disponemos de las funciones seekp y seekg, que permiten cambiar la posición del fichero en la que se hará la siguiente escritura o lectura. La 'p' es de put y la 'g' de get, es decir escritura y lectura, respectivamente. Otro par de funciones relacionadas con el acceso aleatorio son tellp y tellg, que sirven para saber en qué posición del fichero nos encontramos. La función seekg nos permite acceder a cualquier punto del fichero, no tiene por qué ser exactamente al principio de un registro, la resolución de la funciones seek es de un byte. Cuando trabajemos con nuestros propios streams para nuestras clases, derivándolas de ifstream, ofstream o fstream, es posible que nos convenga sobrecargar las funciones seek y tell para que trabajen a nivel de registro, en lugar de hacerlo a nivel de byte. La función seekp nos permite sobrescribir o modificar registros en un fichero de acceso aleatorio de salida. La función tellp es análoga a tellg, pero para ficheros de salida.

Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Embed Size (px)

Citation preview

Page 1: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 126

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

UNIVERSIDAD CATÓLICA DE SANTA MARÍA PROGRAMA PROFESIONAL DE INGENIERÍA DE SISTEMAS

SESIÓN N° 23:

Ficheros de Acceso Aleatorio II en C/C++

I

OBJETIVOS

Comprender los conceptos de operaciones complejas sobre archivos de acceso directo o aleatorio.

Aplicar las operaciones complejas sobre archivos de acceso directo para la gestión de registros.

Valorar las ventajas y recursos que proporcionan las funciones para operación sobre archivos de acceso directo.

II

TEMAS A TRATAR

Introducción. Operaciones complejas en registros y archivos directos Resumen.

III

MARCO TEORICO

1. INTRODUCCIÓN

Los archivos de acceso aleatorio son más versátiles, permiten acceder a cualquier parte del fichero en cualquier momento, como si fueran arrays en memoria. Las operaciones de lectura y/o escritura pueden hacerse en cualquier punto del archivo.

Estos existen para que los datos puedan ser guardados y que no se borren cuando acaben la ejecución del programa.

Para eso disponemos de las funciones seekp y seekg, que permiten cambiar la posición del fichero en la que se hará la siguiente escritura o lectura. La 'p' es de put y la 'g' de get, es decir escritura y lectura, respectivamente.

Otro par de funciones relacionadas con el acceso aleatorio son tellp y tellg, que sirven para saber en qué posición del fichero nos encontramos.

La función seekg nos permite acceder a cualquier punto del fichero, no tiene por qué ser exactamente al principio de un registro, la resolución de la funciones seek es de un byte.

Cuando trabajemos con nuestros propios streams para nuestras clases, derivándolas de ifstream, ofstream o fstream, es posible que nos convenga sobrecargar las funciones seek y tell para que trabajen a nivel de registro, en lugar de hacerlo a nivel de byte.

La función seekp nos permite sobrescribir o modificar registros en un fichero de acceso aleatorio de salida. La función tellp es análoga a tellg, pero para ficheros de salida.

Page 2: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 127

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

Los archivos de acceso aleatorio nos permiten hacer lo mismo que los de secuencial, solo que nos ayudamos de funciones para mover los punteros de lectura y escritura, para leer o escribir cosas de manera aleatoria.Los archivos de acceso directo tienen un conjunto de operaciones complejas que deben llevarse a cabo, en estas tenemos la búsqueda, la eliminación y el purgado de registros del archivo, estas operaciones completan el conjunto de operaciones realizables sobre un archivo de acceso directo o aleatorio, las ventajas que ofrece un archivo de acceso directo sobre un archivo de acceso secuencial son evidentes, sin embargo su gestión reviste un conjunto de conceptos que el estudiante debe aplicar para su correcta manipulación y uso, las operaciones se siguen según una secuencia de operaciones clásicas que no revisten ninguna complejidad ni son necesarias de alterar.

2. OPERACIONES COMPLEJAS EN REGISTROS Y ARCHIVOS

DIRECTOS

Al procesar archivos de acceso directo la forma de aplicar las operaciones cambia un poco por la forma como se producen las instrucciones pero aun así se sigue la misma lógica.

A. BÚSQUEDA

En este punto se estudia la búsqueda de un registro o renglón determinado. En este proceso el usuario del programa quiere que se despliegue un y solo un registro de información proporcionando un dato de búsqueda que generalmente es la clave del registro. Se debe recordar que en esta operación se muestra la diferencia fundamental entre archivos secuenciales y archivos directos, es decir aquí se puede acceder directamente a un registro n cualquiera.

#include <iostream>

using namespace std;

#include <stdio.h>

#include <conio.h>

#include <string.h>

struct

{

int clave;

char nombre[30];

int edad;

} animalito;

int main()

{

system("cls");

// cargando clave a buscar

printf("dame clave buscar:");

int claveb;

scanf("%d",&claveb);

//abriendo, leyendo,cargando estructura

FILE *archdisco;

archdisco = fopen("c:\\ac\\archivo1.dat","ab+");

//usar fseek() para posicionarse al principio del registro

//buscado

fseek(archdisco,(long)(claveb)* sizeof(animalito), 0 );

// ahora se lee el registro

fread(&animalito,sizeof(animalito),1,archdisco);

// desplegando estructura y asegurandose

printf("%d ",animalito.clave);

printf("%s ",animalito.nombre);

printf("%d ",animalito.edad);

printf("\n");

// no olvidar cerrar archivo

fclose(archdisco);

Page 3: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 128

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

system("pause");

return 0;

}

Como se desprende del programa usando fseek() es posible posicionarse en cualquier byte del archivo. El formato completo de fseek() es:

fseek(apuntador,(long)(clave)*(sizeof(registro)),0);

Donde los parámetros son:

Apuntador al archivo en disco El segundo parámetro es el BYTE donde se quiere que empiece la lectura o

grabación al archivo en disco. Este BYTE debe ser de tipo LONG así que si en algún programa de ejemplo ven fseek( , 387L, ); que no les llame la atención, es otra manera de hacerle cast a un dato. Como va a estar difícil que se le atine a un byte determinado, es por eso que en el programa mejor se deja que sea el propio servidor quien calcule el byte donde empieza un registro determinado con clave * sizeof o tamaño de registro.

El tercer parámetro es a partir de donde se quiere posicionar el apuntador interno del archivo, los valores pueden ser:

0 ---> SEEK_SET principio del archivo.

1 ---> SEEK_CUR posicion actual. 2 ---> SEEK_END fin del archivo.

Se debe recordar que es muy importante que las claves grabadas en un archivo directo tengan la secuencia 0,1,2,3,4,5.....n

B. FILTROS CONDICIONES

Otro problema similar al anterior es el de filtros o condiciones, es decir en muchas ocasiones es necesario obtener información acerca de un subconjunto de renglones de el archivo.

Por ejemplo todos los estudiantes que sean mayores de 17 años, o todos los clientes que sean de Tijuana, etc. a esto le llamamos filtros o condiciones.

También se resuelve de manera similar a los de archivos secuenciales es decir usando un ciclo de lectura de todo el archivo e ir desplegando todos los registros que cumplan la condición.

#include <iostream>

using namespace std;

#include <stdio.h>

#include <conio.h>

#include <string.h>

struct

{

int clave;

char nombre[30];

int edad;

} animalito;

int main()

{

system("cls");

// cargando clave a buscar

printf("EDAD MAYOR QUE >= :");

int edad; scanf("%d",&edad);

system("pause");

//abriendo, leyendo,cargando estructura

FILE *archdisco;

Page 4: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 129

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

archdisco = fopen("c:\\ac\\archivo1.dat","at+");

// aqui siempre debe empezar el ciclo de lectura

// y fread() regresa siempre cuantas estructuras leyo

while(fread(&animalito,sizeof(animalito),1,archdisco)==1)

{

// desplegando estructura buscada

if (animalito.edad >= edad)

{

printf("%d ",animalito.clave);

printf(" %s ",animalito.nombre);

printf(" %d ",animalito.edad);

printf("\n");};

} // aqui termina while

// no olvidar cerrar archivo y siempre fuera de while

fclose(archdisco);

system("pause");

return 0;

}

Como se observa es un problema y una solución similar al tema anterior de búsquedas.

C. BORRADO, BAJAS O ELIMINACIÓN DE REGISTROS

Eliminación o bajas es el proceso por medio del cual algunos registros del archivo son purgados del archivo, existen dos maneras por las cuales se puede realizar ese proceso.

En la primera manera se usan dos archivos, el archivo original y un archivo temporal, el procedimiento o algoritmo es muy sencillo, se lee el registro del archivo original y si no es el registro a eliminar entonces se almacena en el archivo temporal, cuando se termina de procesar todo el archivo original, el archivo temporal solo contendrá todos los registros que no se quisieron eliminar, ya con estos dos archivo se procede a eliminar o borrar usando la instrucción remove el archivo original y se procede a renombrar usando la instrucción rename de el archivo temporal como nuevo archivo original.

Sin embargo en archivos directos no se puede ni se debe eliminar físicamente registros de los archivos porque recordar que la clave del registro esta enlazada directamente a la posición que dicho registro tiene en disco y no seria muy conveniente estarle cambiando la matricula al alumno cada rato o el numero de serie al auto, etc.

Aparte de que con esta manera de eliminar incluso físicamente los registros del archivo es que no hay manera de recuperar esa información posteriormente.

Es por eso que otra técnica común de eliminación es incluir un campo de estado, status o bandera o semáforo en el registro y conforme se va cargando el registro y antes de mandarlo a disco se le agrega a dicho campo el carácter 'A' -->alta, así que cuando se quiera una baja solo se pondría dicho campo en 'B' y todos los programas de lectura, búsqueda y filtros deberán revisar esta campo de estado antes de hacer algo con el registro.

D. OPERACIONES CON CAMPOS

En este tema se analiza la manera de poder realizar operaciones o procesos con los campos de los registros en el archivo DIRECTO, lo único importante a considerar es que los campos del registro son en cierta medida igual que variables normales y por tanto se pueden procesar de manera normal como lo muestra el ejemplo.

#include <iostream>

using namespace std;

#include <stdio.h>

#include <conio.h>

#include <string.h>

Page 5: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 130

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

struct

{

int clave;

char nombre[30];

int edad;

} animalito;

int main()

{

system("cls");

FILE *arch1;

long r=0;

arch1 = fopen("c:\\ac\\archivo1.dat","rb+");

while (fread(&animalito,sizeof(animalito),1,arch1)==1)

{

// sumando 100 a edad

animalito.edad = animalito.edad + 100 ;

//como ya se leyo se regresa el apuntador al principio

//del registro

fseek(arch1,r*sizeof(animalito),0 );

// y se escribe el registro modificado al archivo

fwrite(&animalito,sizeof(animalito),1,arch1);

r=r+1;

//turboc no permite i/o archivos sin un rewind, fseek,

//etc

fseek(arch1,r*sizeof(animalito),0);

}; // aqui termina for

//cerrando archivo

fclose(arch1);

//avisando

puts("EDADES + 100");

system("pause");

return 0;

}

Como se observa la solución es muy sencilla solo se ocupa:

Leer fread() el registro, esto mueve el apuntador al siguiente registro. Modificar registro Regresar a posición anterior con fseek() Grabar fwrite() el registro corregido Volver a usar un fseek() porque turboc no acepta i/o sin rewind, fseek, etc ver ayuda

del compilador y no se ocupan los dos archivos como en el caso secuencial.

E. EDICION DE REGISTROS

Modificar o editar un registro es uno de los procesos mas comunes con archivos en disco, generalmente después de un fuerte proceso de captura de registros, una revisión o consulta general muestra muchos de ellos con errores de captura; vamos a editar el segundo registro.

#include <iostream>

using namespace std;

#include <stdio.h>

#include <conio.h>

#include <string.h>

struct

{

int clave;

char nombre[30];

int edad;

} animalito;

int main()

{

system("cls");

// cargando clave a buscar

printf("dame clave editar:");

Page 6: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 131

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

int claveb; scanf("%d",&claveb);

//abriendo, leyendo,cargando estructura

FILE *archdisco;

archdisco = fopen("c:\\ac\\archivo1.dat","rb+");

//usar fseek() para posicionarse al principio de registro

//buscado

fseek(archdisco,(long)(claveb)* sizeof(animalito), 0 );

// ahora se lee el registro

fread(&animalito,sizeof(animalito),1,archdisco);

// desplegando estructura y asegurandose

printf("%d ",animalito.clave);

printf("%s ",animalito.nombre);

printf("%d ",animalito.edad);

printf("\n");getchar();

//recapturando los nuevos datos

printf("dame nuevo nombre :");

gets(animalito.nombre);

printf("dame nueva edad :");

scanf("%d",&animalito.edad);

// regresando a apuntador para regrabar

fseek(archdisco,(long)(claveb)* sizeof(animalito), 0 );

fwrite(&animalito,sizeof(animalito),1,archdisco);

// no olvidar cerrar archivo

fclose(archdisco);

//avisando

printf("REGISTRO EDITADO");

system("pause");

return 0;

}

Observar que es el programa normal de búsqueda pero ya desplegado el registro se piden los nuevos datos, posteriormente se regresa el apuntador de registros a la posición original para volverse a regrabar el registro pero con los datos ya editados.

3. RESUMEN

Los archivos de acceso aleatorio al ser más versátiles, permiten acceder a cualquier parte del archivo en cualquier momento, como si fueran arrays en memoria. Las operaciones de lectura y/o escritura pueden hacerse en cualquier punto del archivo de forma directa con las funciones asociadas a este tipo de archivos.

Los archivos de acceso directo tiene como los de acceso secuencial las mismas operaciones complejas, pero la diferencia es la capacidad que poseen estos archivos de saltar al registro respectivo para hacer sus operaciones, esto hace que el tipo de gestión sea mucho más rápido a la hora de hacer el procesamiento, para ello posee un mecanismo que nos permite apuntar al registro deseado.

IV

(La práctica tiene una duración de 2 horas) ACTIVIDADES

1. Encender el equipo de cómputo, si existe algún desperfecto o faltante en el equipo comunicarlo inmediatamente.

2. Al aparecer la solicitud de contraseña hacer clic en el botón Cancelar o ingresar el nombre de cuenta(login) y contraseña(password) que especifique el Docente. Esperar que aparezca el mensaje de Inicio de sesión.

3. Crear una carpeta que se llame Programación I y dentro de ella una que se llame Práctica Nº 23 dentro de la carpeta Mis Documentos.

4. Ejecute el Visual Studio 2010, crear un nuevo proyecto CRL, para esto elegir en la pestaña Archivo y aquí elegir la opción más adecuada.

5. Nombrar los archivos como se indica en el archivo Actividades N° 23 que se adjunta y asegurarse de almacenarlos en la carpeta Práctica Nº 23 al momento de crearlos.

6. Realizar las acciones indicadas en el archivo adjunto. 7. Al finalizar la práctica de be guardar todos sus archivos, ya sea en su memoria USB o por

Page 7: Guia_de_Practicas_de_Programacion_I_-_Sesion_23_-_2012.pdf

Laboratorio de Programación I Página 132

Mgter. Ángel Montesinos Murillo, Mgter. Manuel Zúñiga Carnero Sesión N° 23

correo electrónico y luego eliminar los archivos del equipo y vaciar la papelera de reciclaje.

V

EJERCICIOS

1. Construir programas de edición o modificación a los archivos ya construidos. 2. construirles programas que procesen algunos campos de los archivos ejemplos que ya

tienen construidos. 3. Construir programas de eliminación usando el segundo método( bajas lógicas como se

indica en el ultimo párrafo) para los archivos construidos y no olvidar reconstruir los programas anteriores para que incluyan y tomen en cuenta el nuevo campo.

VI

CUESTIONARIO

1. ¿Qué es un archivo de acceso directo o aleatorio? 2. ¿Cuáles son las operaciones básicas que se llevan a cabo sobre un archivo de acceso

directo? 3. ¿Qué función se usa para hacer la búsqueda en archivos de acceso directos? 4. ¿Cómo se implementa la búsqueda sobre un archivo de acceso directo? 5. ¿En qué consisten los filtros en el procesamiento de registros en archivos de acceso

directo? 6. ¿En qué consiste el proceso de eliminación de registros en un archivo de acceso directo? 7. ¿Para que se usa el campo de estado en un archivo de acceso directo? 8. ¿Qué tipo de operaciones con campos se lleva acabo en un archivo de acceso directo? 9. ¿Cómo se lleva a cabo el proceso de edición de registros? 10. ¿Cuál es la diferencia de operaciones de registros entre archivos de acceso secencial y

archivos de acceso directo.

VII

BIBLIOGRAFIA Y REFERENCIAS

Deitel, Paul J., Deitel, Harvey M., "Cómo Programar en C++", 6ta Edición, Ed. Pearson Educación, México 2009.

Ceballos Sierra, Francisco J., "Curso de Programación C++. Programación Orientada a Objetos"; MADRID, RA-MA, 1991.

Kernighan, Brian W., Ritchie, Dennis M., "El Lenguaje de Programación C", 2da Edición, Ed. Prentice Hispanoamérica S. A., México 1991.