Subrutinas: procedimientos y funciones - 1


Una subrutina es una parte separada del programa que tiene un nombre y resuelve su propia tarea separada. La subrutina se encuentra al comienzo del programa principal y se puede iniciar (llamar) desde el programa principal especificando el nombre

El uso de subrutinas le permite evitar la duplicación de código, en caso de que necesite escribir el mismo código en diferentes lugares del programa. 
Las bibliotecas que se importan a un programa (por ejemplo, la biblioteca de matemáticas math) consisten en subrutinas que ya han sido compiladas por alguien. Los programadores no necesitan pensar en qué algoritmos implementarán, sino simplemente aplicarlos, pensando solo en lo que están haciendo exactamente. Este es un gran ahorro de tiempo. No es necesario escribir un algoritmo que ya haya sido escrito por otra persona.

Cada rutina solo debe hacer una cosa:  simplemente calcule algo, genere algunos datos o haga otra cosa. 

Hay dos tipos de subrutinas: procedimientos y funciones

Las subrutinas realizan algunas acciones, como imprimir el resultado en la pantalla de cierta forma (un ejemplo simple, la declaración writeln() es una subrutina estándar que imprime en información de la pantalla)

Las subrutinas de función devuelven un resultado (número, cadena de caracteres, etc.) que podemos usar en el programa principal.

Tratemos de escribir un procedimiento simple:
Supongamos que necesitamos mostrar la cadena "Error" en la pantalla cada vez que puede ocurrir un error en el código por culpa del usuario (por ejemplo, cuando ingresa datos incorrectos)
Esto se puede hacer escribiendo la declaración writeln('Error'); Y ahora imagine que esa línea debe insertarse en muchos lugares del programa. Por supuesto, puedes escribirlo en todas partes. Pero esta solución tiene dos inconvenientes.
1) esta cadena se almacenará en la memoria muchas veces
2) si queremos cambiar la salida en caso de error, tendremos que cambiar esta línea en todo el programa, lo cual es bastante inconveniente

Para tales casos, se necesitan procedimientos.
Un programa con un procedimiento podría verse así: ... utilizando el espacio de nombres estándar; procedimiento imprimirError(); // descripción del procedimiento comenzar writeln('Error'); // cuerpo del procedimiento: comandos que ejecutará el procedimiento fin; // programa principal comenzar; ... error de impresión(); // inicia el procedimiento para su ejecución. Solo especificamos el nombre del procedimiento que queremos ejecutar. ... error de impresión(); ... fin. El procedimiento comienza con la palabra procedure. Después del nombre del procedimiento se escriben paréntesis, que indican las variables y sus tipos de las que depende la ejecución del procedimiento. Por ejemplo:

var a, b, respuesta: entero;
procedimiento Suma(a, b: entero);
empezar
    respuesta := a + b;
fin;

Todas las sentencias que se ejecutan en un procedimiento están sangradas. 

Los procedimientos se escriben antes que el programa principal

Para ejecutar un procedimiento, en el programa principal debe llamarlo por su nombre y recordar escribir paréntesis!
Puede llamar a un procedimiento en un programa cualquier número de veces.

Ahora imaginemos que necesitamos mostrar diferentes mensajes en respuesta al error de un usuario, dependiendo del tipo de error que haya cometido.
En este caso, puede escribir su propio procedimiento para cada error:   procedimiento imprimirErrorCero(); comenzar writeln('Error. ¡División por cero!'); fin; procedimiento imprimirEntradaError(); comenzar writeln('Error en la entrada!'); fin; ¿Qué pasa si hay muchos más errores posibles? ¡Esta solución no nos conviene!
Necesitamos aprender a controlar el procedimiento diciéndole qué mensaje de error mostrar.
Para hacer esto, necesitamos parámetros que escribiremos entre paréntesis después del nombre del procedimiento procedimiento printError(s: cadena); comenzar escritura(s); fin; En este procedimiento, s es un parámetro, una variable especial que le permite controlar el procedimiento.
El parámetro es una variable que determina cómo funciona la subrutina. Los nombres de los parámetros se enumeran separados por punto y coma en el encabezado del subprograma. Después del parámetro, dos puntos son seguidos por su tipo.

