Práctica 3 (20%) | P2 GIR Saltearse al contenido

Práctica 3 (20%)

A continuación se encuentra el enunciado de la práctica 3. Lee cuidadosamente el enunciado y sigue las instrucciones. Se recomienda consultar el apartado de Teoría para tratar de resolver dudas de concepto.

1 Cambios

1.1 Versión 1.0.0

  • Enunciado original.

2 Archivos de partida

  • Aquí se encuentran los archivos de partida. Descárgalos y utilízalos como base para resolver la práctica.

3 Objetivos

  • Seguir adquiriendo práctica y destreza con las características de C++.
  • Trabajar con punteros y memoria dinámica.
  • Aplicar técnicas de programación dirigida por eventos con la biblioteca boost::signals2.
  • Practicar el uso de estructuras, funciones y control de flujo en C++.
  • Reforzar el uso de referencias, desreferenciación de punteros y acceso mediante ->.

4 Algunas aclaraciones

  • En esta práctica trabajaremos con programación dirigida por eventos mediante el proyecto Boost. Necesitamos tener instalada la biblioteca boost::signals2.
  • Esta biblioteca se encuentra ya instalada en el Sistema Operativo de la EPS. Si usas un SO diferente pero basado en Ubuntu, puedes instalar la librería completa en el terminal con:
apt-get update
apt install libboost-all-dev
  • En el código de partida entregado junto a este enunciado se incluye un archivo mainp3.cc en el que verás una serie de funciones definidas y un ejemplo de uso. En la función main se conectan dichas funciones con las señales que se tendrán que implementar en el archivo p3.cc.
  • Ten en cuenta que las funciones conectadas a las señales pueden ser diferentes de las que se utilizarán para evaluar la práctica, pero el prototipo de la función será el mismo.
  • En esta práctica no debes mostrar ningún mensaje por pantalla en tu implementación de p3.cc. Cualquier mensaje que se muestre en la consola será responsabilidad de la función main o de cualquiera de las funciones conectadas a las señales.
  • Seguimos trabajando con struct, funciones, referencias, punteros y memoria dinámica.

Recomendación: antes de empezar, conviene repasar en teoría:

  • paso por referencia,
  • diferencia entre objeto y puntero,
  • desreferenciación (*),
  • obtención de direcciones (&),
  • acceso a campos mediante ->.

Otra recomendación importante: si recorres un std::vector y eliminas el elemento actual durante el recorrido, recuerda que los elementos posteriores se desplazan una posición a la izquierda (si representamos el vector como una secuencia de elementos de izquierda a derecha).

Puedes comprobar fácilmente el contenido del camión y de los almacenes en cualquier momento utilizando las funciones displayTruck y displayWarehouse que tienes implementadas en p3.h.

5 Enunciado

En esta práctica implementaremos un simulador sencillo de gestión de mercancías en un entorno logístico.

Un camión puede llegar a un almacén, descargar mercancías en él o cargar mercancías desde él.

Cada mercancía tendrá un tipo, y no todos los almacenes aceptarán todos los tipos de mercancía.

El sistema deberá ser capaz de saber si un camión está actualmente estacionado en algún almacén. Para ello, cada camión tendrá:

  • un indicador parked, que indica si el camión está aparcado,
  • un identificador current_warehouse_id, que indica en qué almacén está aparcado.

Además, el sistema deberá poder trabajar con una flota completa de camiones, consultando cuáles están aparcados en un almacén concreto y realizando operaciones masivas sobre todos ellos.

El sistema generará señales cuando ocurra alguna de las siguientes situaciones:

  • Se llena un almacén (warehouse_full_sig_t).
  • Se llena un camión (truck_full_sig_t).
  • Llega un camión a un almacén (truck_arrived_sig_t).
  • Una mercancía es rechazada por incompatibilidad (rejected_merch_sig_t).

