Os mostramos un curso de iniciación a la programación en Delphi. Este curso explica paso a paso, desde las sentencias del lenguaje Pascal en el que se basa hasta el IDE de desarrollo de Delphi y algunos programas de ejemplo. En este curso de Delphi explicamos el lenguaje Pascal, costantes, variables, tipos de datos, estructuras de control selectivas, estructuras de control repetitivas (for, while, repeat), procedimientos (procedure), funciones (function).
Conceptos básicos de programación
Fases para el desarrollo de una aplicación informática
- Análisis del problema: la primera fase de la resolución de un problema con un equipo
- informático es el análisis del problema. Esta fase requiere una clara definición, donde se contemple exactamente lo que debe hacer el programa y el resultado o solución deseada. Dependiendo de la aplicación a realizar, esta fase puede ser realizada por especialistas en la materia (técnicos de análisis).
- Diseño del algoritmo: en la etapa de análisis del proceso de programación se determina qué hace el programa. En la etapa de diseño se determina cómo hace el programa la tarea solicitada. La resolución de un problema complejo se realiza dividiendo el problema en subproblemas y a continuación dividiendo estos subproblemas en otros de nivel más bajo, hasta que pueda ser implementada una solución en el equipo informático. Este método se conoce técnicamente como diseño descendente (top-down) o modular. Hay diversos métodos para realizar este diseño (diagramas de flujo y pseudocódigos).
- Codificación de un programa: se trata de la escritura en un lenguaje de programación de la representación del algoritmo desarrollada en las etapas precedentes. Dado que el diseño de un algoritmo es independiente del lenguaje de programación utilizado para su implementación, el código puede ser escrito en cualquier lenguaje de programación. En esta fase de realizará también la documentación interna que es la que se incluye dentro del código fuente del programa, mediante comentarios que ayudan a entender el código.
- Compilación y ejecución: una vez que el algoritmo se ha convertido en un programa fuente, es preciso generar un fichero ejecutable (archivo de programa). El programa fuente debe ser traducido a lenguaje máquina. Este proceso se realiza con el compilador y el sistema operativo que se encarga prácticamente de la compilación. Si tras la compilación se presentan errores (errores de compilación) en el programa fuente, es preciso volver a editar el programa, corregir los errores u volver a compilar. Este proceso se repite hasta que no haya errores, obteniéndose el programa objeto, que todavía no es directamente ejecutable. Cuando no haya errores se debe instruir al sistema operativo para que realice la fase de montaje o enlace (link), carga, del programa objeto con las librerías del programa del compilador. En el proceso de montaje se genera un programa ejecutable. Cuando el programa ejecutable se ha creado, se puede ya ejecutar (correr o rodar) desde el sistema operativo, suponiendo que no existen errores durante la ejecución (errores en tiempo de ejecución).
- Verificación y depuración: en esta fase de verificación se comprobará que el programa funciona correctamente, introduciendo gran cantidad de datos de entrada y comprobando que el programa responde adecuadamente. Estos datos de entrada (datos de test o prueba) determinarán si el programa tiene errores («bugs»). Si el programa presenta bugs se depurarán, corrigiéndolos en el código fuente, volviendo a compilarlo y volviendo a generar el programa ejecutable.
- Documentación: en esta fase se realiza la descripción de los pasos a seguir para explicar el uso y funcionamiento del programa de cara a los usuarios finales.
Entorno de programación
Un entorno de programación es un programa que contiene, además del compilador (lenguaje de programación), utilidades y herramientas. Estos elementos están integrados, de modo que pueden llamarse fácilmente a cualquiera de los módulos, durante el proceso de programación, desde cualquier otro. Un entorno de programación típico contiene:
- Un editor, que proporciona el medio de introducir el texto y símbolos para crear el código fuente.
- Un intérprete o un compilador, que convierte el código fuente en instrucciones que la computadora puede comprender y ejecutar.
- Un verificador de errores en tiempo de ejecución, que reconoce todos los errores no detectados anteriormente en tiempo de compilación.
- Un depurador, que ayuda a analizar y corregir errores de sintaxis, estructura o lógicos.
Entorno integrado de desarrollo EID ó IDE (Integrated Development Environment)
El IDE es un entorno de programación que proporciona todas las herramientas que se necesitan para desarrollar programas de aplicación. En nuestro caso, para la realización del curso explicaremos el uso del entorno integrado de desarrollo (IDE) que incluye Borland (ahora CodeGear) Delphi.
El lenguaje Pascal
En primer lugar explicaremos el lenguaje Pascal pues Delphi está basado en éste. Con lo cual explicaremos la estructura de un programa en Pascal, así como el uso de funciones, procedimientos, bucles, condiciones, etc.
Un poco de historia
Pascal es un lenguaje de programación desarrollado por el profesor suizo Niklaus Wirth a finales de los años 60. Su objetivo era crear un lenguaje que facilitara el aprendizaje de la programación a sus alumnos. Sin embargo con el tiempo su utilización excedió el ámbito académico para convertirse en una herramienta para la creación de aplicaciones de todo tipo.
Pascal se caracteriza por ser un lenguaje de programación estructurado fuertemente tipificado. Esto implica que:
1. El código esta dividido en porciones fácilmente legibles llamadas funciones o procedimientos.
2. El tipo de dato de todas las variables debe ser declarado previamente para que su uso quede habilitado.
Estudiaremos en este tema las bases de Pascal, por tratarse del lenguaje de programación utilizado por Borland (hoy CodeGear) Delphi.
Estructura de un programa en Pascal
A continuación os mostramos la estructura de un programa en Pascal, pues es muy similar (casi igual) a la utilizada por Delphi en sus unidades. Para hacer las pruebas iniciales del lenguaje Pascal utilizaremos el famoso Turbo Pascal, un IDE de desarrollo de programas en Pascal realizado por Borland. Lo podéis descargar desde aquí.
La estructura de un programa en Pascal es la siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
program nombre_programa; uses identificadores; const definición de constantes; type declaración de tipos de datos definidos por el usuario; var declaración de variables; procedure ... (definición de procedimientos) function ... (definición de funciones) begin sentencias (cuerpo del programa); end. |
Abriendo Turbo Pascal (ejecutando el fichero TURBO.EXE) se nos abrirá una aplicación de MS-DOS, desde la que podremos hacer nuestro primer programa en Pascal, algo así:
1 2 3 4 5 |
program holaMundo; begin writeln ('Hola mundo'); end. |
El programa en Turbo Pascal:
Para compilar la aplicación y generar el fichero ejecutable pulsaremos en el menú «Compile» y luego en «Destination», de esta forma cambiaremos «Memory» por «Disk» para indicarle que genere el fichero de la aplicación:
Para generar el ejecutable pulsaremos el menú «Compile» y luego en «Make»:
En la carpeta donde tengamos el ejecutable de Turbo Pascal habrá creado un fichero llamado NONAME00.EXE que es el resultado de compilar y enlazar el código anterior:
Puesto que se trata de una aplicación MS-DOS, si queremos ver el resultado tendremos que abrir una consola de MS-DOS, desde «Inicio» – «Ejecutar», escribiremos «cmd» y pulsaremos «Aceptar», en la consola accederemos a la carpeta donde se encuentre Turbo Pascal, con el comando «cd ….»:
cd /ATP/Turbopascal
(asumiendo que Turbo Pascal está en la carpeta ATP y Turbopascal)
Para ejecutar la aplicación pondremos el nombre del ejecutable:
NONAME00.EXE
El resultado:
Hagamos una aplicación un poco más compleja, que pida el nombre y lo muestre por pantalla:
1 2 3 4 5 6 7 8 |
program miNombre; var nombre : string; begin write ('Introduce tu nombre: '); readln (nombre); writeln ('Tu nombre es ' + nombre); end. |
El resultado:
En texto:
NONAME00.EXE
Introduce tu nombre: Fernando Alonso
Tu nombre es Fernando Alonso
Para mostrar un ejemplo de cómo usar una función y un procedimiento realizaremos el siguiente cambio en el código anterior. Utilizaremos una función que será la encargada de pedir el nombre del usuario y devolverlo como cadena de texto y un procedimiento encargado de mostrar el texto al usuario y el resultado de la ejecución de la función anterior:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
program muestraNombre; function obtieneNombre : string var nombre : string; begin readln (nombre); obtieneNombre := nombre; end; procedure pideNombre; var nombre; begin write ('Introduce tu nombre: '); nombre := obtieneNombre; writeln ('Tu nombre es: ' + nombre); end; begin pideNombre; end. |
1 |
Constantes
Una constante es un valor que no puede cambiar durante la ejecución del programa, recibe un valor en el momento de la compilación del programa y este valor no puede ser modificado. Las contantes deben ser declaradas antes de su utilización y puede ser enteros o reales, caracteres o cadenas de caracteres, conjuntos o arrays e incluso de tipo enumerado.
Su definición:
1 2 |
const nombreConstante := valor; |
Por ejemplo:
1 2 |
const PrecioHora := 20; |
Variables
Las variables son objetos de un programa cuyo valor puede cambiar durante la ejecución del programa. El cambio se produce mediante sentencias ejecutables. Una variable es, en realidad, una posición de memoria con nombre. El nombre de la posición (un identificador) se llama nombre variable; el valor almacenado en la posición se llama valor de la variable.
Todas las variables de un programa Pascal deben ser declaradas antes de su uso.
Su declaración:
1 2 |
var nombreVariable : tipo_datos; |
Por ejemplo:
1 2 |
var numeroFactura : string; |
Operadores
Operadores lógicos:
Operador | Operación |
not | Negación binaria |
and | Y binario |
or | O binario |
xor | O exclusivo binario |
shl | Desplazamiento binario izquierda |
shr | Desplazamiento binario derecha |
Operadores de relación:
Operador | Operación |
< | Menor que |
> | Mayor que |
<= | Menor o igual que |
>= | Mayor o igual que |
Operadores aritméticos:
Operador | Operación |
+ | Suma |
– | Resta |
* | Multiplicación |
/ | División en punto flotante (real) |
div | División entera |
mod | Resto de división |
Operadores de comparación:
Operador | Operación |
= | Comparación |
<> | Distinto a |
Operadores de asignación:
Operador | Operación |
:= | Asignación |
Operadores de incremento y decremento:
Operador | Operación |
Inc() | Incremento |
Dec() | Decremento |
Tipos de datos
Mostraremos a continuación los tipos de datos más usuales de Delphi. No mostraremos los de Pascal, pues el curso es de Delphi.
Tipo de dato | Rango | Tamaño | |
Números enteros | Integer | –2147483648..2147483647 | 32 bits |
Cardinal | 0..4294967295 | 32 bits | |
Shortint | –128..127 | 8 bits | |
Smallint | –32768..32767 | 16 bits | |
Longint | –2147483648..2147483647 | 32 bits | |
Int64 | –2^63..2^63–1 | 64 bits | |
Byte | 0..255 | 8 bits | |
Word | 0..65535 | 16 bits | |
Longword | 0..4294967295 | 32 bits | |
Números reales | Real48 | 2.9 x 10^–39 .. 1.7 x 10^38 | 6 bits |
Single | 1.5 x 10^–45 .. 3.4 x 10^38 | 4 bits | |
Double | 5.0 x 10^–324 .. 1.7 x 10^308 | 8 bits | |
Extended | 3.6 x 10^–4951 .. 1.1 x 10^4932 | 10 bits | |
Comp | –2^63+1 .. 2^63 –1 | 8 bits | |
Currency | –922337203685477.5808.. 922337203685477.5807 | 8 bits | |
Real | 5.0 x 10^–324 .. 1.7 x 10^308 | 8 bits | |
Cadenas de caracteres | ShortString | 255 (se mantiene por compatibilidad hacia atrás con Delphi 1) | 2 to 256 bytes |
AnsiString | ~2^3 | De 4 bytes a 2GB | |
WideString | ~2^3 (similar a AnsiString pero compuesto por caracteres Unicode) | De 4 bytes a 2GB | |
PChar | Puntero a un string Char | ||
PAnsiChar | Puntero a un string AnsiChar | ||
String | Igual que AnsiString | De 4 bytes a 2GB | |
Caracteres | AnsiChar | Un carácter ANSI | 1 byte |
WideChar | Un carácter Unicode | 2 bytes | |
Char | Un carácter ANSI | 1 byte | |
Variant | OleVariant | ||
TVarData | 16 bytes | ||
Variant | |||
Lógicos | Boolean | 2 bytes | |
Definidos por el usuario | Array | ||
Pointer | |||
Set | |||
Record | |||
File |
Estructuras de control selectivas
Mediante estas estructuras se permite que una o varias instrucciones se ejecutarán sólo si se cumple una o varias condiciones lógicas:
1 2 3 4 |
if (expresión booleana) then sentencia1 else sentencia2; |
Por ejemplo:
1 2 3 4 5 6 7 |
if( numeroActual > 69) then begin numeroActual := numeroActual + 1; insertaFactura; end else cierraVentana; |
Para entender la sentencia if, crearemos un programa en Turbo Pascal que nos pedirá un número y nos dirá si es positivo o negativo:
1 |
program numeroPositivo;<br>uses Crt;<br>var<br> numero : real;<br>begin<br> ClrScr;<br> WriteLn ('Introduce un número: ');<br> Read (numero);<br> if (numero > 0) then<br> WriteLn ('El número introducido es positivo.')<br> else<br> WriteLn ('El número introducido es negativo.');<br> WriteLn ('Sentencia que se ejecutará siempre.');<br>end. |
Explicamos cada línea del programa:
- «program numeroPositivo»: incio del programa.
- «uses Crt;»: puesto que utilizaremos una función que limpia la pantalla MS-DOS perteneciente a la unidad Crt, es obligatorio indicarlo en la cláusula Uses.
- «var»: inicio de la declaración de variables.
- «numero : real;»: declaración de una variable de tipo «real».
- «begin»: inicio del cuerpo del programa.
- «ClrScr;»: procedimiento de la unidad Crt que limpia el contenido de una ventana MS-DOS.
- «WriteLn (‘Introduce un número: ‘);»: muestra el texto en pantalla «Introduce un número:».
- «Read (numero);»: para la ejecución del programa hasta que el usuario introduzca un valor y pulse Intro, guarda el valor introducido en la variable «numero».
- «if (numero > 0) then»: estructura de control selectiva, si el número introducido es mayor que cero se ejecutará la sentencia que contiene, sino se ejecutará la que hay en el «else».
- «WriteLn (‘El número introducido es positivo.’)»: lo que muestra si se cumple la condición del «if…».
- «else»: inicio de las sentencias que se ejcutarán si la condición del «if….» no se cumple.
- «WriteLn (‘El número introducido es negativo.’)»: sentencia que se ejecutará si no se cumple la condición lógica del «if….».
- «WriteLn (‘Sentencia que se ejecutará siempre.’);»: sentencia que muestra el texto «Sentencia que se ejecutará siempre.», esta sentencia, al estar fuera del if y del else siempre se ejecutará.
- «end.»: indica el final del programa.
Estructuras de control repetitivas
For
Estructura de control que permite la repetición de una serie determinada de sentencias.
Con incremento de «valor_inicial»:
1 2 |
for valor_inicial to valor_final do sentencia; |
O bien con decremento de «valor_inicial»::
1 2 |
for valor_inicial downto valor_final do sentencia; |
Un ejemplo:
1 2 3 4 5 6 7 8 9 10 11 |
var i : integer; begin for i := 1 to 1000 do begin if i > 500 then break; WriteLn ('Se ejecutará siempre que i no sea mayor de 500.'); end; WriteLn ('Siempre se ejecuta.'); end. |
Hemos utilizado «break» para salir de un bucle «for» si de produce una condición dada (que «i» sea mayor que 500).
While
En esta estructura repetitiva el número de iteraciones no se conoce por anticipado (como en el caso del for), en este caso el cuerpo del bucle se repite mientras se cumple una determinada condición.
1 2 |
while condición do sentencia; |
Un ejemplo del uso de «While», haremos un programa que pedirá un número e indicará si es primo o no:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
program numeroPrimo; var primo : boolean; numero, divisor : integer; begin primo := true; divisor := 2; WriteLn ('Introduzca un número: '); ReadLn (numero); while ((divisor < numero) and primo) do begin if (numero mod divisor = 0) then primo := false; divisor := divisor + 1; end; if primo = true then WriteLn (numero, ' es primo.') else WriteLn (numero, ' no es primo.'); end. |
Repeat
Repeat es una variante de la sentencia While. En la sentencia While la condición se evalúa al principio de cada iteración mientras que en la sentencia Repeat la condición se evalúa al final de cada iteración. En un Repeat, la iteración se ejecutará al menos una vez.
1 2 3 4 |
Repeat sentencia; until condición; |
Un ejemplo del uso de «Repeat», haremos un programa que sumará tantos números como indique el usuario:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
program sumaNumeros; var suma : integer; numero : integer; contador : integer; totalNumeros : integer; begin contador := 0; WriteLn ('Introduzca cuantos números quieres sumar: '); ReadLn (totalNumeros); suma := 0; if (totalNumeros > 0) then begin Repeat Write ('Introduzca un número: '); Read (numero); suma := suma + numero; inc(contador); until contador = totalNumeros; WriteLn ('Suman: ', suma); end else WriteLn ('No ha indicado cuántos números sumar.'); end. |
Procedimientos
Un procedimiento es un subprograma que realiza una tarea específica. Puede recibir cero o más valores del programa que llama y devolver cero o más valores a dicho programa llamador. Un procedimiento está compuesto de un grupo de sentencias a las que se le asigna un nombre (nombre del procedimiento o identificador).
Declaración de un procedimiento:
1 2 3 4 5 |
procedure nombre_procedimiento (parámetro1 : tipo_dato; var parámetro_devuelto1 : tipo:dato); begin sentencias del procedimiento; end; |
Por ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 |
procedure muestraAsteriscos (numeroAsteriscos : integer); var i : integer; begin for i := 0 to numeroAsteriscos - 1 do Write ('*'); end; Ejemplo de llamada: ... muestraAsteriscos (25); |
(en este ejemplo el procedimiento no devuelve nada).
Otro ejemplo donde el procedimiento devuelve algún valor:
1 2 3 4 5 |
procedure calculaAreaRectangulo (longitud, anchura : real; var area : real); begin area := longitud * anchura; end; |
Ejemplo de llamada:
1 2 3 4 5 6 7 8 9 |
... var area : real; begin calcularAreaRectangulo (100, 25, area); WriteLn ('El área del rectángulo es: ', area); ... |
Funciones
Una función es igual a un procedimiento pero siempre ha de devolver un valor:
Declaración de una función:
1 2 3 4 5 |
function nombre_función (parámetro1 : tipo_dato) : tipo_dato_devuelto; begin sentencias del procedimiento; result := valor_Devuelto; end; |
Para que la función devuelva el valor se le puede indicar mediante «result» o asignando el valor al propio nombre de la función:
1 2 3 4 5 |
function nombre_función (parámetro1 : tipo_dato) : tipo_dato_devuelto; begin sentencias del procedimiento; nombre_funcion := valor_Devuelto; end; |