AnteriorPosterior

15. Procedimientos y funciones

Por: Nacho Cabanes
Actualizado: 30-07-2019 16:00
Tiempo de lectura estimado: 12 min.

 

Versión en video (16:37 min):

Pascal

15. Procedimientos y funciones

15.1. Procedimientos.

Hemos visto cómo hacer que se repita un bloque de programa, usando estructuras como "for", "while" o "repeat". Pero cuando un fragmento de programa se debe repetir en varias partes de nuestro fuente, el resultado puede seguir siendo redundante. Por ejemplo, podemos escribir varias frases "subrayadas" con asterisco así:

(* PROC01.PAS, procedimientos: acercamiento *)
(* Curso de Pascal, por Nacho Cabanes       *)

program Proc01;

var
    i: byte;

begin
    { Primer texto }
    writeLn( 'Primer texto' );

    { Escribimos 20 asteriscos y avanzamos de linea }
    for i := 1 to 20 do
        write('*');
    writeLn;

    { Segundo texto }
    writeLn( 'Y un segundo texto' );

    { Escribimos 20 asteriscos y avanzamos de linea }
    for i := 1 to 20 do
        write('*');
    writeLn;

    { Tercer texto }
    writeLn( 'Texto de despedida' );

    { Escribimos 20 asteriscos y avanzamos de linea }
    for i := 1 to 20 do
        write('*');
    writeLn;
end.

(*
Resultado:
Primer texto
********************
Y un segundo texto
********************
Texto de despedida
********************
*)

Esto es claramente repetitivo. Podemos crear un "bloque" llamado "Escribir20asteriscos" y que sirva como una "abreviatura" que nos permita no tener que teclear tantos código repetitivo. Además, el repetir menos hace que el programa sea menos propenso a errores, ya sea en el momento de teclear o cuando vayamos a ampliarlo o corregirlo (por ejemplo, si queremos cambiar los 20 asteriscos por 18, corremos el riesgo de olvidar hacerlo en alguno de los bloques). Quedaría así:

(* PROC02.PAS, procedimientos: uso real *)
(* Curso de Pascal, por Nacho Cabanes   *)

program Proc02;

procedure Escribir20asteriscos;
var
    i: byte;
begin
    { Escribimos 20 asteriscos y avanzamos de linea }
    for i := 1 to 20 do
        write('*');
    writeLn;
end;

begin
    writeLn( 'Primer texto' );
    Escribir20asteriscos;
    writeLn( 'Y un segundo texto' );
    Escribir20asteriscos;
    writeLn( 'Texto de despedida' );
    Escribir20asteriscos;
end.

(*
Resultado:
Primer texto
********************
Y un segundo texto
********************
Texto de despedida
********************
*)

Estos bloques, que llamaremos "procedimientos" (y que en otros lenguajes de programación se conocen como "subrutinas") ayudarán a que nuestro programa sea menos repetitivo y resulte más fácil de leer.

En este programa, "i" es una variable local: se declara dentro del procedimiento "Escribir20asteriscos" y sólo es accesible dentro de él. Si en el cuerpo del programa intentamos hacer algo como "i:=2;" el programa no compilará, porque la variable no existe en esa zona. Debemos buscar conseguir que tantas variables como podamos sean locales. Sólo deberán ser "globales" (compartidas por todo el programa, y declaradas fuera de procedimientos) las variables que realmente se vayan a utilizar desde varias zonas distintas.

15.2. Procedimientos con parámetros.

La verdadera potencia de los procedimientos está en que no tienen por qué trabajar siempre con los mismos datos, sino que podemos indicarles unos datos adicionales, que llamaremos parámetros. Por ejemplo, podemos mejorar el procedimiento que escribía asteriscos, si le indicamos la cantidad de asteriscos que debe mostrar en pantalla, así:

(* PROC03.PAS, procedimientos con parametros *)
(* Curso de Pascal, por Nacho Cabanes        *)

program Proc03;

procedure EscribirAsteriscos( cantidad: integer );
var
    i: byte;
begin
    { Escribimos N asteriscos y avanzamos de linea }
    for i := 1 to cantidad do
        write('*');
    writeLn;
end;

begin
    writeLn( 'Primer texto' );
    EscribirAsteriscos(12);
    writeLn( 'Y un segundo texto' );
    EscribirAsteriscos(18);
    writeLn( 'Y texto de despedida' );
    EscribirAsteriscos(20);
end.

(*
Resultado:
Primer texto
************
Y un segundo texto
******************
Y texto de despedida
********************
*)

15.3. Funciones

En muchas ocasiones querremos obtener un valor como resultado de esa "subrutina" que hemos creado. Llamaremos "función" a un procedimiento capaz de devolver un valor. Por ejemplo, podríamos crear una función sencilla, que calcule (y devuelva) el doble del número que se le pase como parámetro, así:

(* DOBLE.PAS, Primer ejemplo de funcion *)
(* Curso de Pascal, por Nacho Cabanes   *)

program FuncionDoble;

function doble( numero: integer): integer;
begin
    doble := numero * 2;
end;

(* Cuerpo del programa *)
var
    n: integer;

begin
    write('Introduce un numero entero: ');
    readLn( n );
    writeLn('Su doble es: ', doble(n) );
    writeLn('Y el doble de 5 es: ', doble(5) );
end.

(*
Ejemplo de ejecucion:
Introduce un numero entero: 3
Su doble es: 6
Y el doble de 5 es: 10
*)

Aquí hay varios detalles que merece la pena comentar, algunos de ellos nuevos:

  • Esta función se llama "doble".
  • Tiene un parámetro llamado "numero", que es un número entero.
  • El resultado va a ser también un número entero.
  • Antes de salir de la función, le asignamos el que será su valor definitivo.
  • Desde el cuerpo del programa usamos la función 2 veces: la primera para calcular el doble del número "n", que ha introducido el usuario, y la segunda para hallar el doble de 5.

