Prácticas de Programación
PR3 - 20232
Fecha límite de entrega: 04 / 06 / 2024
Formato y fecha de entrega
Hay que entregar la práctica antes del día 4 de junio de 2024 a las 23:59.
Se debe entregar un archivo en formato ZIP, que contenga una carpeta UOC20232
con el directorio principal de vuestro proyecto, siguiendo la estructura de carpetas y
nombres de archivos especificados en el enunciado de la práctica. No debe
contener ningún archivo ZIP en su interior. Esta carpeta debe contener:
● Un fichero [Link] con el siguiente formato (ver ejemplo):
Formato:
Correo electrónico UOC
Apellidos, Nombre
Sistema operativo utilizado
Ejemplo:
estudiante1@[Link]
Apellido1 Apellido2, Nombre
Windows 10
● Los ficheros de prueba sin modificaciones.
● Los ficheros *.c y *.h resultantes de los ejercicios realizados.
● Todos los ficheros deben estar dentro de las carpetas correctas (src,
test, …).
● Si se ha utilizado el entorno CodeLite: los ficheros .workspace y
.project que definen el espacio de trabajo y los proyectos de Codelite.
La entrega debe realizarse en el apartado de entregas de EC del aula de teoría
antes de la fecha límite de la entrega. Únicamente el último envío dentro del
período establecido será evaluado.
El incumplimiento del formato de entrega especificado anteriormente puede suponer
un suspenso de la práctica.
Práctica 3 – Prácticas de programación 20232 pág.1
Objetivos
● Saber interpretar y seguir el código de terceras personas.
● Saber compilar proyectos de código organizados en carpetas y librerías.
● Saber implementar un proyecto de código a partir de su especificación.
Criterios de corrección:
Cada ejercicio tiene asociada su puntuación sobre el total de la actividad. Se
valorará tanto que las respuestas sean correctas como que también sean
completas.
● No seguir el formato de entrega, tanto por lo que se refiere al tipo y nombre
de los ficheros como al contenido solicitado, comportará una penalización
importante o la cualificación con una D de la actividad.
● El código entregado debe compilar para ser evaluado. Si compila, se
valorará:
○ Que funcionen tal como se describe en el enunciado.
○ Que obtenga el resultado esperado dadas unas condiciones y datos
de entrada diseñadas (pruebas proporcionadas). No es necesario
pasar todos los tests pero por lo menos debe mostrarse el resultado de
estos por pantalla.
○ Que se respeten los criterios de estilo y que el código esté
debidamente comentado. Se valorará especialmente el uso de
comentarios en inglés.
○ Que las estructuras utilizadas sean las correctas.
○ Que se separe correctamente la declaración e implementación de
las acciones y funciones, utilizando los ficheros correctos.
○ El grado de optimización en tiempo y recursos utilizados en la
solución entregada.
○ Que se realice una gestión de memoria adecuada, liberando la
memoria cuando sea necesario.
En esta práctica sólo se podrán modificar los archivos api.c, api.h, do.h, do.c,
vineyardplot.h, vineyardplot.c, weighing.h, weighing.c, winegrower.h y
winegrower.c que serán los archivos a subir a la herramienta DSLab.
Práctica 3 – Prácticas de programación 20232 pág.2
Aviso
Aprovechamos para recordar que está totalmente prohibido copiar en las PECs y
prácticas de la asignatura. Se entiende que puede haber un trabajo o comunicación
entre los estudiantes durante la realización de la actividad, pero la entrega de esta
debe que ser individual y diferenciada del resto. Las entregas serán analizadas con
herramientas de detección de plagio.
Así pues, las entregas que contengan alguna parte idéntica respecto a entregas de
otros estudiantes serán consideradas copias y todos los implicados (sin que sea
relevante el vínculo existente entre ellos) suspenderán la actividad entregada.
Guía citación: [Link]
Monográfico sobre plagio:
[Link]
Observaciones
En este documento se utilizan los siguientes símbolos para hacer referencia a los
bloques de diseño y programación:
Indica que el código mostrado es en lenguaje algorítmico.
Indica que el código mostrado es en lenguaje C.
Muestra la ejecución de un programa en lenguaje C.
Práctica 3 – Prácticas de programación 20232 pág.3
Análisis dinámico
En esta actividad se utiliza memoria dinámica, que requiere que el programador
reserve, inicialice y libere la memoria. Para ayudar a detectar memoria que no se ha
liberado correctamente, o errores en las operaciones con punteros relacionadas,
hay herramientas que ejecutan un análisis dinámico del programa. Una herramienta
de código abierto muy empleada es Valgrind ([Link] La utilización de
esta herramienta queda fuera del ámbito del curso.
Para entender el significado de los códigos de error, podéis consultar el siguiente
enlace, donde encontraréis ejemplos de código que os ayudarán a entender cuando
se dan estos errores:
[Link]
DSLab
Siguiendo con la misma dinámica que en la práctica anterior, se usará la
herramienta DSLab ([Link] Esta herramienta también se utiliza
en otras asignaturas y tiene como objetivo:
● Proporcionar un entorno común en el que evaluar los ejercicios de
codificación.
Os aconsejamos realizar envíos periódicos a la herramienta de los diferentes
ejercicios de código, ya que os permitirá detectar posibles errores antes de la
entrega final. Tened presente que es la herramienta utilizada como base para
corregir vuestros códigos, y que no se corregirá ningún código en otro
entorno o máquina. Así pues, si vuestro código no funciona en la herramienta
DSLab, se considerará que no funciona, aunque lo haga en vuestro ordenador.
En todo caso, hay que tener presente que las entregas finales deben seguir
haciéndose en el apartado correspondiente del aula, tal como indica el
enunciado. Esta herramienta es una ayuda adicional que ponemos a vuestra
disposición, y en ningún caso es obligatorio su utilización.
Práctica 3 – Prácticas de programación 20232 pág.4
La información básica que os será de utilidad al utilizar DSLab:
● DSLab considera la entrega correcta únicamente si esta pasa todos los tests.
● Se muestra un resumen rápido del número de tests pasados. Por norma
general no será necesario pasarlos todos para aprobar la entrega.
● En los detalles se muestra:
○ El detalle de los tests pasados y de los que han fallado.
○ Es posible descargar un fichero con el texto que el programa muestra
por pantalla (salida estándar). Se ha incluido el uso de valgrind en la
salida estándar de manera que en este apartado podréis ver el informe
sobre la gestión de la memoria. Es recomendable revisar esta parte
para asegurarse de que se hace un uso correcto de los punteros y de
la memoria.
● Existe también un log de ejecución que guarda la evolución de la ejecución
del programa. Si debido a una codificación incorrecta el programa falla y no
es capaz de mostrar el resultado de los tests, se debe revisar este log para
determinar en qué punto se interrumpió la ejecución.
Nota: aunque DSLab es un sistema robusto y utilizado en varias asignaturas de la
UOC, para esta asignatura en concreto está en fase de pruebas. Si encontráis algún
problema indicadlo a los profesores para que podamos corregir cualquier incidencia.
Práctica 3 – Prácticas de programación 20232 pág.5
Enunciado
El punto de partida de esta práctica es la solución oficial de la PR2. El código base
del enunciado incluye todos los archivos necesarios de las actividades anteriores,
con los que veréis que todos los tests de la PR1 y PR2 pasan correctamente.
En esta práctica se realiza una pequeña modificación a la estructura de las pesadas
(tWeighing) y a la estructura de los viñedos (tVineyardplot) para añadir un nueva
enumeración de uva que nos servirá luego para realizar algunas búsquedas y
ordenaciones de los datos.
type
tVineyardPlot = record
code : string;
doCode : string;
weight: float;
weights: tWeighingList;
grapeVariety : tGrapeVariety;
end record
tWeighingList = record
first : pointer to tWeighingNode;
last : pointer to tWeighingNode;
end record
tWeighingNode = record
elem : tWeighing;
prev : pointer to tWeighingNode;
next : pointer to tWeighingNode;
end record
tWeighing = record
code : string;
weight : float;
harvestDay : tDate;
grapeVariety : tGrapeVariety;
end record
tDO = record
code : string;
name : string;
winegrowers: tWinegrowerList;
avgCropField: real;
vineyards: tVineyardPlotData;
end record
tDOData = record
elems : pointer to tDO;
count : integer;
end record
end type
Práctica 3 – Prácticas de programación 20232 pág.6
Ejercicio 1: Gestión de la variedad de uva [5%]
En este ejercicio vamos a usar una nueva enumeración que se puede encontrar
definida en grapevariety.h y que nos permitirá posteriormente centrarnos en las
funciones de búsqueda y ordenación. La enumeración GrapeVariety hace
referencia a la variedad de la uva.
a) Consideraremos que un viñedo está compuesto por una única variedad de
uva. Modifica la definición del tipo de datos Vineyard plot en el fichero
vineyardplot.h, para añadir una nueva variable llamada grapeVariety que
sea del tipo enumerativo tGrapeVariety. Esta variable representa la variedad
de uva actual del viñedo.
Nota: Para permitir que los tests de los siguientes ejercicios compilen ya se ha
añadido una variable con este nombre pero del tipo equivocado.
b) Modifica los métodos vineyardplot_init y vineyardplot_cpy en el fichero
vineyardplot.c para asignar el parámetro adicional que hemos añadido
grapeVariety al viñedo.
c) Debido a que la variedad de uva puede variar en el tiempo, también hay que
añadir la variedad de uva en las pesadas. Modifica la definición del tipo de
datos tWeighing en el fichero weighing.h para añadir una nueva variable
llamada grapeVariety del tipo enumerativo tGrapeVariety.
Nota: Para permitir que los tests de los siguientes ejercicios compilen ya se ha
añadido una variable con este nombre pero del tipo equivocado.
d) Modifica el método weighing_init y weighing_cpy en el fichero weighing.c
para asignar el parámetro adicional que hemos añadido grapeVariety a la
pesada.
Práctica 3 – Prácticas de programación 20232 pág.7
Ejercicio 2: Búsqueda y ordenación de viticultores [40%]
Recordad: Los materiales de la xWiki de referencia para la búsqueda y ordenación
son:
11. Métodos de búsqueda
12. Métodos de ordenación
Aunque estos métodos son propiamente introducidos en estos temas al final del
curso, durante las PRA anteriores ya se han realizado en múltiples ocasiones,
sobre todo la búsqueda secuencial en cadena enlazada y la inserción ordenada.
En la PR1 se proporcionó el método winegrowerList_insert en el fichero
winegrower.c que inserta un viticultor (winegrower) a una lista de viticultores de
tipo tWinegrowerList de manera ordenada según el id (id) del viticultor.
a) Implementa el método winegrowerList_orderByDateAndId en el fichero
winegrower.c para que dada una lista de los viticultores (winegrower)
ordenada según el id (id) del viticultor, cree una copia de la lista ordenada
por fecha de registro (registrationDate) y si dos viticultores tienen la
misma fecha de registro por el id.
Nota: Es recomendable utilizar funciones auxiliares para simplificar el código y
generar un diseño descendente.
El ejercicio anterior era sobre ordenación de los viticultores, a continuación, nos
vamos a centrar en la búsqueda. Tened en cuenta que en la winegrower.h y en
winegrower.c ya se encuentra definida e implementada, respectivamente, el
método winegrowerList_find que dada una lista de viticultores de tipo
tWinegrowerList devuelve un puntero a un viticultor. Para este ejercicio vamos a
usar la variedad de la uva que se ha pedido implementar en el ejercicio 1.
b) Implementa el método winegrowerList_findByGrapevariety en
winegrower.c para que dada una lista de viticultores (winegrowerList)
ordenada de manera ascendente según el id de los viticultores y una
variedad de uva (grapeVariety) devuelva una nueva lista con todos
viticultores que tengan algún viñedo con esa variedad de uva. La lista que se
devuelve debe de estar ordenada de manera ascendente según el id de los
viticultores.
Práctica 3 – Prácticas de programación 20232 pág.8
c) Implementa el método
winegrowerList_findByWeighingYearAndGrapevariety en winegrower.c
para que dada una lista de viticultores (winegrowerList) ordenada de
manera ascendente según el id de los viticultores, un año (year) y una
variedad de uva (grapeVariety) devuelva una nueva lista con todos los
viticultores que para el año pedido han realizado una pesada de esta
variedad de uva en alguno de sus viñedos. La lista que se devuelve debe de
estar ordenada de manera ascendente según el id de los viticultores.
Práctica 3 – Prácticas de programación 20232 pág.9
Ejercicio 3: Búsqueda y ordenación de DO [20%]
Dada una tabla que almacena denominaciones de origen de tipo tDOData nos
interesa ordenar las denominaciones de origen según su producción en un año
dado. Por ello, se os pide:
a) Implementa el método do_getTotalWeighing en do.c para que dada una
denominación de origen (DO) y un año (year) devuelva un tipo double con la
suma de todas las pesadas (weighing) para dicho año.
Nota: A diferencia de en la PRA2, hay libertad para elegir el procedimiento con el
que implementar esta suma de todas las pesadas.
b) Implementa el método doData_orderByWeighing en do.c para que dada
una tabla que almacena denominaciones de origen de tipo tDOData y un año
(year) devuelva una nueva tabla de denominaciones de orígenes. Esta
nueva tabla ha de estar ordenada de mayor a menor pesada total para el año
dado. En caso de que dos denominaciones de origen tengan la misma
pesada total para el año pedido, aparecerá primero la DO contenga un código
de la DO (code) menor.
Nota: Es recomendable utilizar funciones auxiliares para simplificar el código y
generar un diseño descendente.
Práctica 3 – Prácticas de programación 20232 pág.10
Ejercicio 4: Integración en la API [35%]
Siguiendo la dinámica de las PR anteriores, se continuarán tratando todos los
intercambios del API con el exterior utilizando el formato CSV. Recordad que cada
entrada en un archivo CSV corresponde a un dato (fila, objeto, …), y que, por lo
tanto, el archivo es un conjunto de datos. De nuevo, se usa el tipo tCSVData para
intercambiar múltiples datos (por ejemplo, listados) y el tipo tCSVEntry para objetos
únicos. Pueden consultar los datos que se añadirán a una variable de tipo tApiData
desde el archivo test_data.h.
Al haber introducido una nueva variable en las estructuras de las pesadas
(tWeighing) y en los viñedos (tVineyardplot), hay que modificar algunos métodos
que no se han modificado en el ejercicio 1 para permitir el intercambio mediante
CSV.
a) Respecto a las pesadas, no se había definido aún un método para
intercambiar mediante CSV. Implementa el método weighing_parse en el
fichero weighing.c para que inicialice una pesada dada una entrada de CSV
con el siguiente formato, donde el penúltimo número es la variedad de uva:
"WEIGHING;30/12/2023;ABCD;20.00;1; PE-2024-00001;
Nota: En el fichero grapevariety.h se puede observar que cada variedad de fruta
tiene asignada un número entero. Este número es usado para intercambiar la
información mediante CSV. En el ejemplo, el valor 1 corresponde a la variedad de
uva TEMPRANILLO. El valor PE-2024-00001 es el código del viñedo que es
utilizado en el apartado 4d.
b) Modifica el método vineyardplot_parse en el fichero vineyardplot.c para
que se inicialice el valor correcto de la variedad de uva.
c) Modifica el método winegrower_parse en el fichero winegrower.c para que
se inicialice el valor correcto de la variedad de uva.
d) Implementa el método api_addWeighing en el fichero api.c para que dada
una estructura de tipo tApiData se añada la pesada (weighing) al viñedo
pertinente de la estructura (data).
Nota: En la PR1 se realizó el método api_addVineyardplot en el fichero api.c.
Este método puede servir de inspiración.
Práctica 3 – Prácticas de programación 20232 pág.11
e) Modifica el método api_addDataEntry en el fichero api.c para que llame al
método anterior (api_addWeighing) cuando el tipo de entrada sea
WEIGHING.
Se valorará especialmente la gestión de la memoria y la reutilización de código a lo
largo de todo el ejercicio.
Práctica 3 – Prácticas de programación 20232 pág.12