Guia PS

Última modificación por Mario Gorga López el 2024/06/04 15:51

Introducción

En este módulo se presenta un resumen de los conceptos trabajados en la asignatura, junto con la descripción de la prueba de síntesis y materiales que pueden servir de cara a estudiar para la prueba.

Resumen de conceptos

Durante la asignatura de Prácticas de Programación hemos reforzado los conceptos aprendidos en la asignatura de Fundamentos de Programación, profundizando en algunos de los conceptos, extendiendo otros y sobre todo avanzando en el formalismo.

Conceptos básicos

Al inicio de la asignatura se repasaron los conceptos básicos que se habían visto en Fundamentos de Programación, y que son la base de esta asignatura. Los principales conceptos que hay que tener claros son:

  • Diferencia entre algoritmo y programa: un algoritmo es la descripción formal y precisa de la solución a un problema. Los algoritmos se escriben en pseudocódigo, un lenguaje que se encuentra entre el lenguaje natural con que se comunican las personas y el lenguaje máquina que entienden los ordenadores. Este algoritmo se traduce mediante un lenguaje de programación a un programa, que posteriormente puede ser compilado para convertirlo en lenguaje máquina y ejecutado por un ordenador.
  • Tipo de datos: un programa informático no es más que una transformación de una información inicial en una información final. Por lo tanto, uno de los puntos más importantes es poder definir de forma precisa esta información y poderla manipular. Se ha recordado el concepto de variable y tipos de datos. Las variables son objetos que contienen información y nos permiten manipularla. La información que puede contener una variable viene determinada por su tipo de datos. Cada tipo de datos permite guardar un determinado tipo de información, y tenemos diferentes niveles de complejidad. Además, cada tipo de datos tiene un conjunto de operaciones asociadas (aritméticas, lógicas, de asignación, ...). Se pueden hacer cambios de un tipo de datos a otro (casts). Dentro de estos tipos de datos tenemos los tipos básicos, que permiten guardar información muy básica, como un carácter, un número entero o un real. Estos tipos básicos se pueden combinar mediante tuplas para formar tipos de datos más complejos, que pueden guardar la información de una persona o un movimiento bancario. Finalmente habíamos visto los punteros, que son un tipo de datos que pueden almacenar una dirección de memoria. Este tipo de datos nos permite definir parámetros de entrada y salida en acciones y funciones, y tienen un papel muy importante en el uso de la memoria dinámica.
  • Secuencias: también habíamos visto que independientemente de cuál sea el tipo de datos, a menudo no sólo tenemos un dato aislado, sino conjuntos de datos. Cuando tenemos un conjunto con un número fijado de elementos, utilizamos los vectores o matrices. Cuando tenemos un número variable de elementos, utilizamos las tablas. Dependiendo de qué operaciones definimos sobre las tablas, además podemos definir algunos tipos abstractos de datos, tales como pilas, colas y listas.
  • Estructuras de control: los algoritmos y programas son un conjunto de instrucciones que se ejecutan de forma secuencial. Las estructuras de control nos permiten modificar esta ejecución. Tenemos dos tipos de estructuras de control, las alternativas, que nos permiten decidir si ejecutar un código o no dependiendo de una condición lógica y las repetitivas, que nos permiten ejecutar un código varias veces. Dentro del primer conjunto tenemos las estructuras if, if-else, y switch. En el segundo conjunto hemos visto las estructuras for y while. También hemos visto que para las estructuras repetitivas, existen dos casos típicos que si los identificamos nos pueden ayudar a definir la estructura (búsqueda y recorrido).
  • Modularidad: habíamos visto que es conveniente dividir los problemas en problemas más pequeños y reutilizables. Teníamos diferentes niveles de modularidad:
    • Podemos agrupar fragmentos de código en una acción o función. La diferencia es que las funciones devuelven un valor y por lo tanto se pueden utilizar como parte de una expresión, mientras que las acciones no retornan valor y por lo tanto no pueden estar en una expresión. Tanto las funciones como las acciones pueden tener parámetros de entrada, de salida y de entrada/salida.
    • Las funciones y acciones se pueden agrupar en ficheros. Tenemos dos tipos de ficheros, los de cabecera (*.h) y los de código (*.c).
    • Múltiples ficheros se pueden agrupar en formato de librería, pudiéndose utilizar en múltiples aplicaciones.
  • Memoria estática y memoria dinámica: cada variable ocupa un cierto espacio de memoria. La forma en que esta memoria se reserva diferencia entre memoria estática o memoria dinámica. La memoria estática queda definida en nuestro programa, y no puede cambiar durante la ejecución del mismo. Por ejemplo, cuando definimos una variable entera, real o booleana, el espacio que ocupa está fijado, y se reserva automáticamente al ejecutar el programa. Lo mismo ocurre cuando definimos un vector o una matriz. La gran ventaja de la memoria estática es que se gestiona automáticamente, no es necesario reservarla ni liberarla, ya que el compilador se encarga de todo. El gran inconveniente lo encontramos cuando tenemos conjuntos de datos, como tablas o TAD, que tienen un número de elementos que puede ir variando. Si utilizamos memoria estática, debemos reservar un espacio de memoria lo suficientemente grande para que pueda guardarse todos los elementos que necesitamos, lo que obliga a poner un tamaño máximo de elementos, y hace que estemos utilizando más memoria de la necesaria. La memoria dinámica es aquella memoria que pedimos explícitamente durante la ejecución del programa, mediante las llamadas a las funciones malloc o realloc. Al pedir memoria dinámica, se nos devuelve la dirección inicial del espacio que hemos pedido, y hay que guardarla en un puntero para poder acceder. Hay que tener en cuenta que cuando utilizamos este tipo de memoria, nosotros (los programadores) tenemos la responsabilidad de liberar esta memoria cuando ya no la necesitamos, mediante el comando free.
  • Recursividad: En Fundamentos de Programación habíamos visto que la recursividad es una estrategia de programación que básicamente implica que un método se llama a sí mismo con el fin de resolver un problema. También habíamos visto que algunos problemas son recursivos por definición, y que otros problemas pueden convertirse en recursivos. La gran ventaja de la recursividad es que cuando es aplicable, simplifica mucho los algoritmos.