Importante:

  • Cada mercancía se crea dinámicamente y se representa mediante un puntero (Merchandise*).
  • Tanto el camión como el almacén almacenan punteros a mercancías dentro de un std::vector.
  • Cuando una mercancía pasa de un contenedor a otro, no se copia. Lo que debe moverse es el puntero.
  • Una mercancía debe estar en un único lugar en cada momento.
  • La memoria de cada mercancía debe liberarse una sola vez.
  • Si un camión está en carretera, entonces parked == false y current_warehouse_id == 0.
  • Si un camión está aparcado, entonces parked == true y current_warehouse_id contendrá el identificador del almacén en el que está aparcado.

5.1 Estructuras de datos

Antes de comenzar con las funciones, es importante conocer las estructuras (struct) que se utilizan en esta práctica. Estas estructuras están definidas en el archivo p3.h. En todo caso, un id = 0 representará que no es un elemento válido. Asegúrate de seguir las instrucciones para cada función.

MerchandiseType

enum MerchandiseType {
GENERAL,
REFRIGERATED,
DANGEROUS
};
  • Representa el tipo de una mercancía.

Merchandise

struct Merchandise {
uint32_t id;
uint32_t units;
MerchandiseType type;
};
  • Representa una mercancía concreta.
  • id: identificador de la mercancía.
  • units: número de unidades que representa.
  • type: tipo de mercancía.

Truck

struct Truck {
uint32_t id;
uint32_t max_capacity;
uint32_t current_warehouse_id;
bool parked;
std::vector<Merchandise*> cargo;
};
  • Representa un camión.
  • id: identificador del camión.
  • max_capacity: número máximo de mercancías que puede transportar.
  • current_warehouse_id: identificador del almacén en el que está aparcado.
  • parked: indica si el camión está aparcado en un almacén.
  • cargo: vector de punteros a mercancías.

Warehouse

struct Warehouse {
uint32_t id;
uint32_t max_capacity;
bool accepts_general;
bool accepts_refrigerated;
bool accepts_dangerous;
std::vector<Merchandise*> stock;
};
  • Representa un almacén.
  • id: identificador del almacén.
  • max_capacity: número máximo de mercancías que puede almacenar.
  • accepts_general: indica si acepta mercancía general.
  • accepts_refrigerated: indica si acepta mercancía refrigerada.
  • accepts_dangerous: indica si acepta mercancía peligrosa.
  • stock: vector de punteros a mercancías.

5.2 Funciones auxiliares ya implementadas en p3.h

En el archivo p3.h se incluyen varias funciones auxiliares ya implementadas que pueden resultarte útiles durante el desarrollo y las pruebas:

string merchTypeToString(MerchandiseType type)

Devuelve una cadena de texto que representa el tipo de mercancía:

  • GENERAL"GEN"
  • REFRIGERATED"REF"
  • DANGEROUS"DAN"

void displayTruck(const Truck& truck)

Muestra el estado del camión en pantalla.

void displayWarehouse(const Warehouse& warehouse)

Muestra el estado del almacén en pantalla.

Estas funciones ya están implementadas en p3.h y no debes modificarlas.

5.3 Señales (boost::signals2)

En esta práctica se utiliza la biblioteca boost::signals2 para trabajar con programación dirigida por eventos. En p3.h puedes ver varios tipos de señales definidas, que puedes usar directamente en tu implementación.

warehouse_full_sig_t

using warehouse_full_sig_t = boost::signals2::signal<void(const Warehouse&)>;
  • Se activa cuando un almacén alcanza su capacidad máxima.
  • Recibe una referencia constante al Warehouse afectado.

truck_full_sig_t

using truck_full_sig_t = boost::signals2::signal<void(const Truck&)>;
  • Se activa cuando un camión alcanza su capacidad máxima.
  • Recibe una referencia constante al Truck afectado.

truck_arrived_sig_t

using truck_arrived_sig_t = boost::signals2::signal<void(const Truck&, const Warehouse&)>;
  • Se activa cuando un camión llega a un almacén.
  • Recibe una referencia constante al Truck y otra al Warehouse.

rejected_merch_sig_t

