En este estudio de caso, desarrollaremos un sistema de procesamiento de datos en Ada. Este sistema leerá datos de un archivo, procesará la información y generará un informe basado en los datos procesados. Este ejercicio integrará varios conceptos aprendidos en los módulos anteriores, como manejo de archivos, estructuras de control, subprogramas y tipos de datos avanzados.

Objetivos del Estudio de Caso

  1. Lectura de datos desde un archivo: Aprender a manejar archivos en Ada para leer datos.
  2. Procesamiento de datos: Utilizar estructuras de control y subprogramas para procesar la información.
  3. Generación de informes: Escribir los resultados procesados en un archivo de salida.
  4. Aplicación de mejores prácticas: Implementar un código limpio y eficiente siguiendo las mejores prácticas de programación en Ada.

Paso 1: Definición del Problema

Requisitos

  • Leer un archivo de entrada que contiene datos de ventas.
  • Procesar los datos para calcular el total de ventas por producto.
  • Generar un informe que muestre el total de ventas por producto en un archivo de salida.

Estructura del Archivo de Entrada

El archivo de entrada ventas.txt tiene el siguiente formato:

Producto1, 10
Producto2, 5
Producto1, 7
Producto3, 12
Producto2, 3

Estructura del Archivo de Salida

El archivo de salida informe.txt debe tener el siguiente formato:

Producto1: 17
Producto2: 8
Producto3: 12

Paso 2: Diseño del Sistema

Estructura del Programa

  1. Lectura de Datos: Leer los datos del archivo de entrada y almacenarlos en una estructura adecuada.
  2. Procesamiento de Datos: Calcular el total de ventas por producto.
  3. Generación del Informe: Escribir los resultados en un archivo de salida.

Diagrama de Flujo

+-------------------+
| Leer archivo      |
| de entrada        |
+-------------------+
        |
        v
+-------------------+
| Procesar datos    |
| (calcular totales)|
+-------------------+
        |
        v
+-------------------+
| Generar informe   |
| en archivo salida |
+-------------------+

Paso 3: Implementación

Lectura de Datos

Código

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;

procedure Leer_Datos is
   type Producto_Venta is record
      Producto : Unbounded_String;
      Cantidad : Integer;
   end record;

   type Ventas_Array is array (Natural range <>) of Producto_Venta;
   Ventas : Ventas_Array(1 .. 100); -- Asumimos un máximo de 100 registros
   Linea : Unbounded_String;
   Index : Natural := 1;

   Archivo : File_Type;
begin
   Open (Archivo, In_File, "ventas.txt");

   while not End_Of_File(Archivo) loop
      Get_Line(Archivo, Linea);
      declare
         Producto : Unbounded_String;
         Cantidad : Integer;
         Coma_Pos : Natural;
      begin
         Coma_Pos := Index(Linea, ',');
         Producto := To_Unbounded_String(Linea(1 .. Coma_Pos - 1));
         Cantidad := Integer'Value(Linea(Coma_Pos + 1 .. Length(Linea)));
         Ventas(Index) := (Producto, Cantidad);
         Index := Index + 1;
      end;
   end loop;

   Close(Archivo);
end Leer_Datos;

Explicación

  • Lectura del archivo: Utilizamos Ada.Text_IO para abrir y leer el archivo ventas.txt.
  • Almacenamiento de datos: Los datos se almacenan en un array de registros Ventas_Array.
  • Procesamiento de cada línea: Cada línea se divide en producto y cantidad utilizando la posición de la coma.

Procesamiento de Datos

Código

procedure Procesar_Datos is
   type Producto_Total is record
      Producto : Unbounded_String;
      Total    : Integer := 0;
   end record;

   type Totales_Array is array (Natural range <>) of Producto_Total;
   Totales : Totales_Array(1 .. 100); -- Asumimos un máximo de 100 productos
   Total_Index : Natural := 1;

   function Buscar_Producto (Producto : Unbounded_String) return Natural is
   begin
      for I in Totales'Range loop
         if Totales(I).Producto = Producto then
            return I;
         end if;
      end loop;
      return 0;
   end Buscar_Producto;

begin
   for I in Ventas'Range loop
      declare
         Producto : Unbounded_String := Ventas(I).Producto;
         Cantidad : Integer := Ventas(I).Cantidad;
         Pos      : Natural;
      begin
         Pos := Buscar_Producto(Producto);
         if Pos = 0 then
            Totales(Total_Index) := (Producto, Cantidad);
            Total_Index := Total_Index + 1;
         else
            Totales(Pos).Total := Totales(Pos).Total + Cantidad;
         end if;
      end;
   end loop;
end Procesar_Datos;

Explicación

  • Estructura de Totales: Utilizamos un array de registros Totales_Array para almacenar el total de ventas por producto.
  • Búsqueda de Producto: La función Buscar_Producto busca un producto en el array de totales.
  • Actualización de Totales: Si el producto ya existe, se actualiza su total; de lo contrario, se añade un nuevo registro.

