viernes, 28 de marzo de 2008

Lenguaje Turbo Pascal


CLASE 7: Lenguaje Turbo Pascal.
Estructura de un programa en Turbo Pascal
El lenguaje Pascal fue creado en la década del 70 por Niklaus Wirth de Zurich, partiendo de otros lenguajes previamente desarrollados, como el Algol y el Fortran. El Pascal fue desarrollado como un lenguaje de propósito general, orientado hacia fines pedagógicos de nivel universitario y para los estudiantes en la carrera de Sistemas. Desde sus origenes fue concebido como un lenguaje con las herramientas necesarias para facilitar la programación estructurada, ya que reúne las estructuras de control de programa de: la sentencia compuesta –concatenación, bloque-, la estructura condicional –selección- y la cíclica –repetición, iteración-. Permite la programación modular, ya que, otorga la posibilidad de crear módulos –procedimientos y funciones-, logrando dividir un problema en partes menos complejas, partiendo de lo general a lo particular, a su vez, cada una de estas partes puede volver a dividirse, esta tarea se conoce como refinamiento sucesivo. También es un lenguaje fuertemente tipado, es decir, ante la menor incompatibilidad de tipos generará un error. Es un lenguaje proceduralimperativo, orientado a órdenes-. Existen ciertas diferencias entre el Pascal standard con el Turbo Pascal, este último incorpora notables diferencias para beneficio al programador, por lo tanto, de aquí en adelante al hablar del Pascal estaremos refiriéndonos al Turbo Pascal de Borland, versión 5 en adelante.
Entre las ventajas adicionales que encontramos están las unidades, herramientas para la programación orientada a objetos, gráficos, etc..
Los lenguajes de programación se clasifican en:
  • Lenguaje máquina: escritos a nivel de bits, hace que sea una tarea bastante tediosa al programador aunque directamente reconocible por la computadora –cpu-.
  • Lenguajes de bajo nivel:ensambladores-: En lugar de escribir las ordenes impartidas a la máquina con ceros y unos, se utiliza un lenguaje simbólico, que establece una relación 1 a 1, por lo tanto es extraordinariamente rápida su ejecución, la desventaja es que estos lenguajes están muy comprometidos con la máquina en donde deban ser ejecutados, por lo tanto no son transportables prácticamente a otros equipos, esto hace entonces que cada hardware diferente cuente con un código especialmente escrito para cada equipo. Los lenguajes de bajo nivel, las instrucciones se escriben en códigos alfabéticos conocidos como mnemotécnicos, p.e.:
Cód. Código
Máq. Mnemotécnico

0010 ADD
0001 LOAD
0100 STG

Luego de escribir un programa en lenguaje assembler, se necesita de un programa ensamblador que lo traduzca a código máquina.

  • Lenguajes de medio nivel: Son lenguajes que se encuentran en un paso intermedio entre los lenguajes de bajo nivel y los lenguajes de alto nivel. Los lenguajes de bajo nivel se encuentran más cerca de la máquina que del programador, en cambio los lenguajes de alto nivel son más cercanos al programador que a la máquina. Los lenguajes de nivel medio por lo tanto están en un punto intermedio entre la máquina y el programador. El lenguaje C es considerado como un lenguaje de nivel medio, ya que posibilita escribir el código de diferentes maneras, el que se elija hará que esté más cerca de la máquina o del programador o inclusive en un punto medio, entre estos dos, p.e.: c = c + 1 o c += 1 o c++, son distintas maneras de hacer lo mismo, aunque el código máquina que genere no sea el mismo, esto determinará que algunas de estar órdenes al traducirse a código máquina sea más óptima que otras, es decir, se ejecutrá más rápidamente.
  • Lenguajes de alto nivel: Aquí encontramos muchos de los lenguajes de programación, p.e.: Pascal, Basic, Cobol, Fortran, Algol, Ada, Modula, etc. Esta categoría de lenguajes hace que se encuentren más cercanos al programador que de la máquina. Esto significa que al alejarse más de la máquina requerirá de mayor tiempo de ejecución, pero serán más fáciles de escribir por utilizar palabras similares al lenguaje natural. Los programas escritos en un lenguaje de alto nivel son transportables, es decir, se pueden ejecutar en distintas máquinas, ya que no son tan dependientes del hardware. El código escrito debe ser traducido al lenguaje de máquina y para llevar a cabo esta tarea se utilizan los compiladores o bien los intérpretes.