using rejected_merch_sig_t = boost::signals2::signal<void(const Merchandise&, const Warehouse&)>;
  • Se activa cuando una mercancía no puede entrar en un almacén porque ese almacén no acepta su tipo.
  • Recibe una referencia constante a la Merchandise rechazada y otra al Warehouse destino que lo ha rechazado.

Funciones de acceso a las señales

En p3.h también están declaradas varias funciones que devuelven una referencia a cada una de las señales del sistema:

warehouse_full_sig_t& get_warehouse_full_signal();
truck_full_sig_t& get_truck_full_signal();
truck_arrived_sig_t& get_truck_arrived_signal();
rejected_merch_sig_t& get_rejected_merch_signal();

Estas funciones permiten acceder a las señales tanto para conectar manejadores desde mainp3.cc como para lanzarlas desde p3.cc.

Por ejemplo, si en tu implementación quieres lanzar la señal de llegada de un camión, puedes hacerlo así:

get_truck_arrived_signal()(truck, warehouse);

Observa que primero se llama a la función get_..._signal() para obtener la señal, y después se usan paréntesis con los argumentos correspondientes para lanzarla. También puedes guardar en una variable el resultado de la función get_..._signal() y después utilizar dicha variable para lanzar la señal.

¿Cómo se conectan las señales?

En el archivo mainp3.cc se proporcionan funciones para manejar estos eventos y también el código para conectar las señales con estas funciones. Puedes conectar estas funciones a las señales usando .connect(). Por ejemplo:

get_warehouse_full_signal().connect(&onWarehouseFull);
get_truck_arrived_signal().connect(&onTruckArrived);
get_rejected_merch_signal().connect(&onRejectedMerch);

También es posible conectar una señal a una función lambda. En el fichero mainp3.cc tienes un ejemplo a modo de curiosidad. Una función lambda es una función anónima definida directamente en el punto en el que se utiliza (en este caso en la conexión). El ejemplo que tienes en los archivos de partida es el siguiente. No es necesario que sepas definir funciones lambda en esta asignatura. Este ejemplo se incluye únicamente para que veas que existen otras formas de conectar señales, además de las vistas en clase.

get_truck_full_signal().connect([&fleet](const Truck& t) {
std::cout << "[TRUCK FULL] Truck " << t.id
<< " is full and leaves warehouse "
<< t.current_warehouse_id << "\n";
for (Truck& truck : fleet) {
if (truck.id == t.id) {
departTruck(truck);
break;
}
}
});

Así, cuando una señal se dispare desde p3.cc, se ejecutará la función correspondiente. Puedes encontrar más información en el apartado de Teoría.

5.4 Funciones

A continuación se describen las funciones que debes implementar en p3.cc. Todas están declaradas en p3.h. No debes modificar la cabecera.

Truck createTruck(uint32_t id, uint32_t max_capacity)

Descripción:
Crea y devuelve una estructura Truck.

Comportamiento esperado:

  • El camión se inicializa con:
    • id
    • max_capacity
    • current_warehouse_id = 0
    • parked = false
    • cargo vacío
  • Si id == 0, se devolverá empty_truck.
  • Si max_capacity no está entre 1 y 50 (ambos incluídos), se devolverá empty_truck.

Warehouse createWarehouse(uint32_t id, uint32_t max_capacity, bool accepts_general, bool accepts_refrigerated, bool accepts_dangerous)

Descripción:
Crea y devuelve una estructura Warehouse.

Comportamiento esperado:

  • El almacén se inicializa con:
    • id
    • max_capacity
    • los indicadores de compatibilidad recibidos
    • stock vacío
  • Si id == 0, se devolverá empty_warehouse.
  • Si max_capacity no está entre 1 y 200 (ambos incluidos), se devolverá empty_warehouse.
  • Si el almacén no acepta ningún tipo de mercancía, se devolverá empty_warehouse.

Merchandise* createMerchandise(uint32_t id, uint32_t units, MerchandiseType type)

Descripción:
Crea una nueva mercancía.

Comportamiento esperado:

  • La mercancía se inicializa con los valores recibidos.
  • Si id == 0, la función devolverá nullptr.
  • Si units no está entre 1 y 500 (ambos incluidos), la función devolverá nullptr.

