Construir un TDA que cumpla con las especificaciones que se enuncian a continuación. La construcción implica diseñar, implementar, testear y documentar el TDA solicitado.
Un log se define como un registro de mensajes oredenados cronológicamente. Responde a múltiples propósitos, por ejemplo registrar las sucesivas etapas por las que atraviesa un algoritmo, almacenar resultados de una corrida, marcar puntos de control en una aplicación, reportar situaciones anormales o erróneas en la ejecución de una aplicación.
Todos los mensajes registrados son volcados a un archivo de tipo texto, que será utilizado posteriormente para acceder a la información recopilada durante la corrida un programa. Cada línea del archivo tiene una fecha y hora en que ese mensaje fue escrito en el log.
Las operaciones sobre este TDA basicamente permiten agregar mensajes, con diferentes “formatos”, siempre conservando el orden cronológico en el que fueron incorporados.
El objetivo de este TDA es simplificar el registro de mensajes durante la ejecución de un programa.
Luego de entender el enunciado y comprender el trabajo que habia que realizar, el grupo comenzó a discutir como se implementaría el TDA en C++.
Lo primero que se decidió fue representar al TDA en una estructura compuesta por datos atómicos provista por C++ bajo el nombre de STRUCT.
A continuación se analizó que datos estarián incluídos dentro de esa estructura. Como el enunciado decía que tendríamos que guardar cadenas de texto en un archivo lo primero que al grupo se le ocurrió fue incluir en la estructura una dato de tipo STRING. Pero luego de deliberar un momento nos dimos cuenta de que no era necesario en ningun momento almacenar la cadena en memoria principal, ya que sería escrita directamente en el archivo. Entonces concluímos que para solucionar esa parte del problema solo necesitaríamos una referencia a un archivo de texto. Si bien se podría haber incluído un dato que representara al archivo, se optó por incluir un puntero hacia un dato de ese tipo para utilizar los conceptos sobre punteros y memoria dinámica aprendidos en clase.
Pero como el enunciado también decía que debería ser posible conocer la cantidad de registros almacenados en el archivo el grupo decidió incluir en la estructura un dato de tipo INT que serviría de contador.
Una vez definida la estructura, el grupo comenzó a discutir como se llevarían a cabo las primitivas que controlarían al TDA pedidas en el enunciado.
La primitiva inicializar sería la encargada de reservar memoria para el puntero al archivo donde se guardarían los registros y de iniciar el contador en cero.
La primitiva destruir tendría a cargo liberar la memoria reservada para el puntero y volver el contador a cero.
La primitiva escribirMensaje escribiría en el archivo el mensaje con su correspondiente fecha y hora obtenidas mediante el uso de la librería time.h sin olvidar de incrementar el contador en uno.
La primitiva escribirTitulo escribiría en el archivo un título con el formato pedido en el enunciado.
La primitiva escribirTotalMensajes escribiría en el archivo la cantidad de mensajes obtenida del contador con el formato pedido en el enunciado.
Para la realización del trabajo el grupo utilizó 2 archivos: uno donde se incluyó la definición de la estructura y la declaración de las primitivas, el otro contenía la definición de todas las primitivas. Estos archivos son log.h y log.cpp respectivamente.
#ifndef __LOG_H__ #define __LOG_H__ #include <fstream> // Libreria usada para el manejo de archivos #include <string> // Libreria usada para el manejo de Cadenas de Texto using namespace std; struct Log{ int cantidad; // Aqui se almacenara la cantidad de registros ofstream* archivo; // Puntero al archivo donde ser haran los registros }; /*Definición de Primitivas*/ /*------------------------------------------------------------------*/ /* pre: ninguna. post: el log queda listo para ser usado. log: estructura a ser inicializada. nombreArchivo: nombre del archivo donde se escribirán los mensajes. */ void inicializar (Log& log, string nombreArchivo); /*------------------------------------------------------------------*/ /* pre: log ha sido inicializado con la primitiva inicializar(). post: el log queda eliminado. log: instancia sobre la cual se aplica la primitiva. */ void destruir (Log& log); /*------------------------------------------------------------------*/ /* pre: log ha sido inicializado. post: agrega el mensaje al log con el siguiente formato: [fecha-hora] Mensaje. log: instancia sobre la cual se aplica la primitiva. mensaje: texto a escribir. */ void escribirMensaje (Log& log, string mensaje); /*------------------------------------------------------------------*/ /* pre: log ha sido inicializado. post: agrega el título al log con el formato: ******************************* título ******************************* log: instancia sobre la cual se aplica la primitiva. título: título a escribir. */ void escribirTitulo (Log& log, string titulo); /*------------------------------------------------------------------*/ /* pre: log ha sido inicializado. post: agrega un mensaje con la cantidad de mensajes escritos hasta ese momento con el formato: ------------------------------------------ [fecha-hora] Total de Mensajes: XX log: instancia sobre la cual se aplica la primitiva. */ void escribirTotalMensajes(Log& log); /*------------------------------------------------------------------*/ #endif
#include "log.h" // Declaracion del tipo y de las primitivas #include <time.h> // Libreria usada para obtener la fecha y hora using namespace std; void inicializar(Log& log,string nombreArchivo){ log.archivo = new ofstream(nombreArchivo.c_str()); // Se reserva memoria para el puntero al archivo log.cantidad=0; // Se inicializa el contador } void destruir(Log& log){ log.cantidad=0; log.archivo->close(); // Se cierra el archivo delete log.archivo; // Se libera la memoria reservada para el puntero log.archivo=NULL; // Se trunca el puntero } void escribirMensaje(Log& log, string mensaje){ time_t segundos=time(NULL); // Se obtiene la cantidad de segundos pasados desde el 1/1/1970 tm* fechaHora=localtime(&segundos); // Se procesa esa cantidad y se construye la estructura *log.archivo << "[" << fechaHora->tm_mday << "/"; // Se adjuntan *log.archivo << fechaHora->tm_mon+1 << "/"; // la fecha *log.archivo << 1900+fechaHora->tm_year << "-"; // y la hora. *log.archivo << fechaHora->tm_hour << ":"; // Luego *log.archivo << fechaHora->tm_min << ":"; // se *log.archivo << fechaHora->tm_sec << "]"; // adjunta el *log.archivo << mensaje << endl; // mensaje. log.cantidad++; // Se incrementa el contador } void escribirTitulo(Log& log, string titulo){ *log.archivo << "***************************" << endl; *log.archivo << titulo << endl; *log.archivo << "***************************" << endl; } void escribirTotalMensajes(Log& log){ *log.archivo << "-------------------------------" << endl; // Se adjunta la cantidad de mensajes *log.archivo << "Total mensajes: " << log.cantidad << endl; // con formato. }