Etapas para la generación de código máquina
  1. Edición del programa, utilizando la consola –teclado, pantalla-, a través de un editor de texto o que genere código ASCII puro, una vez finalizado se graba en disco con un nombre elegido por el programador y de una extensión que dependerá del lenguaje que hayamos seleccionado para escribir nuestro programa, p.e.: Pascal .Pas, Basic .Bas, C .c, Cobol .Cob o .Cbl, dBase o Clipper o Fox .prg, etc.. Este programa recibe el nombre de programa fuente y es muy importante conservarlo, debido a que en caso de necesitar realizar modificaciones, se realizará con el código fuente.
  2. Compilar el programa fuente, -etapa anterior-, utilizando el compilador correspondiente al lenguaje empleado, por lo tanto, el compilador tiene una entrada que es el lenguaje fuente, p.e.:

    Tp MiProg Tp, Compilador Turbo Pascal de Borland
    Tc MiProg Tc, Compilador Turbo C de Borland
    Cobol MiProg Cobol, Compilador Cobol.

    El archivo generado recibe el nombre de programa objeto y tiene como extensión .obj, -object-. Este programa contiene la traducción del programa fuente, es decir, su código es el de máquina, pero aún no podrá ser ejecutado debido a que habrá que enlazarle las librerías a que hace referencia.
  3. Vincular el programa objeto –resultado de la etapa de compilación-, utilizando la aplicación que contiene las librerías que requiera el programa objeto, generalmente con el nombre de Link o similar, p.e.:

    Link MiProg
    Blink MiProg
    Tlink MiProg
Generalmente podrán incorporarse cuantos módulos .obj necesitemos para general un solo programa que ahora sí contendrán los códigos de las librerías que requería el .obj. El resultado del enlzador es un programa ejecutable cuya extención es .exe, p.e.: MiProg.exe, y es este programa autosuficiente de ser ejecutado.


Un programa en T.Pascal consta de las siguientes partes:

Una cabecera, precedida por una palabra reservada y un identificador, a saber:

Program IdProg;
IdProg tiene como propósito identificar con un nombre apropiado el sentido del programa, es decir, cuál es el proceso que lleva a cabo.

Un área de definiciones y declaraciones de objetos diversos, cada una representada por medio de una palabra reservada, que establece una sección, en el cuál existe una cierta libertad para el orden, salvo que obligatoriamente debamos escribir alguna sección antes de otra, por motivos de que un identificador antes de poder utilizarlo debe estar previamente definido. Las secciones son las siguientes:

uses
{lista de Id.de unidades}
const
{lista de Id. constantes}
type
{lista de tipos}
procedure
{Módulo procedimiento}
function
{Módulo función}
var {Ubicadas en el Segmento de Datos}
{lista de variables globales}

y un bloque principal, encerrado entre las palabras reservadas:

begin
sentencia1;
sentencia2;
.
sentencian
end.

Una palabra reservada en T.Pascal cumple un propósito específico, por lo tanto nunca debe ser utilizada para que cumpla otro rol. Las palabras que aparecen en negrita en el esquema anterior son palabras reservadas.
Un identificador es una palabra creada por el usuario y sirve para definir nombres de unidades, constantes con nombres, tipos, campos de registros, nombres de procedimientos, funciones y variables.Un identificador jamás puede ser una palabra reservada, por lo dicho en el apartado anterior.

En la sección uses definimos las unidades que se van a incorporar a nuestro programa. Una unidad es un conjunto de objetos previamente compilados y cuyo código se agrega al código de nuestro programa, solo el programa principal y sus módulos desarrollados deberán ser compilados. Una unidad compilada tiene extensión .TPU, mientras que el archivo de código fuente tiene la misma extensión que el programa .Pas. Los objetos que componen una unidad son los mismos objetos vistos en el esquema previo, vale decir, otras unidades, constantes con nombre, tipos, procedimientos, funciones y variables.



Unidades predefinidas

El lenguaje T.Pascal proporciona al usuario de unidades las cuales están almacenadas en el archivo TURBO.TPL algunas de las cuales son:

CRT, que reúne un conjunto de objetos para la facilidad del teclado y pantalla, entre estos objetos tenemos los siguientes identificadores de procedimiento o funciones:


gotoxy(x,y) que sirve para ubicar al cursor en las coordenadas x,y siendo (1,1) el ángulo superior izquierdo; (1,80) el ángulo superior derecho; (1,25) el ángulo inferior izquierdo y (80,25) el ángulo inferior derecho.

delay(n) realiza una espera de n milisegundos.

clrscr limpia la pantalla y ubica al cursor en el ángulo superior izquierdo, es decir en las coordenadas (1,1).

clreol limpia una linea pero desde la columna en donde se encuentre el cursor –puntero de la pantalla- hasta el final de la línea, y dejando al cursor posicionado en la fila y columna en que se encontraba previo a limpiar la línea.

keypressed función que realiza una espera hasta que se oprima una tecla, es necesario encerrarla dentro de una estructura cíclica, ya que retorna un valor de tipo boolean.

textcolor(n) cambia el color del carácter, n es un valor entre 0 y 15.

textbackground(n) cambia el color del fondo del cracter, n es un valor entre 0 y 7.

readkey función que lee desde el buffer del teclado un valor, si el buffer está vacío espera a que se presione una tecla, no es necesario terminar con la tecla ENTER.