Una función puede recibir más de un parámetro, y puede realizar operaciones más complejas. Por ejemplo, podríamos calcular una potencia (un número elevado a otro) mediante multiplicaciones repetitivas, así:

(* POTENCIA.PAS, Segundo ejemplo de funcion *)
(* Curso de Pascal, por Nacho Cabanes       *)

program PruebaDePotencia;

function potencia(a,b: integer): integer;   (* Definimos la funcion *)
var
    i: integer;                      (* Locales: para bucles *)
    temporal: integer;               (* y para el valor temporal *)
begin
    temporal := 1;                    (* Inicializacion *)
    for i := 1 to b do
        temporal := temporal * a;     (* multiplicamos "b" veces por "a" *)
    potencia := temporal;             (* y finalmente devolvemos el valor *)
end;

var
    numero1, numero2: integer;

begin                                (* Cuerpo del programa *)
    writeLn('Potencia de un numero entero');
    writeLn;
    writeLn('Introduce el primer numero');
    readLn( numero1 );
    writeLn('Introduce el segundo numero');
    readLn( numero2 );
    writeLn( numero1 ,' elevado a ', numero2 ,' vale ',
        potencia (numero1, numero2) )
end.

Ejercicio propuesto 15.1.1: Crea un procedimiento llamado "Escribir10guiones", que escriba 10 guiones (el símbolo de la resta) en pantalla. Empléalo en un programa.

Ejercicio propuesto 15.1.2: Crea un procedimiento llamado "DibujarRectanguloAsteriscos", que muestre en pantalla un rectángulo de 10 asteriscos de ancho y 5 de alto. Utilízalo en un programa.

Ejercicio propuesto 15.1.3: Crea un procedimiento "EscribirVector", que escriba en pantalla los datos de un vector de números reales de 3 elementos. Los datos deben aparecer separados por comas, y debe haber un paréntesis abierto antes del primer dato y un paréntesis cerrado tras el tercer dato. El vector a mostrar será una variable global llamada "datos". Aplícalo a un programa que pida los datos al usuario y luego los muestre.

Ejercicio propuesto 15.2.1: Crea un procedimiento llamado "EscribirGuiones", que escriba en pantalla tantos guiones como se indique como parámetro. Empléalo en un programa.

Ejercicio propuesto 15.2.2: Crea un procedimiento llamado "DibujarRectanguloAsteriscos", que muestre en pantalla un rectángulo de asteriscos, del ancho y alto que se indiquen como parámetros. Utilízalo en un programa.

Ejercicio propuesto 15.2.3: Crea un procedimiento "EscribirVector", que escriba en pantalla los datos de un vector de números reales de 3 elementos. El vector se pasará al procedimiento como parámetro. Los datos deben aparecer separados por comas, y debe haber un paréntesis abierto antes del primer dato y un paréntesis cerrado tras el tercer dato.

Ejercicio propuesto 15.3.1: Crea una función "triple", que reciba un número real como parámetro, y devuelva como resultado ese número multiplicado por tres.

Ejercicio propuesto 15.3.2: Prepara una función llamada "media", que reciba dos números reales como parámetros, y devuelva como resultado su media aritmética.

Ejercicio propuesto 15.3.3: Crear una función "potenciaReal", que trabaje con números reales, y permita cálculos como 3.2 elevado a 1.7 (pista; hay que usar exponenciales y logaritmos, como vimos en el apartado 1.6.3

Ejercicio propuesto 15.3.4: Haz una función que halle la raíz cúbica del número que se le indique (pista: hallar una raíz cúbica es lo mismo que elevar a 1/3).

Ejercicio propuesto 15.3.5: Define las funciones Suma3 y Producto3, que calculen suma y producto de tres números enteros, y crea un programa que haga una operación u otra según escoja el usuario (empleando "case").

Por supuesto, una función puede devolver valores de otros tipos, no solo numéricos. Así, una función que nos devolviera la inicial de una palabra podría ser:

(* INICIAL.PAS, Funcion que devuelve char *)
(* Curso de Pascal, por Nacho Cabanes     *)

program FuncionInicial;

function inicial( texto: string): char;
begin
    inicial := texto[1];
end;

(* Cuerpo del programa *)
var
    frase: string;

begin
    write('Introduce una frase: ');
    readLn( frase );
    writeLn('Su primera letra es: ', inicial(frase) );
end.

(*
Ejemplo de ejecucion:
Introduce una frase: hola, que tal
Su primera letra es: h
*)

O bien podríamos recorrer una frase formada por varias palabras, para así construir y devolver una cadena que contenga las iniciales de todas ellas:

(* INICIALES.PAS, Funcion que devuelve un string *)
(* Curso de Pascal, por Nacho Cabanes            *)

program FuncionIniciales;

function iniciales( texto: string): string;
var
    temporal: string;
    i: byte;
begin
    temporal := '';
    temporal := temporal + texto[1];
    for i := 2 to length(texto) do
        if texto[i-1] = ' ' then
            temporal := temporal + texto[i];
    iniciales := temporal;
end;

(* Cuerpo del programa *)
var
    frase: string;

begin
    write('Introduce una frase con varias palabras: ');
    readLn( frase );
    writeLn('Sus iniciales son: ', iniciales(frase) );
end.

(*
Ejemplo de ejecucion:
Introduce una frase con varias palabras: hola, que tal
Sus iniciales son: hqt
*)

2509 visitas desde el 30-07-2019

AnteriorPosterior