Diferencia entre revisiones de «Material»

De Wiki del curso de C
Saltar a: navegación, buscar
(Página creada con « == Material de clase == * Transparencias (Se irá actualizando) * Plantilla Juego de la vida == Vídeos ==...»)
 
Línea 1: Línea 1:
 
 
== Material de clase ==
 
== Material de clase ==
  
Línea 9: Línea 8:
 
# https://youtu.be/C0UiG1uYgYQ
 
# https://youtu.be/C0UiG1uYgYQ
 
# https://youtu.be/gqzYwGdPfYM
 
# https://youtu.be/gqzYwGdPfYM
 +
 +
== Tareas ==
 +
 +
 +
{| class="wikitable"
 +
! Tarea
 +
! Subtarea
 +
! Descripción
 +
|-
 +
| 1
 +
|
 +
|  Versión inicial
 +
* Completada la plantilla del juego de la vida
 +
* Completado README.md
 +
|-
 +
 +
| rowspan="2" | 2
 +
| 2.1
 +
|  Intercambiar mundos en lugar de copiarlos
 +
* Se utiliza un array de 3 dimensiones para guardar los 2 mundos
 +
* Se van intercambiando los mundos "actual" y "siguiente" en cada iteración
 +
* Se elimina la función `gol_copy`, ahora innecesaria
 +
|-
 +
 +
| 2.2
 +
| Intercambiar mundos en lugar de copiarlos
 +
* Se utiliza un array de 3 dimensiones para guardar los 2 mundos
 +
* Se van intercambiando los mundos "actual" y "siguiente" en cada iteración
 +
* Se elimina la función `gol_copy`, ahora innecesaria
 +
|-
 +
 +
| rowspan="2" | 3
 +
| 3.1
 +
| Encapsular el juego de la vida en una estructura
 +
* Se encapsulan las variables `worlds` y `current_world` en la estructura `gol`
 +
* La función `gol_step` se encarga ahora de gestionar la variable `curren_world`
 +
|-
 +
 +
| 3.2
 +
| Ocultar todas las funciones que el usuario no necesite
 +
* Se ocultan `gol_get_cell` y `gol_count_neighbours`
 +
* Se declaran como `static` y se elimina el prefijo `gol_`
 +
|-
 +
 +
| rowspan="2" | 4
 +
| 4.1
 +
| Memoria dinámica I: Añadir objetivos `debug` y `release`
 +
Se añaden dos nuevos objetivos al makefile que modifican los flags de gcc para
 +
crear dos ejecutables distintos según convenga.
 +
|-
 +
 +
| 4.2
 +
| Memoria dinámica I: Reserva dinámica de memoria para el mundo
 +
* Ahora los mundos se reservan dinámicamente con `malloc`
 +
* La nueva función `gol_alloc` se encarga de la esta reserva y `gol_free` de la liberación
 +
* Cada mundo es un puntero a un puntero a un boleano, ie un vector de vectores. Se realiza una llamada a malloc para guardar un vector de punteros a filas y luego se realiza otra llamada por cada fila para reservarla.
 +
* Para guardar la referencia a los dos mundos se utiliza un array de dos punteros. El mundo actual y el próximo siempre están en la misma posición de este array, y en cada iteración se intercambian las direcciones de los dos punteros.
 +
* Se usa un enumerado para identificar los índices del mundo actual y el siguiente
 +
|-
 +
 +
| rowspan="2" | 5
 +
| 5.1
 +
| Memoria dinámica II: Implementar test de memoria
 +
* Se crea un nuevo archivo `mem_test.c` con otro `main()` que realiza un número finito de iteraciones del juego sin requerir la interacción del usuario, ni imprimir nada por pantalla
 +
* Se añade un nuevo objetivo (`test`) al makefile que primero compilar el ejecutable `mem_test` con opciones de depuración y con todas las optimizaciones. Después lanzará este ejecutable con valgrind para comprobar fugas de memoria
 +
|-
 +
 +
| 5.2
 +
| Memoria dinámica II: Una sola reserva de memoria por mundo
 +
* Los mundos son un único puntero a un bloque de memoria dónde está la matriz entera. Se realiza una llama a malloc por mundo.
 +
* Ahora hay que calcular el offset de cada célula a mano, por lo que los accesos al mundo siempre se hacen a través de `get_cell` y la nueva función `set_cell`
 +
* Las funciones `set_cell` y `get_cell` reciben el mundo sobre el que actuar (actual o siguiente)
 +
* Se saca la lógica para comprobar los límites del mundo a la función `fix_coords` para poder utilizarla en `set_cell` y `get_cell` sin repetir código
 +
|-
 +
 +
| rowspan="2" | 6
 +
| 6.1
 +
| Memoria dinámica III: Macro funcional para acceder a las células
 +
Utilizar una macro para reutilizar y evitar repetir el mismo código en
 +
`get_cell` y `set_cell`
 +
|-
 +
 +
| 6.2
 +
| Memoria dinámica III: Una reserva de memoria para los dos mundos
 +
* La memoria para los dos mundos se reserva de una vez. La referencia a este bloque de memoria se guarda en la estructura del objeto
 +
* Se utiliza la misma lógica que antes para acceder a las células, con dos punteros a los mundos que vamos intercarbiando.
 +
|-
 +
 +
| ...
 +
| ...
 +
| ...
 +
 +
|}

