Archivos de la etiqueta: Archivo acceso directo

02Dic/16

Conservación de la Información en C++

CONSERVACIÓN DE LA INFORMACIÓN EN C++

 

Autores: MsC. Marcos Antonio León Fonseca.

MsC. Noralys Muñiz Maldonado.

 

Introducción:

 

La conservación permanente de información, requiere de la utilización de archivos de datos ya que el almacenamiento de estos en variables se pierde al terminar la ejecución del programa.

 

En este trabajo se aborda la creación, actualización y procesamiento de los archivos de datos en C++.

 

Desarrollo:

 

En programación un registro es una colección de variables relacionadas bajo un nombre, que puede contener variables de varios tipos diferentes de datos a los cuales se les denomina campo. Por ejemplo, un registro para un Profesor pudiera estar formado por los siguientes campos:

 

  • Número de carné de identidad.
  • Nombres.
  • Especialidad.
  • Asignatura que imparte.
  • Años de experiencia.

 

Al conjunto de registros relacionados, se le denomina archivo.

 

Para facilitar la recuperación de los registros almacenados en un archivo, es necesario que al menos un campo de cada registro sea seleccionado como campo clave, es decir un campo que identifique en particular a cada registro. Por ejemplo, en el registro Profesor pudiera ser el Número del carné de identidad dado que a cada profesor se le asigna un número que lo identifica a él y solo a él.

 

Las formas de organizar los registros dentro de un archivo son variadas. Los tipos de organizaciones más utilizados son:

 

  • Archivo de acceso secuencial.
  • Archivo de acceso directo.

 

Archivos de acceso secuencial.

 

En el archivo de acceso secuencial los registros se almacenan en orden en correspondencia con el campo clave y no necesariamente tienen que ser de la misma longitud. Por ejemplo, en el archivo Profesores, los registros se almacenarían por el número de identidad. El primer registro es el que tenga el menor número de identidad y los siguientes se irán entrando en orden ascendente.

 

El siguiente programa crea el archivo secuencial Profesores:

 

#include <cstdlib>

#include <iostream>

using namespace std;

 

int main(int argc, char *argv[])

