Diseño descendente
Hasta ahora: Problema difícil à
¿Solución?
A partir de ahora: Problema difícil
à
División en subproblemas à Solución de subproblemas
Cuando necesitemos un algoritmo
que resuelva un problema difícil, puedo dividirlo en subprogramas (que al ser
más pequeños son más sencillos de resolver), y ocuparme de solucionar esos
subproblemas, pensando los correspondientes subalgoritmos.
Si alguno de mis subproblemas
continúa siendo demasiado difícil, puedo volver a descomponerlo en subproblemas
y buscar solución a estos, y así tantas veces como sea necesario.
Abstracción
Con los algoritmo ocurre lo
siguiente:
·
Mi problema principal se resuelve resolviendo un
conjunto de subproblemas. Yo sin más enumero las tareas a realizar y me dan
igual esos detalles para elaborar mi algoritmo.
·
Al entrar a resolver cada subproblema, yo cumplo
las especificaciones técnicas que me han dado, escribo un subalgoritmo que
resuelve ese subproblema y me despreocupo del uso que se vaya a hacer de él
siempre y cuando se respeten esas especificaciones y el subalgoritmo sea
empleado para lo que sirve.
Ejemplo.
Calcula el área del triangulo:
¿Qué hacer?
Pedir
datos al usuario
Calcular
la superficie
Mostrar
resultados por pantalla
Hasta ahora, para resolver un
problema pensábamos de una forma “ascendente”. ¿Qué instrucciones tengo que
poner abajo para darle solución a ese gran problema que tengo?
A partir de ahora para resolver
problemas pensamos de arriba abajo. Para resolver mi problema, ¿qué tareas lo
resuelven? Y luego, ¿esas tareas, con que subtareas se resuelven?
Y al final de todo terminarás
poniendo las instrucciones necesarias.
Nuestro lema es: Divide y vencerás
Subprogramas
Un subprograma puede hacer las mismas
acciones que el programa principal. La idea es darle un nombre a un trozo de
programa y quitar de en medio.
¿Qué conseguimos?
Sencillez. Resolvemos problemas
más pequeños y utilizamos la solución para solucionar problemas mayores.
Claridad. Nos queda un programa
mucho más corto donde se puede ver más fácilmente lo que se está haciendo.
Reusabilidad. Si se hace lo mismo
en varios puntos del programa sólo hay que escribirlo una vez y hacerlo
funcionar siempre. Si hubiera errores en ese trozo de programa, sólo habría que
corregirlo una vez.
Reparto de trabajo. Podemos darle
los subproblemas a resolver a diferentes programadores que pueden trabajar en
paralelo.
Resulta más difícil equivocarse y
más sencillo corregir errores. Los subprogramas pueden probarse uno a uno antes
de juntarlos. Los errores en programas cortos y claros se encuentran más fácilmente.
Ejecución de un programa con subprogramas
El programa se va ejecutando hasta
llegar a la llamada a un subprograma.
El programa principal LLAMA o
INVOCA al subprograma (pudiendo enviar datos).
El subprograma devuelve el control
al programa principal (puede devolver datos).
El programa continua ejecutándose justo
donde se había quedado.
Consideraciones
Se puede llamar varias veces en un
mismo subprograma. Un subprograma puede llamar a otro subprograma y así
sucesivamente tantas veces como sea necesario.
Un subprograma puede llamarse
incluso a sí mismo.
Se puede llamar a un subprograma
en cualquier parte de un programa o subprograma.
Parámetros
Un programa y un subprograma se
comunican información por medio de parámetros.
Los parámetros pueden ser:
·
De entrada
(E). Del programa al subprograma al invocarlo
·
De salida
(S). Del subprograma al programa al devolverle el control
·
De
entrada / salida (E/S). En ambas direcciones
Los parámetros de entrada, cuando
los pasa el programa principal, tienen que ser unan expresión de cualquier tipo
(eso sí, el tipo de datos resultante tiene que ser el que espera el
subprograma). Podría ser una variable, un dato…
Los parámetros de salida o
entrada/salida, en cambio, tienen que ser necesariamente una variable, ya que
es en esa variable donde se almacenará el dato que devuelva el subprograma.
Ejemplo
Subprograma destruyeMatriz
{Pasandole una matriz, pone a 0 todos los elementos que están fuera del
rango [min,max] (también parámetros) y que me devolviera en otro parámetro “destruidos”
el número de elementos destruidos}
/* Mi subprograma empezaría definiendo esos parámetros */
Subprograma destruyeMatriz (E/S matriz,Emin,Emax,Sdestruidos)
Normalmente hay que definir de qué
tipo de datos es cada parámetro que va a utilizar el subprograma (aquí lo he
obviado para centrarme en lo que interesa en esta explicación)
/* Lo llamaría desde el subprograma principal, por ejemplo: */
destruyeMatriz (miMatriz,3.5+i,cuantos);
/*Obsérvese que miMatriz y cuantos, al ser parámetros S o E/S son necesariamente
variables.
En cambio, para los valores min y max, como son productos de entrada, puedo
pasar los datos constantes o expresiones que serán evaluados antes.*/
Parámetros actuales y formales
Los parámetros formales son los
que figuran en la declaración del subprograma y son usados para efectuar los
cálculos necesarios en su interior.
Subprograma destruyeMatriz(E/S matriz, E min, E max, S destruidos)
Los parámetros actuales son lo que
se pasan desde el programa principal
destruyeMatriz(minMatriz,3.5+i,cuantos);
Los parámetros actuales hay que
pasarlos en el mismo orden en el que han sido declarados como parámetros
formales y cada uno tiene que ser compatible con el tipo que está esperando al
subprograma para ese parámetro.
Al hacer la invocación se asocian
uno a uno los parámetros actuales con los formales pasando la información que
contienen.
Al serle devuelto el control del
programa o subprograma invocante, se devuelven en las variables los valores
asociados a los parámetros de salida o entrada/salida.
Tipos de subprogramas
En programación hay dos tipos de
subprogramas:
·
Funciones.
Subprogramas que realizan operaciones sobre uno o más valores que se han
pasado como parámetros y producen un único dato como resultado (del tipo que
sea).
·
Procedimientos.
Subprogramas que realizan una serie de acciones que pueden modificar
algunos de los parámetros que reciben, pero no tienen asociado ningún valor concreto
que devuelvan como resultado.
Funciones
En estado puro una función es un
subprograma que realiza operaciones sobre uno o más valores que se han pasado
como parámetros y produce un único dato como resultado (del tipo que sea).
Sólo admite parámetros de entrada.
No puede modificarlos ni hacer nada con ellos para que puedan devolver al
programa principal ninguna información.
Su única forma de enviar información
al programa que le ha llamado es mediante el valor del dato que devuelve como
resultado.
El dato que devuelve puede ser de
cualquier tipo.
Declaración de funciones. Sintaxis
Función<nombre de función(<lista de parámetros formales>)devuelve
tipo>
Variables
<definición de
variables locales>
Principio
<acciones>(Utilizando
parámetros formales)
Devolver<expresión>
Fin
· <nombre
función> Nombre identificativo para la función
·
<lista
de parámetros formales> Entre paréntesis, pondremos los parámetros
formales que esperan la función. De cada parámetro habrá que especificar
nombre, tipo de datos y clase. Se separarán por comas
EJ: función g(E x:real,E y:real)devuelve
real;
·
<tipo>
Tipo de datos que devuelve la función
·
<definición
de variables locales> Aquí definimos variables locales que serán
utilizadas dentro de la función. Sólo existen dentro de ellas. Cuando la
función termine, las variables serán destruidas e inaccesibles.
·
<acciones>(Utilizando
parámetros formales) Las acciones son similares a las de un programa. Se
pueden llamar a otras funciones o procedimientos. En esas acciones se pueden
usar los parámetros formales para hacer cálculos con ellos.
·
Devolver<expresión>
Devolver es una instrucción especial que sólo tienen las funciones. Evalúa la
expresión y devuelve el dato que obtenemos (que tiene que concordar con el tipo
establecido en la cabecera de la función tras el “devuelve”) al programa o
subprograma que invocó a la función.
Ejemplo de declaración
función factorial(n:entero) devuelve entero
variables
resultado:entero;
indice:entero;
principio
resultado:=1;
para indice:=2 hasta n
hacer
resultado:=resultado*indice;
fpara
devolver resultados
fin
Uso de funciones
<nombre de función> (<lista de parámetros actuales>)
Correspondencia entre parámetros formales y actuales
mismo número
de izquierda a derecha
parámetros
correspondientes del mismo tipo
Una llamada a una función devuelve
un valor y por lo tanto es una expresión o parte de una expresión.
Ejemplos:
A:=Factorial(7);
C:=Factorial(A)-Factorial(7)+b;
Algoritmo calculaFactorial
variables
numero:entero;
principio
escribirCadena(pantalla,’Introduzca
un número para calcular su factorial’);
leerEntero(teclado,numero);
escribirCadena(pantalla,’El
factorial del número es:’);
escribirEntero(pantalla,factorial(numero));
fin
0 comentarios:
Publicar un comentario