Revisión del 21:26 19 may 2019

Material de clase

Vídeos

  1. https://youtu.be/C0UiG1uYgYQ
  2. https://youtu.be/gqzYwGdPfYM

Tareas

Tarea Subtarea Descripción
1 Versión inicial
  • Completada la plantilla del juego de la vida
  • Completado README.md
2 2.1 Intercambiar mundos en lugar de copiarlos
  • Se utiliza un array de 3 dimensiones para guardar los 2 mundos
  • Se van intercambiando los mundos "actual" y "siguiente" en cada iteración
  • Se elimina la función `gol_copy`, ahora innecesaria
2.2 Intercambiar mundos en lugar de copiarlos
  • Se utiliza un array de 3 dimensiones para guardar los 2 mundos
  • Se van intercambiando los mundos "actual" y "siguiente" en cada iteración
  • Se elimina la función `gol_copy`, ahora innecesaria
3 3.1 Encapsular el juego de la vida en una estructura
  • Se encapsulan las variables `worlds` y `current_world` en la estructura `gol`
  • La función `gol_step` se encarga ahora de gestionar la variable `curren_world`
3.2 Ocultar todas las funciones que el usuario no necesite
  • Se ocultan `gol_get_cell` y `gol_count_neighbours`
  • Se declaran como `static` y se elimina el prefijo `gol_`
4 4.1 Memoria dinámica I: Añadir objetivos `debug` y `release`

Se añaden dos nuevos objetivos al makefile que modifican los flags de gcc para crear dos ejecutables distintos según convenga.

4.2 Memoria dinámica I: Reserva dinámica de memoria para el mundo
  • Ahora los mundos se reservan dinámicamente con `malloc`
  • La nueva función `gol_alloc` se encarga de la esta reserva y `gol_free` de la liberación
  • Cada mundo es un puntero a un puntero a un boleano, ie un vector de vectores. Se realiza una llamada a malloc para guardar un vector de punteros a filas y luego se realiza otra llamada por cada fila para reservarla.
  • Para guardar la referencia a los dos mundos se utiliza un array de dos punteros. El mundo actual y el próximo siempre están en la misma posición de este array, y en cada iteración se intercambian las direcciones de los dos punteros.
  • Se usa un enumerado para identificar los índices del mundo actual y el siguiente
5 5.1 Memoria dinámica II: Implementar test de memoria
  • Se crea un nuevo archivo `mem_test.c` con otro `main()` que realiza un número finito de iteraciones del juego sin requerir la interacción del usuario, ni imprimir nada por pantalla
  • Se añade un nuevo objetivo (`test`) al makefile que primero compilar el ejecutable `mem_test` con opciones de depuración y con todas las optimizaciones. Después lanzará este ejecutable con valgrind para comprobar fugas de memoria
5.2 Memoria dinámica II: Una sola reserva de memoria por mundo
  • Los mundos son un único puntero a un bloque de memoria dónde está la matriz entera. Se realiza una llama a malloc por mundo.
  • Ahora hay que calcular el offset de cada célula a mano, por lo que los accesos al mundo siempre se hacen a través de `get_cell` y la nueva función `set_cell`
  • Las funciones `set_cell` y `get_cell` reciben el mundo sobre el que actuar (actual o siguiente)
  • Se saca la lógica para comprobar los límites del mundo a la función `fix_coords` para poder utilizarla en `set_cell` y `get_cell` sin repetir código
6 6.1 Memoria dinámica III: Macro funcional para acceder a las células

Utilizar una macro para reutilizar y evitar repetir el mismo código en `get_cell` y `set_cell`

6.2 Memoria dinámica III: Una reserva de memoria para los dos mundos
  • La memoria para los dos mundos se reserva de una vez. La referencia a este bloque de memoria se guarda en la estructura del objeto
  • Se utiliza la misma lógica que antes para acceder a las células, con dos punteros a los mundos que vamos intercarbiando.
... ... ...