Вы находитесь на странице: 1из 11

SUBPROGRAMAS

Los subprogramas son rutinas, procedimientos o conjuntos de instrucciones


que realizan una labor específica. Los subprogramas o subrutinas nacieron de la
necesidad de no repetir innecesariamente un trabajo ya hecho. Pueden invocarse
desde el cuerpo del programa principal cuantas veces se desee. Constituyen el
núcleo de lo que se denomina programación estructurada, y permiten la
descomposición de un problema complejo en subproblemas más sencillos
abordables de forma independiente. Así, como recordaremos del tema 1.2, la
estructura general de un programa de Flowol se puede representar como:

Supongamos, por fijar ideas, que necesitamos encender una lámpara (conectada
a la 1ª salida de la interfaz de control) 3 veces durante medio segundo cada vez y
con intervalos de 1 segundo. Un programa que realiza este proceso puede ser:
Como observamos, se repite 3 veces un mismo conjunto de instrucciones, de
modo que podemos definir un subprograma (llamado lamp, pro ejemplo) cuya
acción sea simplemente encender y apagar la lámpara con los períodos
adecuados e invocar este subprograma 3 veces desde el programa principal:
Como observamos, este nuevo programa es más económico a la hora de
programar y resulta mucho más legible. Cuando un programa contiene muchas
instrucciones esta forma de programar se convierte en indispensable para
obtener un código eficiente y fácil de interpretar por el programador.

1. Edición de un subprograma

Para definir un subprograma no hay más que insertar un bloque terminador y


pulsar el botón Sub en el cuadro de diálogo que aparece:
En el cuadro de texto que aparece en blanco se puede introducir el nombre
deseado para el subprograma:

de modo que se obtiene el bloque:

(si no se hubiese introducido ningún nombre, el subprograma sería reconocido


simplemente por Sub 1).

El cuerpo del subprograma se completa arrastrando y soltando los bloques


necesarios, y se finaliza insertando un terminador Alto.
En Flowol se pueden definir hasta 16 diferentes subprogramas, con un grado
de anidamiento máximo de 8 niveles (es decir, un subprograma puede invocar
en su interior a otro subprograma y éste a su vez a otro, y éste último a otro
más, etc., un máximo de 8 veces). Flowol no comprueba el exceso de
subprogramas o de niveles de anidamiento, de modo que si los mencionados
límites se exceden, el programa parece estar correcto pero en su ejecución
aparecerán resultados erróneos.

En particular, un subprograma se puede llamar a sí mismo. Esto se conoce


como recursividad. No se suele utilizar dado que consume una gran cantidad de
recursos de la computadora.

2. Llamada desde el programa principal

Una vez se tienen definidos uno o más subprogramas, cualquiera de ellos puede
ser invocado desde el programa principal.

Para ello es preciso insertar el bloque Proceso en un punto


del programa: no hay más que pulsar sobre el símbolo
indicado en la figura adjunta de la barra de herramientas,
arrastrarlo y hacer clic en el punto seleccionado. En este
momento se abre el cuadro de diálogo Editar Proceso que
permite introducir los datos necesarios para manejar las
salidas.
El botón Sub da acceso a una lista de los subprogramas previamente definidos,
de forma que se puede seleccionar a cuál de ellos se desea invocar.

Si, por ejemplo, se selecciona el denominado 1(Nom_sub), se obtiene el bloque:

de modo que pulsando Aceptar se tiene el bloque:

que interrumpe el flujo del programa principal para comenzar a ejecutar el


contenido del subprograma. Cuando se alcanza el bloque terminador Alto del
mismo, el programa principal continúa su ejecución en el punto donde lo dejó.

Si en el anterior cuadro Editar Proceso se hubiese pulsado alguno de los botones


numéricos (1-9), por ejemplo, el 5, se hubiese obtenido el bloque:
Este, ejecuta el nº de veces elegido (en este caso 5), las instrucciones contenidas
en el subprograma antes de devolver el control al programa principal. Utilizando
este recurso, el programa presentado anteriormente se puede reescribir de
manera muy compacta:

La llamada repetida a un subprograma podría servirnos también, por ejemplo,


para emitir un sonido de larga duración a partir de un sonido de menor duración.
En el siguiente ejemplo se emite un sonido de 5 s de duración a base de repetir
un sonido que dura en realidad 1 s.
Procedimientos

Los procedimientos son subrutinas las cuales nunca retornan un valor de salida. En
el código de hoy, las siguientes subrutinas son procedimientos:

 multiplicar
 sumarVectores
 mostrarVector
 main

En efecto, main también es un procedimiento. En este caso, main es un


procedimiento con el vector de String args. En otros lenguajes como C++ el método
main puede retornar algún valor que indica el estado en el cual acaba el programa,
pero en Java no sucede así. Sin embargo, a diferencia del main si queremos utilizar
los otros procedimientos y funciones tendremos que llamarlos directamente en
nuestro código de la siguiente forma:

// Sin parámetros
nombreRutina();
// Con parámetros
nombreRutina(argumento1, argumento2, ..., argumentoN);

Podemos entender una subrutina como una sentencia más de forma que podemos
utilizarla incluso en bloques if-else. También podemos pasar como parámetro otra
subrutina tal y como vemos en el código de hoy:
System.out.println("> z + (x^y) = " + sumar(z, potencia(x, y)));

En este caso estamos pasándole a la subrutina sumar la variable z y el resultado de


evaluar la subrutina potencia(x, y). Si queremos verlo de forma matemática para
este caso realmente estamos haciendo z + (x^y) . Para indicar que un
procedimiento no devolverá valor, tenemos que escribir void en el campo
tipoRetorno. De esa forma decimos que no habrá valor de retorno:

static void multiplicar(int x, int y) {


x *= y;
System.out.println("> Dentro del procedimiento la x vale " + x);
}

Nota: de momento definiremos las subrutinas escribiendo static al comienzo de su


declaración. Más adelante explicaré qué significa hacer eso.

Funciones

Las funciones son similares a los procedimientos. Difieren principalmente en que


las funciones siempre retornan un valor, independientemente de que tengan o no
parámetros de entrada. En el código de hoy, las siguientes subrutinas son
procedimientos:

 sumar
 potencia
 sumarVectores
 reiniciarVector
 sumatorio

En todos ellos siempre se recibe uno o más valores y finalmente se devuelve un


tercer valor. Para indicar qué tipo de valor devolverá en lugar de escribir void como
hacíamos con los procedimientos, ponemos el tipo de dato que devolverá. Por
ejemplo:

static int[] reiniciarVector(int[] vector) {


final int TAM_VECTOR = vector.length;
int[] resultado = new int[TAM_VECTOR];
for (int i = 0; i < TAM_VECTOR; i++)
resultado[i] = -1;
return (resultado);
}

En este caso estamos indicando que la función reiniciarVector devolverá un array


de tipo int. Para devolver un valor en las funciones utilizamos la palabra
reservada return seguida de la variable/vector/objeto a devolver. Nota: No es
necesario usar paréntesis en el return, pero es buena práctica hacerlo.

Valor y Referencia

Aquellos que vengan de otros lenguajes como C++ se preguntarán si en Java existe
lo que se conoce como pasar variables por referencia o valor . Cuando le pasamos
un argumento a una subrutina, se dice que se pasa por valor cuando se crea una
copia temporal en una variable auxiliar dentro de la subrutina. Dicha copia
podemos modificarla dentro de la subrutina, pero la variable indicada como
argumento mantendrá el valor que tenía en el momento de llamar a la subrutina.

static void multiplicar(int x, int y) {


x *= y;
System.out.println("> Dentro del procedimiento la x vale " + x);
}

En el procedimiento multiplicar modificamos el valor del primer argumento dentro


del código. No obstante, cuando mostramos por pantalla los resultados vemos que
nos salen cosas distintas:

> Dentro del procedimiento la x vale 10


> Fuera de multiplicar la x vale 2

Esto se debe a que cambiamos el contenido de la variable temporal, pero no el de


la variable original. Por eso se le llama pasar parámetros por valor. El caso
contrario, pasar parámetros por referencia consiste en modificar directamente el
valor de la variable original sin crear variables temporales. Como esto es una mala
práctica, Java no lo permite y se limita a pasar siempre las variables y los arrays
por valor (en el caso de los objetos siempre se pasan por referencia).

Número de argumentos de una subrutina

Antes comenté que el número de argumentos de una subrutina es siempre finito.


Existen ocasiones donde necesitamos declarar una subrutina donde no sepamos
cuántos argumentos puede obtener. Java permite definir funciones con argumentos
variables mediante la siguiente estructura:

tipoDato ... alias

Haciendo eso estamos indicando que la subrutina podrá recibir una cantidad
variable de argumentos. Si nos vamos al código de hoy tenemos una función con
dicho comportamiento:
static int sumatorio(int ... n) {
int resultado = 0;
for (int i: n)
resultado += i;
return (resultado);
}

La función sumatorio suma entre sí todos los números pasados por argumento. Una
forma equivalente de ver este código es la siguiente:

static int sumatorio(int[] n) {


int resultado = 0;
for (int i: n)
resultado += i;
return (resultado);
}

No obstante al llamar a la función tendríamos que pasarle en lugar de tantos


números como quisieramos, un vector con los números almacenados:

// Forma 1
sumatorio(3, 2, 8, 10, 22, 13);
// Forma 2
sumatorio(new int[] {3, 2, 8, 10, 22, 13});

Вам также может понравиться