{

int Clave;

char Nombres [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

FILE *Fichero;

 

if ((Fichero = fopen (“Profesores.dat”, “w”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Entre el indicador de fin de archivo (<CTRL-Z> <RETURN>) para finalizar” << endl;

cout << “Entre la clave: “;

cin >> Clave;

 

while (!feof (stdin)) {

gets (Nombres);

cout << “Entre el nombre del profesor: “;

gets (Nombres);

cout << “Entre la especialidad: “;

gets (Especialidad);

cout << “Entre la asignatura: “;

gets (Asignatura);

cout << “Entre los a\244os de experiencia: “;

cin >> Experiencia;

fprintf (Fichero, “%d %s %s %s %d\n”, Clave, Nombres, Especialidad, Asignatura, Experiencia);

cout << “Entre la clave: “;

cin >> Clave;

}

fclose (Fichero);

}

}

 

Analicemos el programa:

 

El enunciado: FILE *Fichero declara a Fichero como un puntero a la estructura FILE.

 

En la línea:   if ((Fichero = fopen (“Profesores.dat”, “w”)) == NULL) se utiliza el puntero Fichero para crear el archivo “Profesores.dat”.

 

La función fopen recibe dos argumentos: el nombre del archivo y el modo en que se va a abrir. El modo “w” indica que se va a abrir para escritura.

Otros modos de apertura de un archivo son:

 

“r”        para abrir un archivo existente para lectura.

“a”       para añadir registros al final de un archivo.

“r+” para actualizar registros.

“w+” para crear un archivo para actualizar.

“a+” para agregar, abrir o crear un archivo para actualizar.

 

Si un archivo es abierto con fopen para escribir y no existe, es creado y si existe el contenido del mismo es borrado sin advertencias.

 

La estructura de control if se utiliza para saber si el archivo no está abierto, es decir si el puntero al archivo es NULL.

 

La línea while (¡feof (stdin)) se utiliza para determinar si se introduce la combinación de teclas de fin de archivo.

 

El siguiente programa lee los registros almacenados en el archivo  de acceso secuencial “Profesores.dat”:

 

#include <cstdlib>

#include <iostream>

 

using namespace std;

 

int main(int argc, char *argv[])

{

int Clave;

char Nombres [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

FILE *Fichero;

 

if ((Fichero = fopen (“Archivo.dat”, “r”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Clave     Nombres     Especialidad     Asignatura     Experiencia” << endl;

fscanf (Fichero, “%d%s%s%s%d”, &Clave, Nombres, Especialidad, Asignatura, &Experiencia);

 

while (!feof (Fichero)) {

cout << Clave << ” ” << Nombres << ” ” << Especialidad  << ” “<< Asignatura  << ” “<< Experiencia  << ” “<< endl;

fscanf (Fichero, “%d%s%s%s%d”, &Clave, Nombres, Especialidad, Asignatura, &Experiencia);

}

fclose (Fichero);

}

system(“PAUSE”);

}

Cuando se recuperan los datos de un archivo secuencial, se comienza a leer desde el principio del archivo y se leen todos los datos en forma consecutiva hasta que se encuentren los datos deseados. La estructura FILE cuenta con un puntero de posición de archivo que va especificando la posición en el archivo donde ocurrirá la próxima lectura o escritura por lo que si se quiere procesar los datos secuencialmente en un archivo varias veces desde el principio, se debe posicionar el apuntador de posición de archivo al inicio del mismo, esto se logra con el enunciado: rewind (Fichero).

 

En un fichero secuencial la actualización de los datos corre el riesgo de borrar otros datos dentro del archivo ya que, por ejemplo, si el nombre del profesor “Juan” necesita ser modificado por “Juan Antonio”, el nuevo nombre es más largo que el original por lo que los caracteres más allá de la letra “n” sobrescribirían los datos de la Especialidad.

 

Para llevar a cabo la modificación se deberá copiar a un nuevo archivo los registros anteriores a “Juan”, escribir el nuevo registro y copiar los registros existentes después de “Juan” al nuevo archivo, o sea, habría que procesar todos los registros.

 

Archivos de acceso directo.

 

En un archivo de acceso directo, los registros son de longitud fija y se puede tener acceso directamente a ellos sin tener que buscar a través de otros. También es posible insertar, actualizar y borrar registros sin destruir otros datos del archivo.

 

El siguiente programa crea el archivo de  acceso directo Profesores:

 

#include <cstdlib>

#include <iostream>

 

using namespace std;

 

struct Datos {

int Clave;

char Nombre [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

};

 

int main(int argc, char *argv[])

{

FILE *Fichero;

Datos Informacion;

if ((Fichero = fopen (“Profesores.dat”, “w”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Entre el n\243mero de Clave (1 hasta 100; 0 para finalizar): “;

cin >> Informacion.Clave;

while (Informacion.Clave != 0) {

gets (Informacion.Nombre);

cout << “Entre el Nombre del profesor: “;

gets (Informacion.Nombre);

cout << “Entre la Especialidad: “;

gets (Informacion.Especialidad);

cout << “Entre la Asignatura: “;

gets (Informacion.Asignatura);

cout << “Entre los a\244os de Experiencias: “;

cin >> Informacion.Experiencia;

fseek (Fichero, (Informacion.Clave – 1) * sizeof (struct Datos), SEEK_SET);

fwrite (&Informacion, sizeof (struct Datos), 1, Fichero);

cout << “Entre el n\243mero de Clave (1 hasta 100; 0 para finalizar): “;

cin >> Informacion.Clave;

}

fclose (Fichero);

}

}

 

La combinación fseek y fwite se utiliza para escribir los datos en el archivo. La función fseek ubica el puntero en la posición específica del archivo y fwite escribe los datos en esa posición.

 

El enunciado fseek (Fichero, (Información.Clave – 1) * sizeof (struct Datos), SEEK_SET) coloca el puntero en la posición que se obtiene de multiplicar (Información.Clave – 1) por sizeof (struct Datos).

 

La constante simbólica SEEK_SET indica que el puntero se coloca en relación con el principio del archivo.

 

El enunciado fwrite (&Información, sizeof (struct Datos), 1, Fichero) hace que la estructura datos de tamaño sizeof (Struct datos) se escriba al archivo al cual apunta Fichero.

 

El siguiente programa lee los registros almacenados en el archivo de acceso directo “Profesores.dat”:

 

#include <cstdlib>

#include <iostream>

 

using namespace std;

 

struct Datos {

int Clave;

char Nombre [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

};

int main(int argc, char *argv[])

{

FILE *Fichero;

Datos Informacion;

if ((Fichero = fopen (“Profesores.dat”, “r”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Clave     Nombre     Especialidad     Asignatura     Experiencia” << endl;

fread (&Informacion, sizeof (struct Datos), 1, Fichero);

while (!feof (Fichero)) {

cout <<Informacion.Clave << Informacion.Nombre << Informacion.Especialidad << Informacion.Asignatura << Informacion.Experiencia << endl;

fread (&Informacion, sizeof (struct Datos), 1, Fichero);

}

fclose (Fichero);

}

system(“PAUSE”);

}

 

El siguiente programa actualiza los años de experiencias de los registros almacenados en el archivo de acceso directo “Profesores.dat”:

 

#include <cstdlib>

#include <iostream>

 

using namespace std;

 

struct Datos {

int Clave;

char Nombre [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

};

 

int Registro;

int Actualizacion;

 

int main(int argc, char *argv[])

{

FILE *Fichero;

struct Datos Informacion;

if ((Fichero = fopen (“Archivo.dat”, “r+”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Entre el n\243mero de Clave del registro a actualizar: “;

cin >> Registro;

fseek (Fichero, (Registro – 1) * sizeof (struct Datos), SEEK_SET);

fread (&Informacion, sizeof (struct Datos), 1, Fichero);

if (Informacion.Clave == 0)

cout << “Ese registro no existe.” << endl;

else {

cout << Informacion.Clave << ” ” << Informacion.Nombre << ” ” << Informacion.Especialidad << ” ” << Informacion.Asignatura << ” ” << Informacion.Experiencia << endl;

cout << “Entre los a\244os de Experiencias Actualizados: “;

cin >> Actualizacion;

Informacion.Experiencia = Actualizacion;

cout << Informacion.Clave << ” ” << Informacion.Nombre << ” ” << Informacion.Especialidad << ” ” << Informacion.Asignatura << ” ” << Informacion.Experiencia << endl;

fseek (Fichero, (Informacion.Clave – 1) * sizeof (struct Datos), SEEK_SET);

fwrite (&Informacion, sizeof (struct Datos), 1, Fichero);

}

fclose (Fichero);

}

system(“PAUSE”);

}

 

El siguiente programa borra registros almacenados en el archivo de acceso directo “Profesores.dat”:

 

#include <cstdlib>

#include <iostream>

 

using namespace std;

 

struct Datos {

int Clave;

char Nombre [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

};

 

int Registro;

 

int main(int argc, char *argv[])

{

FILE *Fichero;

struct Datos Informacion;

struct Datos BlankInformacion = {0, “”, “”, “”, 0};

if ((Fichero = fopen (“Archivo.dat”, “r+”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Entre el n\243mero de Clave del registro a borar: “;

cin >> Registro;

fseek (Fichero, (Registro – 1) * sizeof (struct Datos), SEEK_SET);

fread (&Informacion, sizeof (struct Datos), 1, Fichero);

if (Informacion.Clave == 0)

cout << “Ese registro no existe.” << endl;

else {

fseek (Fichero, (Registro – 1) * sizeof (struct Datos), SEEK_SET);

fwrite (&BlankInformacion, sizeof (struct Datos), 1, Fichero);

}

fclose (Fichero);

}

system(“PAUSE”);

}

 

El siguiente programa agrega registros al archivo de acceso directo “Profesores.dat”:

 

#include <cstdlib>

#include <iostream>

 

using namespace std;

 

struct Datos {

int Clave;

char Nombre [30];

char Especialidad [30];

char Asignatura [30];

int Experiencia;

};

 

int main(int argc, char *argv[])

{

int Registro;

FILE *Fichero;

Datos Informacion;

if ((Fichero = fopen (“Archivo.dat”, “r+”)) == NULL)

cout << “El fichero no puede ser abierto.” << endl;

else {

cout << “Entre el n\243mero de Clave (1 hasta 100): “;

cin >> Registro;

fseek (Fichero, (Registro – 1) * sizeof (struct Datos), SEEK_SET);

fread (&Informacion, sizeof (struct Datos), 1, Fichero);

if (Informacion.Clave != 0)

cout << “Ese registro existe.” << endl;

else {

Informacion.Clave = Registro;

gets (Informacion.Nombre);

cout << “Entre el Nombre del profesor: “;

gets (Informacion.Nombre);

cout << “Entre la Especialidad: “;

gets (Informacion.Especialidad);

cout << “Entre la Asignatura: “;

gets (Informacion.Asignatura);

cout << “Entre los a\244os de Experiencias: “;

cin >> Informacion.Experiencia;

fseek (Fichero, (Informacion.Clave – 1) * sizeof (struct Datos), SEEK_SET);

fwrite (&Informacion, sizeof (struct Datos), 1, Fichero);

}

fclose (Fichero);

}

system(“PAUSE”);

}

 

Conclusiones:

 

El conocimiento y la utilización de los archivos de datos en nuestros programas, permite la conservación permanente de la información procesada por estos.

 

Bibliografía:

 

Deitel, H. M. y Deitel., P. J. (2005). Cómo Programar en C/C++. Santiago de Cuba., PROGRAF.

Katrib Mora, M. (1986). Lenguajes de programación y Técnicas de compilación. Ciudad de la Habana., Editorial Pueblo y Educación.

Lipschutz, S. (1989). Estructura de datos. Ciudad de la Habana., Edición Revolucionaria.