lunes, 9 de marzo de 2009

Consulta de Fechas con un adoquery

datamodule2.ADOQueryrepresultados.Close;
datamodule2.ADOQueryrepresultados.SQL.Clear;
datamodule2.ADOQueryrepresultados.SQL.Add('Select * from resultados_emitidos,pacientes,convenios');
datamodule2.ADOQueryrepresultados.SQL.Add('where resultados_emitidos.cedula_paciente=pacientes.cedula');
datamodule2.ADOQueryrepresultados.SQL.Add('and resultados_emitidos.codigo_convenio = convenios.codigo');
datamodule2.ADOQueryrepresultados.SQL.Add('and fecha1 >= :fecha_emision and fecha2<= :fecha2');
datamodule2.ADOQuery1.Parameters.ParamByName('fecha1').value := DateTimePicker1.Date;
datamodule2.ADOQuery1.Parameters.ParamByName('fecha2').value := DateTimePicker2.Date;
datamodule2.ADOQueryrepresultados.Open;

miércoles, 4 de febrero de 2009

Cómo enviar E-mail con el cliente de correo electrónico por defecto desde Delphi

¿Cómo puedo enviar un E-Mail desde Delphi usando el cliente de correo electrónico por defecto instalado en tu pc (Outlook por ejemplo) si no tengo un navegador instalado?, pues es muy sencillo, utilizando un TMemo generamos el siguiente código:
uses   ShellAPI, Windows;
...
ShellExecute(0, 'open', PChar('mailto:bugreports@youremail.com?subject=
Bug%20Report&Body=' + MemoBugText.Text),   nil, nil, SW_SHOWNORMAL);

miércoles, 15 de octubre de 2008

Numeros aleatorios sin repeticion (una clase)

image006

Supongamos que tenemos que rellenar una lotería primitiva: tenemos que hallar 6 números aleatorios de entre 69 números pero sin que se repitan.
¿Como lo hacemos?, pues nada, aplicando la clase contenida en este truco.
En concreto acabo de hacer esto pues estoy haciendo una página web y necesito mostrar en la misma página 3 artículos aleatorios de una base de datos... y claro, que se me repitan en la misma página web 3 articulos no es muy estético que digamos...
Como en el asunto este se mezclan datos y funciones y procedures, he decidido meterlo todo en una clase para facilitar su reutilización.
He colocado todo en una unit, (llamada uTAlea) para que con sólo añadirla en la clausula uses de nuestra aplicación pueda ser utillizada.
Aqui está el código de la unit uTAlea que contiene la clase TAlea:

 unit uTAlea;
{Radikal, Q3 para Trucomania.}

interface

uses Windows,SysUtils;

type
{Array de booleanos de longitud variable}
TArrayBool = array[0..0] of boolean;
PArrayBool = ^TArrayBool;

{Clase para manejar numeros aleatorios}
TAlea = class
Maximo : integer; //Valor maximo de los numeros obtenidos
Lista : PArrayBool;
FaltanDeSacar : integer;
constructor Create(Rango:integer);
destructor Destroy; override;
procedure Reset; //Resetea la lista de numeros
function PillaNumero:integer; //Devuelve un numero aletorio sin repeticion
end;



implementation


constructor TAlea.Create(Rango:integer);
begin
{
Si los números a extraer no pueden ser repetidos
hemos de crear un array para almacenar cual ha salido y cual no
Como el array ha de ser variable, usamos el GetMem y
los punteros para que sirva tambien para versiones
anteriores a Delphi 4, que no incorporan los arrays
de longitud variable...
}

inherited Create;
Maximo:=Rango;
FaltanDeSacar:=Rango;
{Reservamos memoria para el array de longitud variable}
GetMem(Lista, 1+Maximo * SizeOf(Boolean));
ZeroMemory(Lista,1+Maximo * SizeOf(Boolean));
end;

destructor TAlea.Destroy;
begin
if Assigned(Lista) then FreeMem(Lista, 1+Maximo * SizeOf(Boolean));
inherited Destroy;
end;

function TAlea.PillaNumero:integer;
var
Numero: integer;
begin
if FaltanDeSacar=0 then raise exception.create( 'Error. No se pude sacar otro numero sin repetir'+#13+#10+
'Error. No more numbers are available');

{Buscamos un número que no haya salido ya}
repeat Numero:=Random(Maximo) until NOT Lista^[Numero];
{Lo apuntamos en la lista de numeros ya usados}
Lista^[Numero]:=TRUE;
{Decrementamos la cantidad de numeros que faltan por salir}
Dec(FaltanDeSacar);
Result:=Numero;
end;

procedure TAlea.Reset;
begin
ZeroMemory(Lista,1+Maximo * SizeOf(Boolean));
FaltanDeSacar:=Maximo;
end;

end.

Ya sabes, la grabas como uTAlea.PAS para poder usarla en tus proyectos.
Vamos con una aplicación de ejemplo para probar la clase:

  • Crea una aplicacion nueva, con una form que contenga un TMemo (Memo1) y un TButton (Button1)

  • Copia el uTAlea.PAS en el directorio de esa aplicacion

  • Añade TAlea en el uses de tu form

  • Mete el siguiente código en el OnCLick del Button1:
     procedure TForm1.Button1Click(Sender: TObject);
    var
    Ristra : TAlea;
    n : integer;
    begin
    Memo1.Lines.Clear;

    Ristra:=TAlea.Create(10);

    {Sacamos 10 numero sin repetir}
    for n:=1 to 10 do begin
    memo1.Lines.Add( IntToStr(Ristra.PillaNumero) );
    end;

    Memo1.lines.Add('Otros 5 numeros de entre 10...');

    Ristra.Reset;
    for n:=1 to 5 do begin
    memo1.Lines.Add( IntToStr(Ristra.PillaNumero) );
    end;

    Ristra.Free;
    end;
  • Calcular la Edad (en años) segun la fecha de nacimiento

    edad_cinturon
    procedure TForm1.Button1Click(Sender: TObject);

    function Edad(FechaNacimiento:string):integer;
    var
    iTemp,iTemp2,Nada:word;
    Fecha:TDate;
    begin
    Fecha:=StrToDate(FechaNacimiento);
    DecodeDate(Date,itemp,Nada,Nada);
    DecodeDate(Fecha,itemp2,Nada,Nada);
    if FormatDateTime('mmdd',Date) <
    FormatDateTime('mmdd',Fecha) then Result:=iTemp-iTemp2-1
    else Result:=iTemp-iTemp2;
    end;

    begin
    Label1.Caption:=intToStr(Edad('07/09/1969'));
    end;

    Mantener una Spash Screen unos segundos tras cargar la aplicación

    SplashScreen 

    En tu form principal, declara una variable pública llamada SplashScreenHandle:

     	var
    SplashScreenHandle:integer;

    En el fuente del projecto, añade una sección var como la siguiente:

     	VAR
    SplashScreen:TSplashScreen;

    Dentro de la sección begin-end, añade el siguiente código al principio:

     Begin
    {Mostramos la Splash Screen}
    {Show the splash screen}
    SplashScreen:=TSplashScreen.Create(Application);
    Splashscreen.show;
    SplashScreen.update;
    {Creamos la form principal}
    {Create the main form}
    Application.createform(MainForm,MainFormUnit);
    MainFormUnit.SplashScreenHandle:=SplashScreen.handle;
    {Aqui el resto de tu projecto...}
    {rest of your code goes here....}
    end.

    Entonces, en tu form principal, mediante un timer, ejecutamos éste código para cerrar la Splash Screen:

         SendMessage(SplashScreenHandle,WM_CLOSE,0,0);

    Agilizar la carga de tu aplicacion

    ¿ Tu aplicacion tarda mucho en cargar ?. Igual te interesa este truco...

    No crees todos los forms de golpe, crea sólo el inicial, y desde el crea dinámicamente los que vayas a utilizar, sólo cuando los vayas a utilizar. Es decir, en el IDE, en Project->Options tienes dos ventanas, una la de 'Autocreate forms' y otra, la de 'Available forms'. Pues pon sólo la principal en 'Autocreate forms'.

    Después, en el uses de la primera form, añades las units del resto de forms, y en el var de la primera form, declaras las variables TForm del resto de forms que vayas a crear.

    Un ejemplo de Form1 que crea una Form2:

    El uses de Form1:

     uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2;

    El var de Form1:

     var
    Form1: TForm1;
    Form2: TForm2;

    Y cuando quieras llamar a la Form2 desde Form1 usa:

     procedure TForm1.Button1Click(Sender: TObject);
    begin
    Form2:=TForm2.Create(self);
    Form2.Show;
    end;

    Si tras hacer todo esto, te sigue tardando mucho en cargar el primer form, puedes ponerle una Splash Screen (una pantalla inicial) en la que le pones el típico mensaje de 'cargando'.

    SplashScreen con progressbar

    SplashScreenProgressBarNoMessage Hacer que aparezca una ventana mientras se carga mi aplicacion (Splash Screen)
    se explica cómo hacer una SplashScreen.
    "SplashScreen con progressbar", esta pensado sobre todo para cuando abres bases de datos y se tarda un mundo en cargar el programa. Con el progressbar queda bastante bien...
    Primero debemos definir cuantos "pasos" va a tener el progressbar, en este caso el numero de bases de datos que vamos a abrir, luego establecemos por ejemplo el valor Max progressbar a 40 y el valor Step a 10 y hacemos 4 "stepit", seria de la siguiente manera:
    Este codigo esta en el evento OnCreate de una form principal, pero podriamos mandarlo llamar de otras forms siempre en el evento OnCreate.

     

     procedure TForm1.FormCreate(Sender: TObject);   
     begin
    Try
    DataBase1.Connected:=True
    Except
    ShowMessage('Cannot open DB1')
    End;
    SplashForm.ProgressBar.StepIt;
    SplashForm.update;
    Try
    DataBase2.Connected:=True
    Except
    ShowMessage('Cannot open DB2')
    End;
    SplashForm.ProgressBar.StepIt;
    SplashForm.update;
    Try
    Table1.Active:=True
    Except
    ShowMessage('Cannot open Table 1')
    End;
    SplashForm.ProgressBar.StepIt;
    SplashForm.update;
    Try
    Table2.Connected:=True
    Except
    ShowMessage('Cannot open Table 2')
    End;
    SplashForm.ProgressBar.StepIt;
    SplashForm.update;
    ...
    SplashForm.Free
    end;

    jueves, 7 de agosto de 2008

    Ventajas de migrar de Delphi 7 a Delphi 2007 for Win32 Part. 1

    Muchos desarrolladores que utilizan la versión 7 se Delphi preguntan cuales son las razones para cambiar a una nueva versión de Delphi, en este momento la mas nueva versión de Delphi 2007 para Win32, exclusivamente para desarrollo nativo – Win32. Como las discusiones sobre el asunto se extienden, vamos a presentar, en este articulo, las principales razones para hacer esta migración, presentando todos los nuevos recursos desde la versión de Delphi 7.

    Continuamos buscando mas calidad y mejor desempeño en el IDE y las aplicaciones generadas, con Delphi 2007 for Win32 tenderás mas desempeño en tiempo de desarrollo y en la aplicación final comparado a Delphi 7.

    Novedades en el compilador y el lenguaje desde Delphi 7

    Directiva inline

    Se trata de una nueva directiva que va aumentar el desempeño del compilador con solo agregar la palabra reservada “inline”. En este caso, el método es expandido, evitando su lectura a todo momento. Esta forma de acceso presenta mejores resultados para métodos pequeños, fuera del alcance de la unit o para rutinas con muchos parámetros. Para el caso de rutinas mas grandes, se recomienda hacer una análisis de costo-benefició en cuanto a su utilización

    A continuación se muestra el código una aplicación de consola, utilizando “inline” en la función Max. 

    program InlineDemo;
    {$APPTYPE CONSOLE}

    uses
      MMSystem;

      function Max(const X,Y,Z: Integer): Integer;inline
      begin
        if X > Y then
          if X > Z then Result := X
                   else Result := Z
        else
          if Y > Z then Result := Y
                   else Result := Z
      end;

    const
      Times = 10000000; // 10 millón
    var
      A,B,C,D: Integer;
      Start: LongInt;
      i: Integer;

    begin
      Random; // 0
      A := Random(4242);
      B := Random(4242);
      C := Random(4242);
      Start := TimeGetTime;
      for i:=1 to Times do
        D := Max(A,B,C);
      Start := TimeGetTime-Start;
      writeln(A,', ',B,', ',C,': ',D);
      writeln('Calling Max ',Times,' times took ',Start,' milliseconds.');
      readln

    end.

    Al ejecutar esté código y comparar los resultados se encuentra una reducción importante en el tiempo de respuesta. Los siguientes resultados se obtuvieron después de que se ejecutó la función Max 10 millones de veces en una computadora Pentium M 1.8GHz con 2GB RAM. . Aunque estos valores pueden cambiar una computadora a otra, las proporciones son similares.

    Con inline Sin inline
    25 milisegundos 68 milisegundos

    De acuerdo con lo visto en la tabla anterior, se observa que al utilizar la capacidad “inline”, el código compilado puede aumentar, su rendimiento más de un 50%.

    Sobrecarga de operadores

    type
       TMyClass = class
         class operator Sumar(a, b: TMyClass): TMyClass;      // Sumar las clases de tipo TMyClass
         class operator Restar(a, b: TMyClass): TMyclass; // Restar las clases de tipo TMyClass
         class operator Implicit(a: Integer): TMyClass;     // Conversión implícita  para la clase de tipo TMyClass
         class operator Implicit(a: TMyClass): Integer;     // Conversión implícita de la clase TmyClass para Integers.
         class operator Explicit(a: Double): TMyClass;      // Conversión explicita de un Double para la clase TMyClass
       end;

    // Ejemplo de implementación del método Sumar
    class operator TMyClass.Add(a, b: TMyClass): TMyClass;
    begin
       // ...
    end;

    var
    x, y: TMyClass;
    begin
       x := 12;      // Conversión implícita de un Integer, ejecuta el método Implicit
       y := x + x;   // Ejecuta TMyClass.Add(a, b: TMyClass): TMyClass
       b := b + 100; // Ejecuta TMyClass.Add(b, TMyClass.Implicit(100))
    end;

    Class Helpers

    Los Class Helpers permiten extender clases sin utilizar herencia. Este recurso es importante, pues algunas clases, llamadas clases Selead, no pueden ser heredadas. La utilización de este nuevo recurso es muy apreciada. A continuación se muestra un ejemplo.

    type
       TMyClass = class
          procedure MyProc;
          function  MyFunc: Integer;
       end;

       ...

       procedure TMyClass.MyProc;
       var X: Integer;
       begin
          X := MyFunc;
       end;

       function TMyClass.MyFunc: Integer;
       begin
           ...
       end;

    ...

    type
       TMyClassHelper = class helper for TMyClass
         procedure HelloWorld;
         function MyFunc: Integer;
       end;

       ...

       procedure TMyClassHelper.HelloWorld;
       begin
          writeln(Self.ClassName); // Self hace referencia al tipo TMyClass y no TMyClassHelper
       end;

       function TMyClassHelper.MyFunc: Integer;
       begin
         ...
       end;
    ...
    var
      X: TMyClass;
    begin
      X := TMyClass.Create;
      X.MyProc;    // Ejecuta TMyClass.MyProc
      X.HelloWorld; // Ejecuta TMyClassHelper.HelloWorld
      X.MyFunc;    // Ejecuta TMyClassHelper.MyFunc

    Vale la pena observar que la referencia es siempre a la clase TMyClass. El compilador sabe cuando ejecutar la llamada a TMyClassHelper.

    Strict private y Strict protected

    Ahora en Delphi Win32 y .NET se tienen dos formas adicionales de determinar la visibilidad de los atributos de una clase: strict private y strict protected.

    Strict private: todos los atributos de la clase son visibles únicamente en la clase que fueron declarados. Estos atributos no estarán visibles para métodos declarados en la misma unit y para aquellos que no forman parte de la clase.

    Strict protected: Específica que los atributos da clase son visibles para la propia clase y sus descendentes.

    Los Records ahora soportan métodos

    Las capacidades de los registros (records) han sido incrementadas, pasando a ser casi lo mismo que una clase (Class), con soporte ha:
    Constructores.
    Sobre posición de operadores.
    Declaración de métodos no-virtuales.
    Métodos y propiedades estáticos.

    Veamos un ejemplo de la implementación de un registro con estas nuevas características:

    Type
        TMiRegistro = Record
        Type
             TTipoColor = Integer;
        Var
             Rojo : Integer;
             Class Var
             Azul : Integer;
             Procedure imprimirRojo();
    Constructor Create(Val : Integer);
             Property pRojo : TTipoColor Read Rojo Write Rojo;
             Class Property  pAzul : TTipoColor Read Azul Write Azul;
        End;

        Constructor TMiRegistro.Create(Val: Integer);
    Begin
      Rojo := Val;
    End;

    Procedure TMiRegistro.imprimirRojo;
    Begin
      WriteLn('Rojo: ', Rojo);
    End;

    De acuerdo a lo visto anteriormente los registros pueden utilizar muchas de las funcionalidades que hasta entonces eran exclusivas de las clases, sin embargo los registros no son clases y tienen muchas diferencias:
    Los Registros no tienen soporte a herencia;
    Los Registros pueden tener partes variable, las clases no;
    Los Registros son tipos de datos y pueden, entre otras cosas, ser copiados, clases no;
    Los Registros no tienen destructores;
    Los Registros no tienen soporte a métodos virtuales;

    Class abstract, Class sealed, Class const, Class type, Class var, Class property

    Diversas nuevas formas de declaración de clases, tipos, variables y propiedades.

    Class abstract -Especifica una clase abstracta.

    Class sealed - Especifica que la clase no puede ser heredada.

    Class const - Especifica una constante para la clase, que puede ser accedida sin necesidad de crear instancias de la clase.

    Class type -Define uno tipo para la clase que puede ser accedida sin necesidad de crear instancias de la clase.

    Class var -Define una variable en el scope de la clase que puede ser accedida sin necesidad de crear instancias de la clase.

    Class property -Define propiedad que puede ser accedida sin la necesidad de crear instancias de la clase.

    Nested Clases

    De una forma más didáctica, las clases Nested (o anidadas) serian como subclases, que pueden ser accedidas a partir de una clase y su tipo declarado dentro del contexto. Ejemplo de clase:

    type
          TOuterClass = class
           strict private
              myField: Integer;
           public
              type
                 TInnerClass = class
                  public
                    myInnerField: Integer;
                    procedure innerProc;
                 end;

             procedure outerProc;
           end;

    El método de la clase interna se implementa de la siguiente manera:

    procedure TOuterClass.TInnerClass.innerProc;
    begin
       ...
    end;

    Finalmente el siguiente código muestra como acceder al método que está en la clase anidada:

    var
       x: TOuterClass;
       y: TOuterClass.TInnerClass;

    begin
       x := TOuterClass.Create;
       x.outerProc;
       ...
       y := TOuterClass.TInnerClass.Create;

    Métodos finales

    Los Métodos declarados con final especifican que el mismo método no pode ser sobrepuesto (override) en clases descendentes, sin embargo se puede declarar uno método con el mismo nombre siendo virtual.

    Static class method

    Son clases que cuando son declaradas como Static no necesitan ser instanciadas para ser accedidas.

    For … in

    Ahora es posible hacer un for directo en objetos que contengan collections, arrays, expresiones string y expresiones de tipo set, tanto para Delphi Win32 como para .NET. Ejemplos:

    Ejemplo: Iteración en un Array

    var
      IArray1: array[0..9] of Integer   = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
      I: Integer;

    begin
      for I in IArray1 do
         begin
             // Hacer algo aquí...
         end;

    Ejemplo: iteración en un String:

    var
      C: Char;
      S1, S2: String;

      OS1, OS2: ShortString;
      AC: AnsiChar;
    begin

      S1 := ‘Nuevos recursos en Delphi 2007';
      S2 := '';

      for C in S1 do
        S2 := S2 + C;

      if S1 = S2 then
        WriteLn('SUCESSO #1');
      else
        WriteLn('FALHOU #1');

      OS1 := 'Migrando de Delphi 7 para Delphi 2007...';
      OS2 := '';

      for AC in OS1 do
        OS2 := OS2 + AC;

      if OS1 = OS2 then
        WriteLn('EXITO #2');
      else
        WriteLn('FALLOU #2');

    end.

    Novedades en el IDE desde Delphi 7

    El IDE trae una serie de novedades, como:

    MSBuild à controle todo el proceso de compilación de su aplicación, los pasos antes y después de compilar un proyecto, esto es excelente para los desarrolladores que necesitan automatizar la compilación. Cuando abrir un proyecto en Delphi 2007, automáticamente el mismo va ser convertido para el nuevo formato y con la extensión DPROJ, para soportar MSBuild.

    Vista e XP Themes à el IDE soporta los temas para Windows Vista y XP. Ahora es default y puedes habilitar y deshabilitar a través de las opciones de proyecto.

    Project Manager à el project manager soporta múltiplas selecciones y con esto permite abertura, grabación y borrar mas de un archivo simultáneamente.

    File Browser à con el File Browser no tenemos que abrir Windows Explorer o ir al menú File Open todo tiempo para abrir un archivo, pues File Browser ofrece acceso directo a su árbore de carpetas de dentro del IDE.

    Live Templates, Block Completion, indicador de líneas alteradas

    Los nuevos recursos de live template extienden la capacidad de crear plantillas de código en Delphi. Estas plantillas son creadas en un archivo XML y ayudan a programar escribiendo menos código.

    image

    Figure 1. Creando un try..finally utilizando la capacidad de LiveTemplates.

    La capacidad de block completion es uno de los recursos que habilitan el begin y end automático. ¿Quién nunca se perdió con begin y end?

    En la figura 1, tenemos una marcación amarilla y otra verde, la amarilla representa las líneas que fueron cambiadas, mientras las verdes son líneas que no cambiaran.

    Histórico de los cambios

    Independiente de una herramienta de control de versiones, las alteraciones en fuentes son versionadas localmente, permitiendo la comparación entre las versiones.

    image

    Figura 2. Versionamento local y comparación entre 2 fuentes

    Depurador

    El nuevo depurador trae diversas mejoras en variables locales, call stack y otros, sin embargo una de las principales novedades es la visualización en árboles. Véase un ejemplo:

    image

    Figura 3. Depurando una aplicación y visualizando las variables en TreeView

    También es posible configurar la barra de enrollamiento de la ventana de eventos y abrir separadamente cada ítem de la ventana de CPU, con un simples drag-and-drop presionando la tecla CTRL, la ventana se queda transparente, facilitando la lectura del código durante la depuración.

     

    Refactoring

    Esta es una de las capacidades que más les gustan a los usuarios de Delphi 7, ya que a través de los refactorings se pueden renombrar clases, variables y métodos de manera que al hacer un cambio de nombre se cambien automáticamente todas las líneas de código en los que se hacía referencia al nombre anterior. Mediante esta capacidad de refactoring es posible también cambiar los parámetros de clases, seleccionar parte del código y generar un método a partir del bloque seleccionado, también es posible mover métodos de una clase a otra, entre muchas otras cosas.

    Unidades de Prueba

    La integración con unidades de pruebas a través de DUnit facilitan la creación de métodos y en general código de pruebas que se usa para probar el código de la propia aplicación. Esto facilita la notablemente la prueba de las aplicaciones, pues es como si se tuviese un “programa que prueba al programa”.

    SQL Window - Query Builder

    Ahora a través del DataExplorer podemos construir querys visualmente utilizando el Query Builder, desde simples sentencias select hasta complejos querys utilizando joins.

    image

    Figure 4 SQL Window integrado a Query Builder

    martes, 15 de julio de 2008

    PROCEDIMIENTOS Y FUNCIONES


    Delphi, es un lenguaje estructurado, lo cual indica que los programas escritos en este lenguaje, pueden descomponerse en pequeños módulos que pueden ser llamados cuando los necesitemos. Estos módulos en Pascal se llaman funciones y se identifican mediante un nombre. Se declaran del siguiente modo:



    function nombre (argumento1: tipo; argumento2: tipo;...) : tipo;
    Begin
    /Acciones a realizar/
    End;

    Donde nombre es el nombre que se asignará a la función, argumento1 y argumento2 son valores que pasan a la función y tipo es el tipo de valor que retornará como resultado. Por ejemplo, si queremos implementar en Pascal la función matemática: f(x, y) = (x * x + y) / x siendo x e y números enteros, se realizaría de este modo:

    Function f (x: integer; y: integer) : integer;
    Begin
    F = (x * x + y) / x;
    End;

    Dicha función, se definirá una sola ocasión durante el programa, y únicamente será necesario hacer llamada a esta función mediante su nombre y sus valores dados entre paréntesis.

    a := f(1, 2); {llamada a f con x=1 e y=2}
    b := f(a, 3); {llamada a f con x=a e y=3}
    c := f(a, b) + f(1, 4);

    Los valores colocados entre paréntesis de la función, reciben el nombre de argumentos. Estos se comportan dentro de la función, como si se tratase de variables.

    PROCEDIMIENTOS

    Toda función que no retorna valores ningún valor, o que no realiza operaciones matemáticas o genera resultados numéricos, recibe el nombre de procedimiento. La programación estructurada, se basa en dividirse en pequeñas partes autosuficientes que realizan una tarea muy concreta, y que pueden ser invocados cuando se desee. Se puede realizar alguna función o tarea especifica que arroje información de modo no numérico, o sin realizar operaciones, es entonces cuando se utilizan los procedimientos.

    Un procedimiento se declara del mismo modo que una función, a diferencia que la palabra reservada Function cambia por Procedure y al final de la lista de argumentos no se pone ningún tipo de valor de respuesta, pues no arroja ningún resultado. Ejemplo:

    Program Ejemplo2;
    Procedure Di (mensaje: String);
    Begin
    Showmessage(mensaje);
    End;
    Begin
    Di (‘Mi nombre es: ’);
    Di (‘David Osornio Fernández’);
    End;

    También es posible construir funciones o procedimientos que no tengas argumentos, pues pueden realizar una tarea concreta, no importando alguna otra cosa. Ejemplo:

    Program Ejemplo3;
    Procedure Saluda;
    Begin
    Showmessage(‘Hola a todos’);
    End;
    Procedure Nombre;
    Begin
    Showmessage(‘Mi nombre es David Osornio Fernández’);
    End;
    Procedure Despidete;
    Begin
    Showmessage(‘Adiós a todos’);
    End;
    Saluda;
    Nombre;
    Despidete;
    End;

    SELECCIÓN MULTIPLE


    Cuando se realiza un programa, es frecuente encontrarse con alguna variable que según su valor realizara alguna acción. Esto se podría realizar con muchos If´s anidados, pero resultaria algo enredado, por ejemplo: Si se desea que cuando a tenga el valor 1, c tome el valor 10, cuando a tenga el valor 2, c tome el valor 15, cuando a tenga el valor 3, c tome el valor 20 y cuando no sea alguno de los 3 valores, entonces que c tome el valor 0:



    If a = 1 then c := 10 Else

    If a = 2 then c := 15 Else

    If a = 3 then c := 20 Else

    c := 0;



    Esta forma de tomar decisiones resulta muy poco ortodoxa. El lenguaje Pascal nos ofrece para dicho propósito otra forma mas fácil de hacerlo. Mediante la palabra reservada case of. La sintaxis de dicha instrucción es la siguiente.



    case variable of

    valor1: acción1;

    valor2: acción2;

    ....

    Else acción N;

    End;



    Donde variable es el identificador de la variable que será comprobada y valor1, valor2... son los diferentes valores que puede tomar dicha variable. Si tomamos el problema anteriormente planteado, tendremos que la solución sería de este modo:



    case a of

    1: c := 10;

    2: c := 15;

    3: c := 20;

    Else c:= 0;

    End;