21 - Procedimientos: conceptos

Hasta ahora hemos trabajado con una metodología de programación lineal. Todo el algoritmo de nuestro programa se ejecutan en forma secuencial de principio a fin.

Esta forma de organizar un programa solo puede ser llevado a cabo si el mismo es muy pequeño (decenas de líneas)

Cuando los problemas a resolver tienden a ser más grandes la metodología de programación lineal se vuelve ineficiente y compleja.

El segundo paradigma de programación que veremos es la programación estructurada.

La programación estructurada busca dividir o descomponer un problema complejo en pequeños problemas. La solución de cada uno de esos pequeños problemas nos trae la solución del problema complejo.

En Delphi/Pascal el planteo de esas pequeñas soluciones al problema complejo se hace dividiendo el programa en procedimientos y funciones.

Primero veremos el concepto de procedimiento y en un concepto futuro veremos las pequeñas diferencias que tiene una función.

Un procedimiento es un conjunto de instrucciones en Delphi/Pascal que resuelven un problema específico.

El lenguaje Delphi/Pascal ya tiene incorporado algunos procedimientos básicas. Algunos de ellos ya las utilizamos en conceptos anteriores como son los procedimientos: ReadLn, Write, WriteLn.

Veamos ahora como crear nuestros propios procedimientos.

El tema de procedimientos en un principio puede presentar dificultades para entenderlo y ver sus ventajas ante la metodología de programación lineal que veníamos trabajando en conceptos anteriores.

Los primeros problemas que presentaremos nos puede parecer que sea más conveniente utilizar programación lineal en vez de programación estructurada con procedimientos.

A medida que avancemos veremos que si un programa empieza a ser más complejo (cientos de líneas, miles de líneas o más) la división en pequeños procedimientos nos permitirá tener un programa más ordenado y fácil de entender y por lo tanto en mantener.

La sintaxis para declarar un procedimiento en Delphi/Pascal es:

procedure [nombre del procedimiento];
begin
 [Instrucciones]
end;

Problema 1

Confeccionar una aplicación que muestre una presentación en pantalla del programa.
Solicite la carga de dos valores y nos muestre la suma.
Mostrar finalmente un mensaje de despedida del programa.
Implementar estas actividades en tres procedimientos.

Proyecto83

program Proyecto83;

{$APPTYPE CONSOLE}

procedure Presentacion;
begin
  WriteLn('Programa que permite cargar dos valores por teclado.');
  WriteLn('Efectúa la suma de los valores');
  WriteLn('Muestra el resultado de la suma');
  WriteLn('*******************************');
end;

procedure CargaSuma;
var
  valor1: Integer;
  valor2: Integer;
  suma: Integer;
begin
  Write('Ingrese el primer valor:');
  ReadLn(valor1);
  Write('Ingrese el segundo valor:');
  ReadLn(valor2);
  suma := valor1 + valor2;
  WriteLn('La sumade los dos valores es:', suma);
end;

procedure Finalizacion;
begin
  WriteLn('*******************************');
  WriteLn('Gracias por utilizar este programa');
end;

{bloque principal del programa}
begin
  Presentacion;
  CargaSuma;
  Finalizacion;
  ReadLn;
end.

La forma de organizar nuestro programa cambia en forma radical.

El programa comienza a ejecutarse como siempre en el bloque principal del programa donde tenemos las llamadas a los procedimientos:

{bloque principal del programa}
begin
  Presentacion;
  CargaSuma;
  Finalizacion;
  ReadLn;
end.

Primero en el archivo declaramos los tres procedimientos llamados Presentacion, CargaSuma y Finalizacion.

La sintaxis para declarar un procedimineto es mediante la palabra clave procedure seguida por el nombre del procedimineto (el nombre del procedimiento no puede tener espacios en blanco ni comenzar con un número)

Luego del nombre del procedimineto mediante un bloque begin end disponemos el algoritmo del procedimiento propiamente dicho:

procedure Presentacion;
begin
  WriteLn('Programa que permite cargar dos valores por teclado.');
  WriteLn('Efectúa la suma de los valores');
  WriteLn('Muestra el resultado de la suma');
  WriteLn('*******************************');
end;

Dentro del procedimiento implementamos el algoritmo que pretendemos que resuelva ese procedimineto, por ejemplo el procedimiento Presentacion tiene por objetivo mostrar en pantalla el objetivo del programa.

La palabra clave end de cada procedimiento finaliza con un punto y coma a diferencia del end final del bloque principal que finaliza con un punto.

Si un procedimiento necesita almacenar datos y solo utilizarlos en dicho procedimiento podemos definir variables locales en una sección var:

procedure CargaSuma;
var
  valor1: Integer;
  valor2: Integer;
  suma: Integer;
begin
  Write('Ingrese el primer valor:');
  ReadLn(valor1);
  Write('Ingrese el segundo valor:');
  ReadLn(valor2);
  suma := valor1 + valor2;
  WriteLn('La sumade los dos valores es:', suma);
end;

Las variables locales valor1, valor2 y suma solo se pueden manipular dentro del procedimiento CargaSuma.

El tercer procedimiento de nuestro programa muestra un mensaje de despedida:

procedure Finalizacion;
begin
  WriteLn('*******************************');
  WriteLn('Gracias por utilizar este programa');
end;

Es importante remarcar que todo programa en Delphi/Pascal comienza en el bloque begin end. que indicamos al final del archivo:

{bloque principal del programa}
begin
  Presentacion;
  CargaSuma;
  Finalizacion;
  ReadLn;
end.

Como podemos comprobar para llamar a un procedimiento debemos invocarlo por su nombre:

  Presentacion;

Desde el bloque principal se invocan los procedimientos en el orden que necesitemos:

invocación procedimientos en Delphi/Pascal

Para ejecutar una instrucción por vez en el entorno de Delphi podemos presionar la tecla especial "F7". Esta es una forma muy didáctica de ver el orden de ejecución de las instrucciones de nuestro programa.

Recordemos que lo que encerramos entre llaves es un comentario y por lo tanto no es obligatorio disponerlo en nuestro programa:

{bloque principal del programa}

Problema 2

Confeccionar una aplicación que solicite la carga de dos valores enteros y muestre su suma.
Repetir la carga e impresión de la suma 5 veces.
Mostrar una línea separadora después de cada vez que cargamos dos valores y su suma.

Proyecto84

program Proyecto84;

{$APPTYPE CONSOLE}

procedure CargaSuma;
var
  valor1: Integer;
  valor2: Integer;
  suma: Integer;
begin
  Write('Ingrese el primer valor:');
  ReadLn(valor1);
  Write('Ingrese el segundo valor:');
  ReadLn(valor2);
  suma := valor1 + valor2;
  WriteLn('La suma de los dos valores es:', suma);
end;

procedure Separacion;
begin
  WriteLn('********************************');
end;


var
  f: Integer;

{bloque principal del programa}
begin
  for f:=1 to 5 do
  begin
    CargaSuma;
    Separacion;
  end;
  ReadLn;
end.

El resultado de ejecutar este programa tiene una salida por pantalla similar a esta:

invocación procedimientos en Delphi/Pascal

Hemos declarado dos procediminetos, una que permite cargar dos enteros sumarlos y mostrar el resultado:

procedure CargaSuma;
var
  valor1: Integer;
  valor2: Integer;
  suma: Integer;
begin
  Write('Ingrese el primer valor:');
  ReadLn(valor1);
  Write('Ingrese el segundo valor:');
  ReadLn(valor2);
  suma := valor1 + valor2;
  WriteLn('La suma de los dos valores es:', suma);
end;

Y otro que tiene por objetivo mostrar una línea separadora con asteriscos:

 
procedure Separacion;
begin
  WriteLn('********************************');
bnd;

Ahora nuestro bloque principal del programa, recordemos que estas líneas son las primeras que se ejecutarán cuando iniciemos el programa:

var
  f: Integer;

{bloque principal del programa}
begin
  for f:=1 to 5 do
  begin
    CargaSuma;
    Separacion;
  end;
  ReadLn;
end.

Como vemos podemos llamar al procedimineto CargaSuma y Separacion muchas veces en nuestro caso en particular 5 veces.

Lo nuevo que debe quedar claro es que la llamada a los procediminentos desde el bloque principal de nuestro programa puede hacerse múltiples veces (esto es lógico, recordemos que ReadLn es un procedimiento ya existente en Delphi/Pascal y lo llamamos múltiples veces dentro de nuestro algoritmo)

La variable f se lo define previo al bloque principal y solo se la puede utilizar en dicho bloque:

var
  f: Integer;

Problemas propuestos

  • Desarrollar un programa con dos procedimientos. El primero solicite el ingreso de un entero y muestre el cuadrado de dicho valor. El segundo que solicite la carga de dos valores y muestre el producto de los mismos. LLamar desde el bloque del programa principal a ambos procedimientos.
  • Desarrollar un procedimiento que solicite la carga de tres valores y muestre el menor. Desde el bloque principal del programa llamar 2 veces a dicho procedimiento (sin utilizar una estructura repetitiva)
Solución
program Proyecto85;

{$APPTYPE CONSOLE}

procedure CalcularCuadrado;
var
  valor: Integer;
  cuadrado: Integer;
begin
  Write('Ingrese un entero:');
  ReadLn(valor);
  cuadrado := valor * valor;
  WriteLn('El cuadrado es:', cuadrado);
end;

procedure CalcularProducto;
var
  valor1: Integer;
  valor2: Integer;
  producto: Integer;
begin
  Write('Ingrese primer valor:');
  ReadLn(valor1);
  Write('Ingrese segundo valor:');
  ReadLn(valor2);
  producto := valor1 * valor2;
  WriteLn('El producto de los dos valores es:', producto);
end;


{bloque principal del programa}
begin
  CalcularCuadrado;
  CalcularProducto;
  ReadLn;
end.




program Proyecto86;

{$APPTYPE CONSOLE}

{$R *.res}

procedure MenorValor;
var
  valor1: Integer;
  valor2: Integer;
  valor3: Integer;
begin
  Write('Ingrese primer valor:');
  ReadLn(valor1);
  Write('Ingrese segundo valor:');
  ReadLn(valor2);
  Write('Ingrese tercer valor:');
  ReadLn(valor3);
  if (valor1 < valor2) and (valor1 < valor3) then
  begin
    WriteLn('Menor valor:', valor1);
  end
  else
  begin
    if valor2 < valor3 then
    begin
      WriteLn('Menor valor:', valor2);
    end
    else
    begin
      WriteLn('Menor valor:', valor3);
    end;
  end;
end;


{bloque principal del programa}
begin
  MenorValor;
  MenorValor;
  ReadLn;
end.