Ahora, al llamar al procedimiento, debe indicar entre paréntesis el valor real que se le asignará al parámetro (variable s) dentro de nuestro procedimiento printError('¡Error! ¡División por cero!'); Este valor se llama argumento.
El argumento es el valor del parámetro que se pasa a la subrutina cuando se llama.
Un argumento puede ser no solo un valor constante, sino también una variable o una expresión aritmética.

A menudo es necesario utilizar variables adicionales que solo se utilizarán en la subrutina. Estas variables se denominan locales (o locales) y solo se pueden manipular dentro de la subrutina en la que se crean.
 
Ámbito de variable local es la función o procedimiento dentro del cual se declara

Así, es posible limitar el alcance (scope) de una variable solo a la subrutina donde realmente se necesita. En programación, esta técnica se denomina encapsulación  - ocultar una variable para que no se modifique desde el exterior.

Si es necesario declarar una variable que sería visible en cualquier parte del programa (en cualquier subrutina), dichas variables se declaran fuera de todas las subrutinas (consulte el programa 3 de la tabla a continuación)
Estas variables se denominan globales.

Analice tres programas:

1) En este programa, la variable i es local. Una variable local se declara dentro de una subrutina 2) Aquí, aunque haya una variable i en el programa principal (con valor 7), se creará una nueva variable local i con valor 5. 
Cuando ejecute este programa, la pantalla mostrará el valor 75
3) Este programa tiene una variable global i. Su valor se puede cambiar dentro de una subrutina, y dentro del programa principal
El procedimiento trabajará con la variable global i y se le asignará un nuevo valor igual a 2. Se muestra en pantalla el valor 2
prueba de procedimiento();
var i: entero;
empezar
    yo := 5;
    escribir(i);
fin;
var i: entero;

prueba de procedimiento();
var i: entero;
empezar
    yo := 5;
    escribir(i);
fin;

empezar
    yo := 7;
    escribir(i);
    prueba();
fin.
var i: entero;

prueba de procedimiento();
empezar
    yo := 2;
fin;

empezar
    prueba();
    escribir(i);
fin.
Problema: escriba un procedimiento que intercambie los valores de dos variables.
Las peculiaridades de esta tarea son que necesitamos que los cambios realizados en el procedimiento sean conocidos por el programa que llama.

Intentemos escribir el procedimiento así:

var x, y: entero; procedimiento Swap(a, b: entero); // con tal descripción de los parámetros del procedimiento, var c: entero; begin // copiará los valores de los argumentos (x e y) // las variables a y b son variables independientes no relacionadas con x e y c := un; un := b; b := c; fin; comenzar x := 1;   y := 2; Intercambiar (x, y); //los valores de las variables x e y (argumentos) se copian en los parámetros a y b writeln('x = ', x, ', y = ', y); // x=1, y=2 fin. Si ejecuta este programa, puede ver que los valores de las variables x e y no han cambiado. Para que los parámetros cambien los valores de los argumentos, debe usar pasar datos por referencia.Para hacer esto, después del nombre del tipo de datos en la cabecera de la subrutina se debe poner la palabra var  procedimiento Swap(var a, b: entero);   // ahora las variables a y b obtienen las direcciones de las variables x e y en la memoria var c: entero;  comenzar c := un; un := b; b := c; fin; Uso: Si pasa un argumento por referencia, entonces solo el nombre de la variable (NO un número y NO una expresión aritmética) puede estar en este lugar al llamar al procedimiento.< br />
NO llame a un procedimiento como este: Intercambiar(x, 4); Intercambiar(5+x, y);