string merchandiseToString(const Merchandise* merch)

Descripción:
Devuelve una cadena con la representación textual de una mercancía.

Comportamiento esperado:

  • Si merch == nullptr, la función devolverá exactamente la cadena "null".
  • En otro caso devolverá una cadena con este formato exacto:
{id=<id>,u=<units>,t=<tipo>}
  • donde:
    • <id> es el identificador de la mercancía,
    • <units> es el número de unidades,
    • <tipo> será GEN, REF o DAN según corresponda.

Importante:

  • La función recibe un puntero a Merchandise, no un objeto.
  • Puedes apoyarte en la función merchTypeToString() para obtener la representación textual del tipo.
  • Puedes utilizar la función std::to_string(...) para convertir valores numéricos en cadenas de texto (string).

Ejemplos:

{id=101,u=5,t=GEN}
{id=302,u=1,t=REF}
null

bool addToTruck(Truck& truck, Merchandise* merch)

Descripción:
Añade una mercancía al camión.

Comportamiento esperado:

  • Si se cumplen todas las condiciones siguientes:

    • el camión existe (tiene id válido),
    • la mercancía no es nula,
    • y el camión tiene espacio disponible, entonces se añade el puntero al final del vector cargo y devuelve true.
  • La función devolverá false en caso contrario.

Importante:
Esta función no debe lanzar señales.

bool addToWarehouse(Warehouse& warehouse, Merchandise* merch)

Descripción:
Añade una mercancía al almacén.

Comportamiento esperado:

  • Si el almacén existe (tiene id válido), la mercancía no es nula, hay espacio disponible y la mercancía es compatible:
    • se añade el puntero al final del vector stock y se devuelve true.
  • Si no puede insertarse, la función devuelve false.

Importante:
Esta función no debe lanzar señales.

bool arriveTruck(Truck& truck, const Warehouse& warehouse)

Descripción:
Registra la llegada de un camión a un almacén.

Comportamiento esperado:

  • Si el camión y el almacén existen (tienen id válido), y el camión no está ya aparcado:
    • parked pasa a valer true,
    • current_warehouse_id pasa a valer warehouse.id,
    • se lanza la señal truck_arrived_sig_t,
    • devuelve true.
  • Si no puede realizarse la operación, la función devuelve false y no se cambiará el estado del camión.

void departTruck(Truck& truck)

Descripción:
Hace que un camión abandone el almacén en el que estuviera aparcado.

Comportamiento esperado:

  • Si el camión estaba aparcado:
    • parked pasa a valer false,
    • current_warehouse_id pasa a valer 0.
  • Si no estaba aparcado o si tiene un id incorrecto, no hará nada.

uint32_t unloadTruck(Truck& truck, Warehouse& warehouse)

Descripción:
Descarga mercancías desde un camión hacia un almacén.

Comportamiento esperado:

  • La operación solo puede realizarse si el camión está aparcado en ese almacén y si el camión y el almacén tienen un id válido. En caso contrario, la función devolverá 0 y no modificará ni el camión ni el almacén.
  • Se recorrerá el vector cargo del camión en orden secuencial.
  • Para cada mercancía:
    • si el almacén tiene hueco y la mercancía es compatible, se moverá al final del almacén,
    • si la mercancía no es compatible, permanecerá en el camión y se lanzará rejected_merch_sig_t por cada mercancía incompatible.
  • La función devolverá el número de mercancías movidas.
  • Si al terminar la operación el almacén queda lleno, se lanzará warehouse_full_sig_t una vez.
  • Las mercancías movidas al almacén deben conservar el orden relativo en el que aparecen originalmente en cargo.
  • Las mercancías que permanezcan en el camión también deben conservar su orden original.

Importante:
La mercancía no se copia, solo se mueve el puntero.

uint32_t loadTruck(Truck& truck, Warehouse& warehouse)

Descripción:
Carga mercancías desde un almacén hacia un camión.