window(x1,y1,x2,y2) crea una ventana, todo aquello que se emita será enviado a esta ventana, la ventana máxima es window(1,1,80,25).

sound(n) emite un sonido, por el speaker, n indica un valor de frecuencia.

nosound hace que deje de emitirse sonido, se utiliza para deterner a sound.

En lugar de utilizar valores entre 0 y 15 para indicar el color se podrán utilizar las constantes con nombres definidas en esta unidad, p.e.: blue, red, green, white, yellow, black, lightred, etc..

PRINTER brinda una variable lst de tipo archivo text que permite enviar la salida hacia la impresora, además da facilidades para su manejo ya que no es necesario ni abrir ni cerrar ese dispositivo, debido a que lo gestiona la unidad.

DOS otorga un conjunto de objetos de servicios al sistema operativo D.O.S., entre estos objetos se encuentran los procedimientos:
getdate(aa,mm,dd,ds) que obtiene la fecha del sistema, cada parámetro es de tipo word y ds indica el día de la semana, 0 para domingo, 1 para lunes, ..., 6 para sábado.
gettime(hh,mm,ss,cs) que obtiene la hora del sistema, cada parámetro es de tipo word y cs indica centésimas de segundo.

SYSTEM esta unidad siempre estará disponible en nuestros programas y jamás deberá anunciarse en la sección uses, si se hiciera se colgaría el programa. Aquí se encuentran muchos de los objetos que utilizamos en un programa, p.e.: las funciones numéricas, las funciones de cadenas, las sentencias de asignación externas de entrada y salida, es decir, los procedimientos read, readln, write, writeln que veremos más adelante, como todas las sentencias y funciones para manejo de archivos y asignación de memoria.

Unidades definidas por el usuario

T.Pascal también permite que el usuario desarrolle sus propias unidades; para hacerlo debemos conocer como es su estructura. Una unidad se compone de las siguientes partes:

Unit IdUnidad;
interface {Parte pública o visible a otras unidades o programas
que utilicen esta unidad}
uses
const
type
procedure {solo la cabecera}
function {solo la cabecera}
var

implementation {Parte privada}
uses
const
type

procedure {se desarrolla completamente}
{los procedimientos que no aparecen en la sección de interface no serán reconocidos por los programas que enlacen la unidad, solo serán reconocidos por la unidad, es decir son locales y solo serán reconocidos por otras unidades si están definidas dentro de su ámbito}
function {se desarrolla completamente}
{las funciones que no aparecen en la sección de interface no serán reconocidos por los programas que enlacen la unidad, solo serán reconocidos por la unidad, es decir son locales y solo serán reconocidos por otras unidades si están definidas dentro de su ámbito}
var

begin
{Inicializar la unidad}
sentencias
end.

El nombre que identifica a la unidad debe ser el mismo nombre que demos al archivo. El archivo fuente tiene extensión .Pas y el archivo compilado tiene extensión .Tpu, es decir, Unidad Turbo Pascal. Las unidades se compilan en forma independiente de los programas, por lo tanto, cuando un programa requiere los servicios de una unidad solo se la menciona en la sección uses, enlazando su código al programa.
Las unidades son llamadas también librerías, y los objetos que incluimos deben ser de un tema específico. Por último diremos que las unidades son módulos que acentúan la programación modular y permiten la construcción de grandes programas.

En la sección const definimos constantes con nombres y es de uso global en el programa. En vez de utilizar valores constantes en nuestro programa, en ciertas situaciones es conveniente utilizar este tipo de objetos, que por diversas razones lo hace más legible y dinámico a la hora de modificar el programa, p.e. en vez de utilizar la constante 21 del IVA, podríamos definir una constante con nombre denominada IVA y hacerla igual al valor 21, luego en los distintos puntos del programa en donde dicho valor podría aparecer, pondríamos este identificador. Si a futuro debemos realizar un cambio de valor solo iremos al único lugar en donde podemos modificarlo. Por conveniencia utilizamos nombres escrito todo en mayúscula a efectos de darnos cuenta en el momento de leer un listado fuente de que esos identificadores son objetos constantes y no variables. El único lugar en donde podemos cambiar el valor de una constante con nombre es en la sección const. La sintaxis es:

const
IdConst = expresión;

Ejemplos:

const
IVA = 21;
MIN = 12;
MAX = MIN * 2 –1;
VAL_ABS = abs(-MAX);
COC = MAX div MIN;
RES = MAX mod MIN;
CAD = ‘esto es una cadena de caracteres’;
LONG = length(cad);
C = #67;
VERDADERO = true;
ENT = trunc(23.74);
CODASCCI = ord(‘A’);

En la sección type definimos nuevos tipos de datos y es de uso global en el programa. La sintaxis es:

type
IdTipo = tipo;

IdTipo es un identificador válido.
tipo es un identificador o tipo simple o tipo estructurado o tipo string o tipo pointer.

