SUBPROGRAMAS AULA MENTOR
Introducción
Se ha establecido en temas anteriores que la programación modular es necesaria para realizar
programas correctos. Para facilitar esta tarea los lenguajes de programación proporcionan lo
que se conoce como módulos, subrutinas o subprogramas.
Un subprograma o módulo es un conjunto de instrucciones que realizan una determinada
tarea. Es posible hacer que ese módulo se ejecute tantas veces como se desee. También es
posible que desde un módulo se llame o invoque a otro módulo.
Los módulos se utilizan para:
*Dividir un determinado problema en partes, agrupando cada una de estas partes en un
módulo.
*Programar tareas que se repiten varias veces a lo largo del programa, de forma que se
codifican una única vez.
*Parametrizar una determinada tarea: permitir que un subprograma sea capaz de realizar una
misma tarea con distintos datos de entrada.
Todo programa en Pascal (y en general en cualquier lenguaje de programación de alto nivel)
tendrá un módulo llamado principal.
Este módulo hace las veces de director de orquesta: el programa empieza en la primera
sentencia de este módulo y termina con la última sentencia de este. Si el problema a resolver
es muy simple todo el programa se codifica en dicho módulo. Si es más complejo, serán
necesarios otros módulos, y el módulo principal será el encargado de llamarlos.
En Pascal el módulo principal es el cuerpo begin-end. del programa. Si existen otros módulos,
estos se definen antes del cuerpo del programa principal, como vimos al estudiar la estructura
de un programa en Pascal.
-1-
SUBPROGRAMAS AULA MENTOR
Conexiones entre subprogramas. Transferencia de parámetros
Si se descompone un programa en partes o módulos será necesario que se comuniquen de
alguna forma para que los resultados de un módulo sean utilizados por otro. Es necesario que
los subprogramas se transmitan información.
Suponga que desea codificar un módulo que calcule el precio de venta al público (PVP) de un
producto: esté deberá recibir de alguna forma el precio de ese producto y el IVA que se le
aplica. Si el módulo se llama calcula_PVP, se espera un funcionamiento similar a:
“Oiga, módulo calcula_PVP: muestre por pantalla el precio final de un libro de valor
1000 pesetas, al que se le aplica un 7% de IVA. “
Se le proporciona información al módulo para que realice su tarea: el valor del libro y el IVA
que se le aplica. Se dice que el valor del libro y el IVA son parámetros del subprograma. Esto
significa que este módulo o subprograma se puede utilizar para productos de distinto precio y
con distinto valor de IVA.
Al mismo tiempo el módulo me devuelve información: el precio final del libro. Esta
información se puede devolver de distintas formas:
*Como parámetro.
*Como resultado del módulo.
*Por algún periférico de salida, por ejemplo la pantalla. De esta forma el programa no
puede seguir usando el resultado para otros cálculos.
Utilicemos el ejemplo del PVP de un producto para estudiar como se definen y utilizan los
módulos en Pascal:
Definición de una función
Una función se define (y veremos que un procedimiento se define de forma similar) siguiendo
un esquema similar al de un programa. Estudiemos la función PVP y desglosemos sus partes:
Function PVP(valorprod: real; ivaprod: real): real;
var
total_iva : real;
begin
total_iva := valorprod*ivaprod/100;
PVP := valorprod + total_iva;
end;
Esta función la puede encontrar en Precio.pas.
*En la primera línea se define el nombre de la función (PVP), los parámetros (valor e iva y sus
tipos) y finalmente el tipo de datos del valor que devuelve la función (real).
*A continuación las secciones de constantes (const), tipos (type) y variables (var). En este
ejemplo sólo aparece la sección de variables.
*Estas variables definidas dentro de una función son las que denominábamos locales.
-2-
SUBPROGRAMAS AULA MENTOR
*Finalmente, el cuerpo de la función, encerrado entre un par begin-end;. La sentencia end
final está terminada en ";" y no en un "." como en el cuerpo del programa principal.
*La última línea de la función es una sentencia de asignación que le da valor a una variable,
que debe tener el mismo nombre que la función. De esta forma la función devuelve un valor
como resultado de su ejecución. Esta línea debe ser siempre la última.
Llamada o invocación de una función
Para que dicha función se ejecute simplemente hay que "invocarla" o llamarla desde otro
módulo, escribiendo su nombre y colocando entre paréntesis los valores que queremos que
reciba la función para trabajar. Como la función devuelve un valor, es necesario que se le
asigne dicho valor devuelto a una variable, o que se utilice dentro de una expresión:
total := PVP(1700, 10);
Recuerde que en una sentencia de asignación primero se ejecuta la parte derecha del operador
":= ". En este caso estamos invocando o llamando a la función PVP, y proporcionándole como
información que el valor del producto es 1700 pesetas y el IVA es del 10 %, y esperamos que
nos devuelva como resultado el PVP. Una vez que se ha ejecutado la función PVP, nos
devuelve el valor 1870, que se lo asignamos a la variable total.
En esta llamada hemos usado constantes (1700 y 10), pero se pueden usar en la invocación a
la función variables, a las que previamente se les ha asignado un valor:
valor_libro := 1500;
iva_libro := 7;
total := PVP(valor_libro ,iva_libro);
o la invocación puede ser parte de expresiones más complejas:
total := numero_articulos * PVP(valor_libro ,iva_libro);
Parámetros reales y formales
Hemos introducido el concepto de parámetro. Debemos distinguir entre los parámetros que
aparecen en la definición de la función y los parámetros que aparecen en la llamada a la
función:
*Los parámetros reales son los que se utilizan (ya sean expresiones o variables) cuando
se invoca a un módulo. En los ejemplos previos, 1500 y 7, o valor_libro e iva_libro
son parámetros reales.
*Los parámetros formales son los que se usan en la definición de un módulo. En el
ejemplo del PVP, parámetros formales son valor e iva. Dentro de la función, los
parámetros formales se tratan como variables locales de la función.
-3-
SUBPROGRAMAS AULA MENTOR
Correspondencia de parámetros
Podemos observar que la función tiene parámetros formales únicos, pero que cada vez que
llamamos o invocamos a la función los parámetros reales pueden ser distintos.
La correspondencia entre parámetros reales y formales se realiza de la siguiente forma:
-Cuando se invoca un módulo, se establece una correspondencia entre los parámetros reales y
los parámetros formales.
-Esta correspondencia se va a efectuar según el orden en que aparezcan en la sentencia de
llamada, y según el orden en que fueron declaradas (correspondencia posicional).
-Por lo tanto, el número de parámetros reales ha de coincidir con los parámetros formales, y
además han de ser del mismo tipo.
-Finalmente, esta correspondencia podrá ser de dos tipos, por valor o por referencia.
Estudiaremos estos tipos en apartados posteriores.
Ejemplo Transferencia de parámetros
Hemos visto qué son los parámetros, cómo se definen las funciones, qué son parámetros
formales y reales, y como se corresponden los parámetros al hacer la llamada a la función.
Pero antes de continuar con este tema, vamos a intentar entender, mediante trazas, como se
produce la transferencia de parámetros. Para ello vamos a situar trazas en nuestro programa
PVP antes de la llamada a la función, y dentro de la propia función.
... Function PVP(valorprod: real; ivaprod: real): real;
var
total_iva : real;
begin
if (dep) then
begin
writeln('%%%%% Dentro funcion PVP');
writeln('%%%%% Antes de ninguna sentencia. valorprod: ',
valorprod:0:1, ' ivaprod: ', ivaprod:0:1);
end;
-4-
SUBPROGRAMAS AULA MENTOR
total_iva := valorprod*ivaprod/100;
PVP := valorprod + total_iva;
end;
(** Cuerpo del programa principal **)
begin
total := 0;
dep := true; (* ACTIVA/DESACTIVA las trazas de depuración *)
write('Introduzca el valor del producto: ');
readln(valor);
write('Introduzca el IVA del producto: ');
readln(iva);
writeln;
if (dep) then
writeln('** Antes funcion PVP. Valor: ',
valor:0:1, ' IVA: ', iva:0:1, ' total: ', total:0:1);
if (dep) then
writeln('** sentencia que se va a ejecutar: total = PVP(valor,iva)');
total := PVP(valor,iva);
if (dep) then
writeln('** Despues funcion PVP. Valor: ',
valor:0:1, ' IVA: ', iva:0:1, ' total: ', total:0:1);
writeln;
writeln('El precio final es: ', total:0:1);
writeln;
(* *********************** *)
if (dep) then
writeln('** sentencia que se va a ejecutar: total = PVP(3000,20)');
total := PVP(3000,20);
writeln;
writeln('El precio final es: ', total:0:1);
writeln;
(* *********************** *)
if (dep) then
writeln('** Antes funcion PVP. Valor: ',
valor:0:1, ' IVA: ', iva:0:1, ' total: ', total:0:1);
-5-
SUBPROGRAMAS AULA MENTOR
if (dep) then
writeln('** sentencia que se va a ejecutar: total = PVP(valor*10, 20-2)');
total := PVP(valor*10,20-2);
writeln;
writeln('El precio final es: ', total:0:1);
end.
Las trazas de depuración están destacadas en color rojo: antes de las llamadas a la función
PVP, y dentro de esta función.
En especial, observe la traza dentro de la función. Está justo al comienzo de dicha función.
Cuando se ejecute dicha sentencia no se ha ejecutado ninguna línea de código de la función.
Function PVP(valorprod: real; ivaprod: real): real;
var
total_iva : real;
begin
if (dep) then
begin
writeln('%%%%% Dentro funcion PVP');
writeln('%%%%% Antes de ninguna sentencia. valorprod: ',
valorprod:0:1, ' ivaprod: ', ivaprod:0:1);
end;
total_iva := valorprod*ivaprod/100;
PVP := valorprod + total_iva;
end;
Observe que dicha traza intenta presentar por pantalla los valores almacenados en los
parámetros formales valorprod e ivaprod. El código completo lo puede encontrar en
preciodep.pas.
Tras compilarlo y ejecutar nos queda:
-6-
SUBPROGRAMAS AULA MENTOR
Observe las tres llamadas a la función PVP que hay en el programa principal:
total := PVP(valor,iva);
Los parámetros reales son dos variables, valor e iva. El primero, valor, se corresponde con el
parámetro formal valorprod, y el segundo, iva, con ivaprod.
valor se copia en valorprod
iva se copia en ivaprod
Dentro de la función, estos parámetros toman los valores de los parámetros reales sin que
exista ninguna sentencia de asignación. No es magia: se ha realizado de forma automática la
correspondencia de parámetros entre reales y formales.
total := PVP(3000,20);
En esta los parámetros reales son constantes. Observe en el gráfico resultado de la ejecución la
correspondencia.
total := PVP(valor*10,20-2);
En esta los parámetros reales son expresiones: la variable valor*10, e iva-2. Observe en la
figura que valores toman los parámetros formales dentro de la función: 1000 y 18.
Tipos de correspondencia de los parámetros
Los parámetros se pueden corresponder según dos criterios:
*por valor: cuando se pasa un parámetro por valor, en el momento de la llamada a la función
se copia el valor del parámetro real en el parámetro formal. Si modificamos el parámetro
formal dentro de la función NO se modifica el parámetro real:
P. REAL se copia en P. FORMAL
En Pascal, por defecto, los parámetros se pasan por valor. En el ejemplo previo, los dos
parámetros formales son por valor. Hasta este momento todos los parámetros definidos son
por valor.
*por referencia: Cuando se pasa un parámetro por referencia, se considera que el parámetro
real y el formal son la misma variable, y cualquier modificación en la función sobre el
parámetro formal implica que estamos modificando el parámetro real.
P. REAL es equivalente a P. FORMAL
Para especificar en Pascal un parámetro por referencia se utiliza la palabra reservada VAR
antes de la definición del parámetro formal, como se hace en el siguiente ejemplo:
Procedure Swap(VAR x, y: Integer);
-7-
SUBPROGRAMAS AULA MENTOR
Como puede observar, ya no es una función sino un procedimiento. Y eso es lo que vamos a
estudiar a continuación. Veremos ejemplos del uso de parámetros por referencia en los
ejemplos de este tema, y sobre todo en el tema de tablas.
(*
Tema 6: Subprogramas
Programa de ejemplo de definición e invocación de funciones
*)
Program PrecioFinal;
Var
valor: real; (* Precio del libro *)
iva: real; (* IVA aplicable *)
total: real; (* Precio venta al público *)
num: real; (* Número de libros *)
(* Recibe el valor de un producto y el IVA (en %) y devuelve como *)
(* resultado de la función el precio final *)
Function PVP(valor: real; iva: real): real;
var
total_iva : real;
begin
total_iva := valor*iva/100;
PVP := valor + total_iva;
end;
(** Cuerpo del programa principal **)
begin
write('Introduzca el valor del producto: ');
readln(valor);
write('Introduzca el IVA del producto: ');
readln(iva);
total := PVP(valor,iva);
writeln('El precio final es: ', total:0:1);
write('Introduzca el número de productos: ');
readln(num);
writeln('El total es ', total:0:1, ' x ',
num:0:0, ' = ', num*PVP(valor,iva):0:1);
end.
-8-
SUBPROGRAMAS AULA MENTOR
(*
Tema 6: Subprogramas
Programa de ejemplo de definición e invocación de funciones
Se muestra mediante trazas de depuración la transferencia de parámetros.
*)
Program PrecioFinal;
Var
valor: real; (* Precio del libro *)
iva: real; (* IVA aplicable *)
total: real; (* Precio venta al público *)
dep: boolean; (*Controla depuración *)
(* Recibe el valor de un producto y el IVA (en %) y devuelve como *)
(* resultado de la función el precio final *)
Function PVP(valorprod: real; ivaprod: real): real;
var
total_iva : real;
begin
if (dep) then
begin
writeln('%%%%% Funcion PVP');
writeln('%%%%% Antes de ninguna sentencia. valorprod: ',
valorprod:0:1, ' ivaprod: ', ivaprod:0:1);
end;
total_iva := valorprod*ivaprod/100;
PVP := valorprod + total_iva;
end;
(** Cuerpo del programa principal **)
begin
total := 0;
dep := true; (* ACTIVA/DESACTIVA las trazas de depuración *)
write('Introduzca el valor del producto: ');
readln(valor);
write('Introduzca el IVA del producto: ');
readln(iva);
writeln;
if (dep) then
writeln('** Antes funcion PVP. Valor: ',
valor:0:1, ' IVA: ', iva:0:1, ' total: ', total:0:1);
if (dep) then
-9-
SUBPROGRAMAS AULA MENTOR
writeln('** sentencia que se va a ejecutar: total = PVP(valor,iva)');
total := PVP(valor,iva);
if (dep) then
writeln('** Despues funcion PVP. Valor: ',
valor:0:1, ' IVA: ', iva:0:1, ' total: ', total:0:1);
writeln;
writeln('El precio final es: ', total:0:1);
writeln;
(* *********************** *)
if (dep) then
writeln('** sentencia que se va a ejecutar: total = PVP(3000,20)');
total := PVP(3000,20);
writeln;
writeln('El precio final es: ', total:0:1);
writeln;
(* *********************** *)
if (dep) then
writeln('** Antes funcion PVP. Valor: ',
valor:0:1, ' IVA: ', iva:0:1, ' total: ', total:0:1);
if (dep) then
writeln('** sentencia que se va a ejecutar: total = PVP(valor*10, 20-2)');
total := PVP(valor*10,20-2);
writeln;
writeln('El precio final es: ', total:0:1);
end.
Procedimientos
Hemos estudiado que una función devuelve un valor como resultado de la función. Un
procedimiento es simplemente un módulo o subprograma que no devuelve nada como
resultado de su ejecución.
Esta distinción no es del todo exacta: Un procedimiento no devuelve información como
resultado de su ejecución, pero si puede devolver información a la función que lo ha llamado
mediante parámetros por referencia.
Definición de un procedimiento
Un procedimiento se define:
- 10 -
SUBPROGRAMAS AULA MENTOR
Procedure Suma (Real:a,b);
var
total: real;
begin
total := a + b;
write( a, ' + ', b, ' = ', total);
end;
Como podemos comprobar, es muy similar a la definición de una función: cambia la palabra
reservada function por procedure y no devuelve nada como resultado de la función. Esto
implica que no es necesaria una sentencia de asignación con el nombre de la función al final
del procedimiento.
Invocación de un procedimiento
La llamada a un procedimiento es similar a la de una función; se especifica su nombre y los
parámetros reales:
nombre_del_procedimiento (parametros_reales_sin_tipo);
Pero en el caso de procedimientos, estos no pueden ser parte de expresiones como las
funciones, ya que no devuelven ningún valor como resultado.
La invocación del procedimiento suma podría ser:
suma (7,5);
pero nunca
total := suma (7,5);(* Incorrecto *)
Observe este ejemplo: además del procedimiento suma se ha codificado un procedimiento sin
parámetros que hace una presentación inicial por pantalla. Descubra como se define e invoca
dicho procedimiento sin parámetros.
Intentemos ahora mediante ejemplos ver la diferencia entre parámetros por valor y referencia,
y entre funciones y procedimientos.
- 11 -