Enlaces relacionados

Especificación formal de algoritmos

En Fundamentos de Programación habíamos visto cómo escribir algoritmos para resolver problemas. Estos algoritmos describían una secuencia de pasos para resolver el problema. En Prácticas de Programación hemos visto que podemos especificar formalmente aquellas asunciones iniciales en los datos a partir de las precondiciones. De esta manera queda detallado formalmente cuál es el estado inicial del algoritmo. También podíamos escribir formalmente el estado final del algoritmo cuando ha acabado a través de las postcondiciones.

Aparte de la especificación formal, hemos visto que estas condiciones formales se pueden trasladar al código en lenguaje C, utilizando las aserciones.

Diseño descendente

En Fundamentos de Programación habíamos visto el tema de la modularidad. El diseño descendente nos proporciona una metodología para aplicar esta modularidad, dividiendo un problema en problemas más pequeños y simples. En el análisis de un problema hay que tener en cuenta tanto los datos que se manipulan, como el tratamiento que se hace de estos datos.

Enlaces relacionados

Recursividad

A partir de la definición básica de dada en Fundamentos de Programación, en Prácticas de Programación hemos visto ejemplos de métodos recursivos más complejos. También hemos visto que tenemos diferentes tipos de recursividad, pudiendo hablar de recursividad simple o múltiple, directa o indirecta, y final o no final. Finalmente también hemos visto que todo algoritmo recursivo se puede convertir en un algoritmo iterativo.

Enlaces relacionados

Tipos abstractos de datos (TAD)

En Fundamentos de Programación ya habíamos visto los tipos abstractos de datos, en concreto las pilas, colas y listas. Todas estas estructuras las habíamos definido básicamente sobre tablas. Hemos visto cómo podemos definir estos tipos de datos basados en memoria dinámica, a través del uso de los punteros. También hemos visto que un TAD puede contener cualquier tipo de elemento, incluso otro TAD.

Análisis de la complejidad

Hemos visto que no sólo hay que hacer algoritmos que resuelvan problemas, sino que también hay que hacer algoritmos que sean óptimos. Hemos visto cómo calcular la complejidad de un algoritmo respecto al número de datos. Es muy importante tener conciencia de la complejidad de un algoritmo a la hora de utilizarlo en una aplicación, ya que puede ser la diferencia entre que esta aplicación sea de utilidad o no.

Métodos de búsqueda y ordenación

Finalmente, hemos visto que existen algoritmos para buscar elementos en una secuencia ordenada y cómo ordenar una secuencia. Estas dos operaciones son muy comunes en todas las aplicaciones, y por tanto hay que conocer los métodos que existen y su complejidad.

Prueba de Síntesis

La Prueba de Síntesis puede contener preguntas teóricas, ejercicios a realizar en lenguaje algorítmico y ejercicios a realizar en lenguaje C. Las preguntas mezclarán los diferentes contenidos vistos en la asignatura. A modo de ejemplo, a continuación se muestra un enunciado de muestra de la Prueba de Síntesis. Se recomienda intentar solucionar la PS primero, y después comprobar la solución. Si tenéis dudas, lo podéis comentar en el foro de teoría de la asignatura.

Recomendaciones a la hora de hacer la Prueba de Síntesis

Antes de empezar la prueba de síntesis (o cualquier prueba/examen de la UOC) es importante comprobar la información de la portada. En concreto, hay que comparar el código de la asignatura con los códigos que encontraréis en vuestra hoja personal de examen. En la siguiente figura se muestra donde encontraréis los códigos dentro del enunciado:

PsHeaderIB.png

También es importante verificar el peso de cada pregunta y qué materiales se pueden utilizar. En esta asignatura se permite tener materiales. Esta información la encontraréis en los siguientes apartados de la hoja técnica:

PsInfo_IB.png

Etiquetas:
Creado por editor1 el 2018/09/17 11:45