Comportamiento esperado:

  • La operación solo puede realizarse si el camión está aparcado en ese almacén y si el camión y el almacén tienen un id válido. En caso contrario, la función devolverá 0 y no modificará ni el camión ni el almacén.
  • Mientras el almacén tenga mercancías y el camión tenga hueco:
    • se tomará la primera mercancía del almacén,
    • se insertará al final del vector cargo del camión,
    • se eliminará del vector stock del almacén.
    • se repite hasta que recorramos el almacen completo.
  • La función devolverá el número de mercancías movidas.
  • Si al terminar la operación el camión queda lleno, se lanzará truck_full_sig_t una vez.
  • Las mercancías se cargarán siguiendo el orden en el que aparecen en stock, comenzando siempre por la primera.

Importante:
La mercancía no se copia, solo se mueve el puntero.

vector<Truck*> getTrucksInWarehouse(const Warehouse& warehouse, vector<Truck>& all_trucks)

Descripción:
Devuelve un vector con punteros a todos los camiones que están aparcados en el almacén recibido.

Comportamiento esperado:

  • La función recibe:
    • el almacén del que se quieren obtener los camiones,
    • la flota completa de camiones del programa.
  • Se devolverán punteros a los camiones que estén aparcados en el almacén recibido y que tengan un id válido.
  • Si no hay camiones aparcados en ese almacén o si el almacén tiene un id incorrecto, se devolverá un vector vacío.
  • Los camiones se devolverán en el mismo orden en que aparecen en all_trucks.

uint32_t unloadAllTrucksInWarehouse(Warehouse& warehouse, vector<Truck>& all_trucks)

Descripción:
Descarga mercancías desde todos los camiones aparcados en un almacén hacia ese mismo almacén.

Comportamiento esperado:

  • La función debe obtener los camiones aparcados en el almacén usando getTrucksInWarehouse().
  • Después, debe intentar descargar cada uno de esos camiones sobre el almacén.
  • La función devolverá el número total de mercancías movidas entre todos los camiones procesados.
  • Las señales correspondientes se lanzarán a través de las llamadas a unloadTruck().
  • Los camiones se procesarán en el mismo orden en que son devueltos por getTrucksInWarehouse().
  • Si el almacén no es válido (id = 0), la función devolverá 0 y no modificará ni el almacén ni ningún camión.

uint32_t loadAllTrucksInWarehouse(Warehouse& warehouse, vector<Truck>& all_trucks)

Descripción:
Carga mercancías desde un almacén hacia todos los camiones aparcados en ese almacén.

Comportamiento esperado:

  • La función debe obtener los camiones aparcados en el almacén usando getTrucksInWarehouse().
  • Después, debe intentar cargar cada uno de esos camiones desde el almacén.
  • La función devolverá el número total de mercancías movidas entre todos los camiones procesados.
  • Las señales correspondientes se lanzarán a través de las llamadas a loadTruck().
  • Los camiones se procesarán en el mismo orden en que son devueltos por getTrucksInWarehouse().
  • Si el almacén no es válido (id = 0), la función devolverá 0 y no modificará ni el almacén ni ningún camión.

void freeTruck(Truck& truck)

Descripción:
Libera toda la memoria dinámica asociada al camión.

Comportamiento esperado:

  • Debe liberar cada una de las mercancías que todavía sigan almacenadas en el camión.
  • Tras liberar la memoria, el camión debe quedar convertido en empty_truck.

void freeWarehouse(Warehouse& warehouse)

Descripción:
Libera toda la memoria dinámica asociada al almacén.

Comportamiento esperado:

  • Debe liberar cada una de las mercancías que todavía sigan almacenadas en el almacén.
  • Tras liberar la memoria, el almacén debe quedar convertido en empty_warehouse.

5.5 Notas importantes sobre memoria

  • Si una mercancía se mueve del camión a un almacén, deja de pertenecer al camión y pasa a pertenecer al almacén. Lo mismo ocurrirá en el sentido contrario.
  • Nunca debe haber dos contenedores almacenando simultáneamente la misma mercancia. Si ocurre esto, lo podrás ver fácilmente si tratas de liberar toda la memoria asociada a los camiones y a los almacenes. Valgrind puede serte útil.
  • Cuando una mercancía se mueve, se mueve el puntero, no una copia de la estructura.
  • Si estás recorriendo un std::vector y eliminas el elemento actual, presta atención a cómo actualizas el índice o iterador del recorrido.