El lenguaje Pascal es fuertemente tipado -strongly typed-, esto quiere decir que todas las variables deben estar previamente definidas correspondiendo a un tipo de dato al que pertenecen. Otra clase de lenguajes que verifican el tipo de variables según el valor que se le asigne por primera vez se denominan auto tipadosself typed- mientras que otros lenguajes podrían permitir que una variable tome valores de distinto tipo durante la ejecución del programa, en este caso se denomina dinámicamente tipadosdinamically typed-.
Definir a una variable como perteneciente a un tipo de dato, circunscribe al conjunto de valores que puede tener y las operaciones que pueden realizarse.

Los tipos en Pascal se clasifican en:

Tipos simples
Ordinalespredefinidos-
Integer
ShortInt
LongInt
Byte
Word
Char
Boolean
Ordinales -definidos por el usuario-
Enumerado
Intervalo
Reales
Real
Single
double
extended
comp
Tipos String –cadena de caracteres-
String
String[n]
Tipos estructurados
Record
File
Set
Array

Tipos punteros
Pointer
^IdTipoBase
Tipos Procedurales
Procedure...
Function...

Ejemplos:

type
int = integer;
str20 = string[20];
Fecha = record
aa : word;
dd,
mm : byte
end;
RegAlu = record
NroLeg : longint;
ApeNom,
Domic,
Local : str20;
FecNac : Fecha;
EstCiv : char
end; Meses = 1..12;
MesesStr = (Enero, Febrero, Marzo, Abril, Mayo, Junio, Julio, Agosto, Septiembre,
Octubre, Noviembre, Diciembre);
PriSem = Enero..Junio;
SegSem = Julio..Diciembre;

Meses es de tipo [1; 12]. MesesStr es de tipo por enumeración siendo los nombres de los meses constantes y únicos, es decir, no puede volver a definirse para otro tipo, los valores ordinales son Enero = 0, Febrero = 1, ... PriSem es de tipo [Enero; Junio].
Sobre los tipos ordinales se pueden aplicar las funciones : ord, pred y succ. p.e.: ord(Marzo) = 2, Succ(Mayo) = Junio, Pred(Octubre) = Septiembre, ord(false) = 0.

Las variables son objetos a los que se les pueden asignar valores del mismo tipo en que han sido definidas. La sintaxis es:

var
Lista-IdVar : tipo;

Lista_IdVar es una lista de identificadores válidos separados por comas.

Aquellas variables definidas fuera del ámbito de un módulo son variables globales. Estas variables son estáticas, debido a que el espacio que ocupen en la memoria estará definido en tiempo de compilación y no se libera hasta que finalice la ejecución del programa. Las variables globales se localizan en el segmento de datos, que es una región de memoria hasta un máximo de 64Kbytes, en caso de necesitar más espacio, se puede recurrir a un diseño modular, esto hace que aquellas variables que sean propias del módulo ocupen lugar en otra region de memoria que es el segmento del stack o pila, las variables definidas dentro del ámbito de un módulo se denominan variables locales y existen mientras el control de ejecución del programa esté cedido al módulo, vale decir estas variables como así también los parámetros, se crean cuando se llama o invoca al módulo y son eliminadas cuando se regresa el control al punto desde donde se invocó. Por otro lado si aún fuera necesario incrementar el espacio para variables se podrá utilizar otra región de memoria al área del heap o montículo, en donde el límite es el resto de la memoria disponible. Pero a diferencia de las variables globales, estas variables ubicadas en el heap se denominan variables dinámicas y se crean o eliminan en tiempo de ejecución, por medio de los procedimientos definidos por Pascal new y dispose respectivamente. Para poder acceder a estas localizaciones es necesario recurrir a las variables de tipo puntero, es decir, variables que contienen una dirección de memoria.
Ejemplos:
var
a, b, c : real;
i, j : integer;
cad20 : str20; {str20 es un identificador que debió definirse en la sección type}
car : char;
rAlumno : RegAlu {RegAlu debe estar definido previamente en la sección type}
existe : boolean;
NroLeg : longint;
cant, kg : word;

Los procedimientos son módulos que deben ser invocados para que su código pueda ser ejecutado, ya que, si no se lo invocan están como en un estado de hibernación. La comunicación entre la llamada y el módulo se logra por medio de los parámetros. En el punto de la llamada se denominan parámetros actuales, mientras que en la cabecera del módulo se denominan parámetros formales. Un procedimiento está estructurado en las siguientes partes:
Una cabecera que incluye:
La palabra reservada procedure
El identificador de procedimiento
Una lista de parámetros, que podrán ser pasados por valor o por referencia; en este último caso deberá estar precedido con la palabra reservada var.
Un área de definiciones y declaraciones de objetos locales.
Un cuerpo encerradas entre las palabras reservadas begin y end.
procedure IdProc(lista de parámetros);
var {Locales}