Generación del Informe

Código

procedure Generar_Informe is
   Archivo : File_Type;
begin
   Create (Archivo, Out_File, "informe.txt");

   for I in Totales'Range loop
      if Totales(I).Producto /= Null_Unbounded_String then
         Put_Line(Archivo, To_String(Totales(I).Producto) & ": " & Integer'Image(Totales(I).Total));
      end if;
   end loop;

   Close(Archivo);
end Generar_Informe;

Explicación

  • Creación del archivo de salida: Utilizamos Ada.Text_IO para crear y escribir en el archivo informe.txt.
  • Escritura de datos: Iteramos sobre el array de totales y escribimos cada producto y su total en el archivo.

Paso 4: Ejecución del Programa

Código Completo

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO; use Ada.Strings.Unbounded.Text_IO;

procedure Sistema_Procesamiento_Datos is
   type Producto_Venta is record
      Producto : Unbounded_String;
      Cantidad : Integer;
   end record;

   type Ventas_Array is array (Natural range <>) of Producto_Venta;
   Ventas : Ventas_Array(1 .. 100); -- Asumimos un máximo de 100 registros
   Linea : Unbounded_String;
   Index : Natural := 1;

   Archivo : File_Type;

   procedure Leer_Datos is
   begin
      Open (Archivo, In_File, "ventas.txt");

      while not End_Of_File(Archivo) loop
         Get_Line(Archivo, Linea);
         declare
            Producto : Unbounded_String;
            Cantidad : Integer;
            Coma_Pos : Natural;
         begin
            Coma_Pos := Index(Linea, ',');
            Producto := To_Unbounded_String(Linea(1 .. Coma_Pos - 1));
            Cantidad := Integer'Value(Linea(Coma_Pos + 1 .. Length(Linea)));
            Ventas(Index) := (Producto, Cantidad);
            Index := Index + 1;
         end;
      end loop;

      Close(Archivo);
   end Leer_Datos;

   procedure Procesar_Datos is
      type Producto_Total is record
         Producto : Unbounded_String;
         Total    : Integer := 0;
      end record;

      type Totales_Array is array (Natural range <>) of Producto_Total;
      Totales : Totales_Array(1 .. 100); -- Asumimos un máximo de 100 productos
      Total_Index : Natural := 1;

      function Buscar_Producto (Producto : Unbounded_String) return Natural is
      begin
         for I in Totales'Range loop
            if Totales(I).Producto = Producto then
               return I;
            end if;
         end loop;
         return 0;
      end Buscar_Producto;

   begin
      for I in Ventas'Range loop
         declare
            Producto : Unbounded_String := Ventas(I).Producto;
            Cantidad : Integer := Ventas(I).Cantidad;
            Pos      : Natural;
         begin
            Pos := Buscar_Producto(Producto);
            if Pos = 0 then
               Totales(Total_Index) := (Producto, Cantidad);
               Total_Index := Total_Index + 1;
            else
               Totales(Pos).Total := Totales(Pos).Total + Cantidad;
            end if;
         end;
      end loop;
   end Procesar_Datos;

   procedure Generar_Informe is
      Archivo : File_Type;
   begin
      Create (Archivo, Out_File, "informe.txt");

      for I in Totales'Range loop
         if Totales(I).Producto /= Null_Unbounded_String then
            Put_Line(Archivo, To_String(Totales(I).Producto) & ": " & Integer'Image(Totales(I).Total));
         end if;
      end loop;

      Close(Archivo);
   end Generar_Informe;

begin
   Leer_Datos;
   Procesar_Datos;
   Generar_Informe;
end Sistema_Procesamiento_Datos;

Ejecución

  1. Compilación: Compila el programa utilizando el compilador de Ada.
    gnatmake sistema_procesamiento_datos.adb
    
  2. Ejecución: Ejecuta el programa.
    ./sistema_procesamiento_datos
    

Conclusión

En este estudio de caso, hemos desarrollado un sistema de procesamiento de datos en Ada que lee datos de un archivo, los procesa y genera un informe. Este ejercicio ha integrado varios conceptos clave de Ada, como el manejo de archivos, estructuras de control, subprogramas y tipos de datos avanzados. Al completar este estudio de caso, deberías tener una comprensión más profunda de cómo aplicar estos conceptos en un proyecto real.

Resumen de Conceptos Aprendidos

  • Manejo de Archivos: Lectura y escritura de archivos en Ada.
  • Estructuras de Control: Uso de bucles y condicionales para procesar datos.
  • Subprogramas: Modularización del código mediante procedimientos y funciones.
  • Tipos de Datos Avanzados: Uso de registros y arrays para almacenar y manipular datos.

Preparación para el Siguiente Tema

En el próximo estudio de caso, aplicaremos estos conceptos en un contexto de sistemas embebidos, lo que nos permitirá explorar las capacidades de Ada en entornos de tiempo real y sistemas con recursos limitados.

© Copyright 2024. Todos los derechos reservados