5.6 Salida esperada con el mainp3.cc proporcionado

Al compilar y ejecutar el archivo mainp3.cc junto con tu implementación (p3.cc), deberías obtener una salida similar a la siguiente:

[ARRIVAL] Truck 10 arrived at warehouse 1
[ARRIVAL] Truck 20 arrived at warehouse 1
[ARRIVAL] Truck 30 arrived at warehouse 2
--- Initial state ---
Truck 10 [parked at warehouse 1]: {id=101,u=5,t=GEN} {id=102,u=3,t=DAN}
Truck 20 [parked at warehouse 1]: {id=201,u=4,t=REF} {id=202,u=6,t=GEN}
Truck 30 [parked at warehouse 2]: {id=302,u=1,t=REF} {id=301,u=8,t=DAN}
Warehouse 1: empty
Warehouse 2: empty
--- Trucks parked in warehouse 1 ---
Truck 10
Truck 20
[REJECTED] {id=102,u=3,t=DAN} cannot enter warehouse 1
--- After unloading all trucks in warehouse 1 ---
Truck 10 [parked at warehouse 1]: {id=102,u=3,t=DAN}
Truck 20 [parked at warehouse 1]: empty
Truck 30 [parked at warehouse 2]: {id=302,u=1,t=REF} {id=301,u=8,t=DAN}
Warehouse 1: {id=101,u=5,t=GEN} {id=201,u=4,t=REF} {id=202,u=6,t=GEN}
Warehouse 2: empty
[TRUCK FULL] Truck 10 is full and leaves warehouse 1
--- After loading all trucks in warehouse 1 ---
Truck 10 [on the road]: {id=102,u=3,t=DAN} {id=101,u=5,t=GEN}
Truck 20 [parked at warehouse 1]: {id=201,u=4,t=REF} {id=202,u=6,t=GEN}
Truck 30 [parked at warehouse 2]: {id=302,u=1,t=REF} {id=301,u=8,t=DAN}
Warehouse 1: empty
Warehouse 2: empty
[REJECTED] {id=302,u=1,t=REF} cannot enter warehouse 2
[WAREHOUSE FULL] Warehouse 2 is full with 2 merchandise item(s)
--- Final state ---
Truck 10 [on the road]: {id=102,u=3,t=DAN} {id=101,u=5,t=GEN}
Truck 20 [parked at warehouse 1]: {id=201,u=4,t=REF} {id=202,u=6,t=GEN}
Truck 30 [parked at warehouse 2]: {id=302,u=1,t=REF}
Warehouse 1: empty
Warehouse 2: {id=401,u=2,t=GEN} {id=301,u=8,t=DAN}

6 Uso de make

El fichero Makefile incluye la configuración de la herramienta make con varias opciones que pueden resultarte útiles. A continuación tienes una lista de las cosas que puedes hacer:

ComandoDescripción
makeCompila y enlaza el código generando el ejecutable p3.
make runCompila, enlaza y ejecuta la práctica.
make runvCompila, enlaza y ejecuta la práctica con Valgrind.
make vstatsMuestra un resumen de pérdidas de memoria detectadas por Valgrind.
make debugCompila y abre el ejecutable con gdb en modo texto.
make tgzBorra archivos compilados y genera el archivo comprimido irp2-p3.tgz.
make cleanElimina los archivos compilados (ejecutables, objetos, etc.).
  • Si has compilado tu programa y vuelves a compilar sin modificar nada del código, make detectará que no necesita compilar nada. Si aún así necesitas recompilar, puedes usar primero make clean y después make.

  • Para la ejecución con Valgrind necesitas tener instalado el programa valgrind. Puedes instalarlo en Linux así:

    • sudo apt-get install valgrind
  • Valgrind te será muy útil para detectar:

    • accesos a memoria incorrectos,
    • uso de punteros no válidos,
    • y fugas de memoria al no liberar correctamente las mercancías creadas dinámicamente.