begin
sentencia; ...
end;
lista de parámetros es: Identificador, ... : tipo o var Identificador, ... : tipo

Si el parámetro no está precedido por la palabra reservada var, entonces el parámetro es pasado por valor, esto es, con el valor pasado se hace una copia en otra región de memoria y cualquier cambio que se hiciere, en realidad no afectará al parámetro actual, por estar trabajando con la copia, y no con el valor original. Este tipo de pasaje de parámetros es utilizado cuando el valor se conoce antes de invocar al módulo y deseamos pasar el valor al módulo para que realice algún proceso. Los parámetros pasados por valor son parámetros de entrada y sirve para inicializar al parámetro formal. El objeto que ocupa la misma posición, el parámetro actual, puede ser una expresión, es decir, puede ser una constante, una variable o una expresión propiamente dicha, p.e.:

Si el parámetro está precedido por la palabra reservada var, entonces el parámetro es pasado por referencia, esto es, se pasa la dirección del objeto, por lo tanto, este objeto, del parámetro actual, solo debe ser una variable. El parámetro formal recibe la dirección, y al momento en que se le asigne un valor dentro del módulo al parámetro formal, en realidad se lo está asignando al parámetro actual, a través del parámetro formal. Imaginemos que este parámetro formal es una catapulta que envía lo que recibe a un único punto, al punto al que apunta, es decir en donde está ubicada la variable –el parámetro actual-, cuya dirección es la que recibió el parámetro formal. Este tipo de pasaje de parámetros es utilizado cuando conocemos el valor dentro del módulo y queremos dárselo al bloque que lo llamó a través de su parámetro actual o bien conociendo previamente su valor, dentro del módulo invocado quizás sufra alguna modificación y queremos informarlo al bloque que invocó al módulo, por medio de su parámetro actual. Este tipo de parámetros pasados por referencia son parámetros de salida o bien de entrada-salida.
Las funciones son módulos que deben ser invocados para que su código pueda ser ejecutado, ya que, si no se invocan están como en un estado de hibernación. La comunicación entre la llamada y el módulo se logra por medio de los parámetros. En el punto de la llamada se denominan parámetros actuales, mientras que en la cabecera del módulo se denominan parámetros formales.

Una función está estructurada en las siguientes partes:

Una cabecera que incluye:
La palabra reservada function
El identificador de la función.
Una lista de parámetros, que podrán ser pasados por valor, es lo más habitual o por referencia; en este último caso deberá estar precedido con la palabra reservada var.
El tipo de dato simple que retornará la función.
Un área de definiciones y declaraciones de objetos locales.
Un cuerpo encerradas entre las palabras reservadas begin y end, el cual deberá tener al menos una sentencia de asignación y que asigne al nombre de la función el resultado de una expresión que deberá coincidir con el tipo en que fue definida en su cabecera.


function IdFunc(lista de parámetros) : tipo;
var {Locales}

begin
sentencia; ...
IdFunc <-- expresión end;

lista de parámetros es: Identificador, ... : tipo o var Identificador, ... : tipo

Si el parámetro no está precedido por la palabra reservada var, entonces el parámetro es pasado por valor, esto es, con el valor pasado se hace una copia en otra región de memoria y cualquier cambio que se hiciere, en realidad no afectará al parámetro actual, por estar trabajando con la copia, y no con el valor original. Este tipo de pasaje de parámetros es utilizado cuando el valor se conoce antes de invocar al módulo y deseamos pasar el valor al módulo para que realice algún proceso. Los parámetros pasados por valor son parámetros de entrada y sirve para inicializar al parámetro formal. El objeto que ocupa la misma posición, el parámetro actual, puede ser una expresión, es decir, puede ser una constante, una variable o una expresión propiamente dicha.

Si el parámetro está precedido por la palabra reservada var, entonces el parámetro es pasado por referencia, esto es, se pasa la dirección del objeto, por lo tanto, este objeto, del parámetro actual, solo debe ser una variable. El parámetro formal recibe la dirección, y al momento en que se le asigne un valor dentro del módulo al parámetro formal, en realidad se lo está asignando al parámetro actual, a través del parámetro formal. Imaginemos que este parámetro formal es una catapulta que envía lo que recibe a un único punto, al punto al que apunta, es decir en donde está ubicada la variable –el parámetro actual-, cuya dirección es la que recibió el parámetro formal. Este tipo de pasaje de parámetros es utilizado cuando conocemos el valor dentro del módulo y queremos dárselo al bloque que lo llamó a través de su parámetro actual o bien conociendo previamente su valor, dentro del módulo invocado quizás sufra alguna modificación y queremos informarlo al bloque que invocó al módulo, por medio de su parámetro actual. Este tipo de parámetros pasados por referencia son parámetros de salida o bien de entrada-salida.
La sentencia de asignación
Presenta el siguiente formato:
variable := expresión

Bloque del diagrama de flujo
variable <-- expresión

