All posts by Noralys Muñiz Maldonado

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.

 

 

02Dic/16

Aprendizaje de matemáticas por medio de la programación

 

 

APRENDIZAJE DE MATEMÁTICAS POR MEDIO DE LA PROGRAMACIÓN

 

Autores: MsC. Marcos Antonio León Fonseca.

MsC. Noralys Muñiz Maldonado.

 

Introducción:

 

En el mundo informático es un criterio generalizado que el aprendizaje de la programación ejerce una influencia positiva en el desarrollo del pensamiento y en la capacidad para la solución de problemas transferibles a otros dominios del conocimiento.

 

Aprender a programar, es aprender a solucionar problemas, pero a su vez, la solución de problemas obliga a la reflexión acerca de los aspectos esenciales del fenómeno en cuestión por lo que la contribución que la programación puede aportar al entendimiento de otros temas, las matemáticas en especial, es significativo.

 

El propósito de este artículo consiste en demostrar, a través de ejemplos, que la programación favorece el aprendizaje de las matemáticas.

 

Desarrollo:

 

Ejemplos:

 

Los lenguajes de programación tienen implementada una estructura de control de extraordinario valor, llamada recursividad, la cual permite que un procedimiento se llame a sí mismo como un subprocedimiento. Utilizando los recursos que brinda el lenguaje de programación C++, elabore funciones recursiva que permitan:

 

  1. a) Hallar el factorial de un número.

 

Matemáticamente se define como factorial de un número n al producto de los enteros positivos desde 1 hasta n y se denota por n!

 

n! = 1 . 2 . 3 . 4 . 5 . . . (n – 2) (n – 1) n

 

también se define 0! = 1, de forma que la función está definida para todos los enteros no negativos. Así tenemos que:

 

0! = 1     1! = 1     2! = 1 . 2 = 2     3! = 1 . 2 . 3 = 6

4! = 1 . 2 . 3 . 4 = 24     5! = 1 . 2 . 4 . 5 = 120

 

y así sucesivamente.

 

 

Observe que:

 

5! = 5 . 4! = 5 . 24 = 120    6! = 6 . 5! = 6 . 120 = 720

 

esto se cumple para cualquier entero n positivo; o sea,

 

n! = n (n – 1)!

 

de acuerdo con esto, la función factorial se puede definir también como :

 

Si n < 2 entonces n! = 1

Si n ≥ 2 entonces n! = n (n – 1)!

 

Por ejemplo, 4! sería:

 

4! = 4 . 3!

3! = 3 . 2!

2! = 2 . 1!

1! = 1 . 0!

0! = 1

1! = 1 . 1 = 1

2! = 2 . 1 = 2

3! =  3 . 2 = 6

4! = 4 . 6 = 24

 

Esta definición de n! es recursiva  ya que se refiere a sí misma cuando invoca (n – 1) !

 

Luego nuestra función podría ser:

 

int Factorial (int n) {

if (n < 2)

return 1;

else

return n * Factorial (n – 1);

}

 

  1. b) Encontrar el término n-ésimo Fn de la secuencia de Fibonacci.

 

La celebre secuencia de Fibonacci designada por F0, F1, F2, …, es:

 

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …

O sea:

 

F0 = 0 y F1 = 1 y cada término sucesivo es la suma de los dos términos precedentes, por ejemplo, los dos términos que siguen a la secuencia anterior son:

34 + 55 = 59      y      55 + 89 = 144

por lo que una definición formal de esta función es la siguiente:

 

Si n = 0 o n = 1, entonces Fn = n

Si n > 1, entonces Fn = Fn-2 + Fn-1

 

Este es otro ejemplo de definición recursiva, ya que la definición se refiere a sí misma en Fn-2  y  Fn-1

 

Nuestra función podría ser:

 

int Fibonacci (int n) {

if (n == 0 || n == 1)

return n;

else

return Fibonacci (n – 2) + Fibonacci (n – 1);

}

 

  1. c) Encontrar un valor determinado para la función de Ackermann.

 

La función de Ackermann es una función con dos argumentos a los cuales se le pueden asignar cualquier número entero no negativo: 0,1, 2, 3, 4, …

 

Esta función se define como:

 

Si m = 0, entonces A (m, n) = n + 1

Si m ≠ 0, pero n = 0, entonces A (m, n) = A (m – 1, 1)

Si m ≠ 0 y n  ≠ 0, entonces A (m, n) = A (m – 1, A (M, n – 1))

 

Por ejemplo, el valor de A (1, 3) sería:

 

A (1, 3) = A (0, A (1, 2))

A ( 1, 2) = A (0, A (1, 1))

A (1, 1) = A (0, A (1, 0))

A (1, 0) =  A (0, 1)

A (0, 1) = 1 + 1 = 2

A (1, 1)  = A (0, 2)

A (0, 2) = 2 + 1 = 3

A (1, 1) = 3

A (1, 2) = A (0, 3)

A (0, 3) = 3 + 1 = 4

A (1, 2) = 4

A (1, 3) = A (0, 4)

A (0, 4) = 4 + 1 = 5

A (1, 3) = 5

 

Una vez más tenemos una definición recursiva, ya que se refiere a sí misma en  A (m – 1, 1) y A (m – 1, A (M, n – 1)).

 

 

Por lo que nuestra función podría ser:

 

int Ackermann (int m, int n) {

if (m == 0)

return n + 1;

else

if (m != 0 && n == 0)

return Ackermann (m – 1, 1);

else

if (m != 0 && n != 0)

return Ackermann (m – 1, Ackermann (m, n – 1));

}

 

Como se puede notar la implementación de las funciones en el lenguaje de programación requiere del análisis de los aspectos esenciales de los contenidos matemáticos que se abordan favoreciéndose con ello su aprendizaje.

 

Conclusiones:

 

La contribución que la programación puede aportar al aprendizaje de contenidos  matemáticos, es significativo.

 

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.