7 Archivos

  • p3.h: cabecera con los tipos de datos y prototipos de las funciones que tienes que implementar.
  • p3.cc: implementación de las funciones. No debe contener main. Es el fichero que se va a evaluar.
  • mainp3.cc: contiene algunas pruebas básicas del programa y la conexión de las señales. Puedes modificarlo para hacer tus propias pruebas.
  • Makefile: se recomienda su uso para compilar de forma sencilla.

8 Entrega. Requisitos técnicos

  • Requisitos que tiene que cumplir este trabajo práctico para considerarse válido y ser evaluado (si no se cumple alguno de los requisitos, la calificación será cero):

  • El archivo entregado se llama irp2-p3.tgz (todo en minúsculas). Dentro de dicho archivo habrá una carpeta llamada irp2-p3 que contendrá al menos el archivo p3.cc.

  • El archivo comprimido lo puedes crear así en el terminal:

tar cfz irp2-p3.tgz irp2-p3
  • También puedes emplear el archivo Makefile que tienes en la carpeta de la práctica para generar el fichero de la entrega, tal y como hemos visto en clase de prácticas:
make tgz
  • Al descomprimir el archivo irp2-p3.tgz se crea un directorio de nombre irp2-p3 (todo en minúsculas).

  • Dentro del directorio irp2-p3 estará al menos el archivo p3.cc (todo en minúsculas). No pasa nada si incluyes más archivos, se ignorarán si no son necesarios para la corrección.

  • Recuerda que los ficheros .h no se deben modificar, de lo contrario tus ficheros .cc podrían no compilar con el corrector. No es necesario entregarlos; si se hace no pasa nada.

  • Las estructuras, funciones y señales implementadas se llaman como se indica en el enunciado, respetando en todo caso el uso de mayúsculas y minúsculas. También es imprescindible respetar estrictamente los textos y los formatos de salida que se indican en este enunciado.

  • Al principio de todos los ficheros fuente (.h y .cc) entregados y escritos por ti se debe incluir un comentario con el nombre y el NIF (o equivalente) de la persona que entrega la práctica, como en el siguiente ejemplo:

// NIF: 12345678-Z
// NOMBRE: GARCIA PEREZ, LAURA
  • Un error de compilación o de enlace implicará un cero en esa parte de la práctica.

  • Se utilizará Valgrind para comprobar que no haya fugas de memoria en tu programa. Puedes instalarlo y probarlo antes de realizar la entrega para asegurarte de corregir posibles errores relacionados con la gestión de memoria dinámica.

  • En este caso, la estructura mínima del fichero que debes entregar es la siguiente:

irp2-p3.tgz
└── irp2-p3
└── p3.cc
  • Lugar y fecha de entrega: recuerda que las entregas se realizan siempre en (y solo en) https://pracdlsi.dlsi.ua.es en las fechas y condiciones allí publicadas. Puedes entregar la práctica tantas veces como quieras; solo se corregirá la última entrega. El usuario y contraseña para entregar prácticas es el mismo que se utiliza en UACloud.

9 Detección de plagios/copias

  • En el Grado en Ingeniería Robótica, la Programación es una materia muy importante. La manera más efectiva de aprender a programar es programando y, por tanto, haciendo las prácticas correspondientes además de otros programas.

  • Tratar de aprobar las asignaturas de programación sin programar (copiando) es complicado y, además, te planteará problemas para seguir otras asignaturas y también en tu futura vida laboral.

  • En una asignatura como Programación-II es difícil que alguien que no ha hecho las prácticas supere los exámenes de teoría o el de recuperación de prácticas.

  • IMPORTANTE:

    • Cada práctica debe ser un trabajo original de la persona que la entrega.
    • En caso de detectarse indicios de copia de una o más prácticas, se tomarán las medidas disciplinarias correspondientes, informando a las direcciones de Departamento y de la EPS por si hubiera lugar a otras medidas disciplinarias adicionales.