Permite asignar valores a las variables. El lado izquierdo del símbolo := es el objeto que recibe el valor, y debe ser solamente una variable. El lado derecho del mismo símbolo indicado anteriormente, es una expresión y una vez calculado su valor es asignado a la variable que está del lado izquierdo, el cual debe coincidir su tipo con el que ha sido definida la variable, pues en caso de que no coincida, se dará un mensaje de error. La excepción está cuando la variable es de tipo real y la expresión genere un resultado de tipo entero.
Ejemplos:

a := 3;
letra := ‘A’;
mes := Enero;
mesStr := ‘Enero’;
mesPos := ord(Enero);
c := 2; x := 30;
EsMayor := (x > y) and (‘A’ > ‘@’);
c := c + 5;
ApeNom := rAlumno.ApeNom;
existe := false;
precio := 281.94;
y := k + sqrt(sqr(a) + sin(x * pi / 180));
La asignación externa de entrada
Presenta el siguiente formato:

var, ...read(var,...)
readln(var,...)

Bloque del diagrama de flujo
Espera a que se ingrese un valor, siendo el dispositivo por defecto el teclado, por lo tanto, una vez tipeado el valor y luego de oprimir la tecla ENTER, el valor es asignado a la variable que aparece como parámetro del procedimiento read o readln, luego de esto la ejecución continúa su rumbo. Debe existir una correspondencia de tipos entre el valor ingresado y la definición del parámetro en el procedimiento read o readln, ya que si no se corresponden sus tipos ocacionará en un error de compilación. Si bien se aceptan escribir más de una variable, es conveniente escribir una sola y usar readln, para evitar ciertos fenómenos no deseados. Las cadenas y caracteres se ingresan sin encerrarlas entre apóstrofos.

Ejemplos:

readln(NroLeg);
readln(rAlumno.ApeNom);
readln(rAlumno.FecNac.dd);

La asignación externa de salida

Presenta el siguiente formato:
exp, ...
write(exp, ...)
writeln(exp, ...)

Bloque del diagrama de flujo
Espera a que se emita el valor, siendo el dispositivo por defecto la pantalla, por lo tanto, una vez que se haya emitido luego de esto la ejecución continúa su rumbo. Si la exp es una constante entonces el valor emitido es la propia constante, si exp es una variable entonces se emite su contenido y por último si exp es una expresión propiamente dicha entonces el resultado de evaluar la expresión es lo que se emite. Se puede dar formato a la salida de los valores enteros, escribiendo; writeln(valEnt:m) o write(valEnt:m), en donde m indica la longitud a reservar, p.e.: writeln(mes:2,’-‘,aa:4) en cambio con valores reales la forma es, writeln(valReal:m:n), en donde m indica el espacio a reservar y n la cantidad de dígitos decimales que se van a emitir, la longitud m incluye el punto decimal, p.e. writeln(‘$ ‘,imp:8:2), después de emitir el signo $ seguido de un espacio reserva 8 lugares para emitir el valor, compuesto por 5 dígitos enteros un punto decimal y dos dígitos decimales, si el número tuviera menos dígitos enteros entonces rellena con blancos a izquierda de la parte entera del número y con dígitos ceros a derecha en la parte decimal del número. En cambio, si el número necesita de más espacio igual se emite, pero ya no podrá quedar alineado con respecto a los valores emitidos en esa misma posición, es decir, quedarán corridos o desalineados. También se pueden emitir las cadenas con el siguiente formato, write(cad:m) o writeln(cad:m), si la cadena tiene menos caracteres que m, entonces primero se emiten espacios en blanco y después la cadena, por lo tanto, la alineación se efectúa a derecha. Para realizar un tabulado horizontal, se realiza de esta forma, write(‘ ‘:m), emitiendo m espacios en blanco, p.e. si queremos emitir una cadena y a continuación otro valor pero a partir de una misma posición , hacemos, write(Descrip,’ ‘:22-length(cad),precio:8:2).Ejemplos:
write( ‘Apellido y Nombre: ‘,ApeNom);
writeln(‘Pre.unit.: ‘,PreUni:8:2,’ Cantidad: ‘,cant:5,’ Total: ‘,cant*PreUni:10:2);
writeln(‘[a; b] = [‘,a,’; ‘,b,’]’);
Estructuras de Control de programas

La sentencia compuesta BEGIN END

La sentencia compuesta establece que sus componentes que son sentencias, se ejecuten en el orden en que han sido escritas. Estas sentencias son consideradas como si fueran una sola sentencia; este concepto es vital para aquellos casos en que el ámbito de una estructura de control es una sola sentencia. Las palabras reservadas begin y end encierran las sentencias dentro de la sentencia compuesta y van separadas por punto y coma, antes de un end no es obligatorio su uso, si se escribe entonces la sentencia a ejecutar será la sentencia vacía. La sintaxis es:

begin {Bloque}
x := 5;
ObtDatos(rAlumno);
writeln(‘Localidad: ‘,rAlumno.Local);
writeln(‘x: ‘,x:4)
end.

Sentencias condicionales

Las sentencias condicionales son las que posibilitan una ruptura en la secuencia de ejecución de las sentencias, posibilitando cambiar de rumbo, es decir, poder seleccionar que acciones ejecutar si se cumple o no una condición. A continuación se presentan las variantes de este tipo de sentencias condicionales:
La sentencia condicional simple IF
Es la sentencia más habitualmente empleada para realizar bifurcaciones o ramificaciones, ya que, con este tipo de sentencia condicional permite efectuar la más variada forma de uso para estos casos. La sintaxis es:

La expresión debe generar un resultado de tipo boolean. Si la expresión produce un resultado verdadero –true-, entonces se ejecuta la sentencia que sigue a then. Si la expresión produce un resultado de falso –false-, entonces se ejecuta la sentencia que sigue a else. Si la parte else no está presente entonces nada se ejecuta.
Si una sentencia condicional if no tiene la parte else decimos que es una selección simple incompleta y si está presente es una selección simple completa. Un else se corresponde con el último if abierto, este concepto es muy importante debido a que en los casos de if’s anidados, podemos tener una situación de un if completo y dentro de este un if incompleto, ¿a que if le corresponde, entonces el único else?. Evidentemente al if interno, por lo tanto nuestra lógica estaría mal representada. La solución a estos casos obliga a usar un bloque de concatenación, encerrando al if interno, por lo cual la partícula else ahora se referirá al if externo, como era de esperar en nuestra lógica.

La sentencia condicional múltiple CASE

Una opción a la sentencia condicional simple es la sentencia condicional múltiple. Esta sentencia permite bifurcar por más ramas o caminos, pero presenta ciertas limitaciones con respecto a la condicional simple, ya que, la expresión debe generar un valor de tipo ordinal, por lo tanto, las expresiones reales y de cadena no pueden ser empleadas para las sentencias condicionales múltiples. La sintaxis es:


La sentencia case consiste en una expresión –selector- su resultado debe ser de tipo ordinal, y una lista de sentencias, cada una de las cuales está precedida por una o más constantes, del mismo tipo de la expresión, denominadas constantes case, o precedida con la palabra reservada else.
El valor ordinal del selector debe estar limitado a [-32768; 32767] y los tipos string, longint y word son inválidos para usarlos como selector.
La sentencia case después de evaluar el resultado de la expresión compara por igual con los valores constantes case en el orden en que han sido escritas, ejecutando la sentencia correspondiente a ese caso si existió una igualdad. En caso contrario y si está presente la partícula else se ejecutará la sentencia que le sigue, sino nada se ejecutará.
Este tipo de sentencia condicional es apta cuando se quiera evaluar una serie de valores ordinales; en lugar de emplear la sentencia condicional simple en forma anidada. Debido a esto, se hace más limpia la codificación a efectos de poder interpretar la lógica de manera más clara. No obstante, debemos tener en cuenta que este tipo de sentencia condicional no puede ser aplicada en todos los casos, es decir, es de aplicación limitada a los tipos ordinales.

Ejemplos:


Sentencias repetitivas

Las sentencias repetitivas establecen que ciertas sentencias serán ejecutadas repetidamente. Los ciclos son tan importantes en un proceso computacional que prácticamente no existen procesos que no incluya algún ciclo. Situaciones como escribir 10, 100, 1000 o mas veces un conjunto de sentencias haría improbable la programación, más aún, ¿cuántas veces escribir esas sentencias, si la cantidad de veces a realizarse estaría establecida por alguna condición?. Imposible de no existir los ciclos. A continuación se verán diversas variantes que podemos encontrarnos con este tipo de estructuras de control. Será el buen criterio del programador seleccionar una de estas variantes ante una situación particular.
En todo tipo de ciclos tendremos por lo general sentencias previas al inicio del ciclo, en este punto decimos preparar la situación antes. Entre las acciones más habituales tenemos; emitir títulos y/o datos, inicializar variables. Dentro del ámbito del ciclo denominamos procesar las acciones ubicadas en este segundo punto y por último, al salir del alcance del ciclo tenemos el terminar, que incluye ciertas acciones como ser, emitir resultados, cálculos de promedios, porcentajes, etc..

Preparar
Repetir
   Procesar
FinRepetir
Terminar

La sentencia indefinida, pre-condición, 0-X, mientras WHILE

La sentencia indefinida establece que la sentencia o bloque de sentencias se ejecutarán si la condiciones pre-establecida en la cabecera de esta estructura es verdadera y en caso de que se haga falsa se abandonará la repetición. La sintaxis es:

La expresión que controla la repetición debe ser de tipo boolean. Ésta es evaluada antes que la sentencia contenida sea ejecutada. La sentencia contenida es ejecutada repetidamente mientras la expresión sea verdadera. Si la expresión fuera falsa al inicio entonces nada se ejecuta. Por lo tanto, este tipo de ciclo es un ciclo en la cual la sentencia contenida puede no ejecutarse o bien ser ejecutada x veces, de ahí que también se lo denomine ciclo 0-x. La expresión puede estar controlada por un acumulador, un valor centinela, una señal, una condición de fin de archivo como se verá más adelante, o por condiciones múltiples. Este tipo de estructura se basta por sí misma, esto quiere decir que no depende de la existencia de otras estructuras repetitivas. Aunque como se verá más adelante en ciertas condiciones particulares otra variante cíclica será más óptima para ciertos casos.
Debemos tener sumo cuidado con esta estructura cuando se haya ingresado al ciclo y poder establecer con alguna acción que modifique el resultado de la expresión, a que en algún momento se invierta produciendo un resultado de falso para así poder abandonar el ciclo. El ámbito es de una sola sentencia, más, requiere el uso de un bloque o sentencia compuesta –concatenación-.
En general existirá un conocer primer valor en la instancia de preparar; dentro del ciclo, procesar el valor y como última acción, dentro del ciclo, conocer próximo valor.

Preparar
   Emitir títulos
   Inicializar variables
   Conocer primer valor
while expresión do begin
   Procesar valor
   Conocer próximo valor
end
Terminar
   Cálculos finales
   Emitir resultados finales del procesar

Ejemplos:




La sentencia exacta, pre-condición, para FOR

La sentencia for hace que la sentencia contenida sea ejecutada repetidamente una cantidad exacta de veces. La sintaxis es:

En el punto de entrada o cabecera se evalúa el valor inicial y final. Cuando una sentencia for, usa la cláusula to, si el valor inicial es mayor al valor final, la sentencia dentro del ámbito del ciclo no se ejecuta. La variable de control se inicializa con el valor inicial, luego que haya ejecutado la sentencia contenida y de haber determinado que su valor es menor al valor final, la variable de control se incrementa en uno por cada repetición, en cambio, si el valor de la variable de control se hizo igual al valor final, se abandona el ciclo. La cantidad de veces que se repite el ciclo está dado por la siguiente expresión:
CantRepAsc = valFin – valIni + 1.
Cuando una sentencia for usa la cláusula downto, si el valor inicial es menor al valor final, la sentencia dentro del ámbito del ciclo no se ejecuta. La variable de control se inicializa con el valor inicial, luego que haya ejecutado la sentencia contenida y de haber determinado que su valor es mayor al valor final, la variable de control se decrementa en uno por cada repetición, en cambio, si el valor de la variable de control se hizo igual al valor final, se abandona el ciclo. La cantidad de veces que se repite el ciclo está dado por la siguiente expresión:
CantRepDesc = valIni – valFin + 1.

La variable de control, como así también, el valor inicial y el valor final deben ser del mismo tipo ordinal.
El valor de la variable de control no debe ser modificada por el programador, pero sí puede ser usada para otro propósito.
Un ciclo for es más óptimo que un ciclo while. No obstante el ciclo for solo podrá se utilizado cuando se sabe de antemano la cantidad de veces en que se debe de ejecutar la sentencia contenida en su ámbito de alcance.

for i:= 1 to 5 do
writeln(i);

for i:= 5 downto 1 do
writeln(i);

write(‘Ingrese un valor inicial: ‘);
readln(vi);
write(‘Ingrese un valor final: ‘);
readln(vf);
for i:= vi to vf do begin
write(‘Ingrese nombre: ‘);
readln(Nom);
writeln(‘¿Cómo estás?, ‘,Nom)
end;

La sentencia indefinida, post-condición, 1-X, hasta REPEAT UNTIL

La sentencia repeat until contiene una expresión que controla la ejecución repetida de una secuencia de sentencias dentro de la sentencia repeat until. La sintaxis es:
La sentencia debe producir un resultado de tipo boolean. Las sentencias entre los símbolos repeat y until son ejecutadas secuencialmente hasta que el resultado de la expresión se torne verdadera. Las sentencias contenidas son ejecutadas al menos una vez, debido a que la expresión es evaluada después de la ejecución de cada secuencia.
Debemos tener sumo cuidado con esta estructura cuando se haya ingresado al ciclo y poder establecer con alguna acción que, modifique el resultado de la expresión, a que en algún momento se invierta produciendo un resultado de verdadero para así poder abandonar el ciclo. El ámbito queda establecido entre los símbolos repeat until, por lo tanto no es necesario el uso de un bloque para contener varias sentencias.
Este tipo de ciclo debe ser utilizado con mesura, solo en aquellos casos en que al menos una vez deben ejecutarse las acciones contenidas en el ciclo, como p.e., en la creación de menú, validación de datos, determinar si un conjunto de datos está ordenado, entre ciertos otros casos.
Ejemplos:





Siguiente: Archivos I



No hay comentarios: