Procedimientos y Funciones. - Departamento de Electrónica

Anuncio
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
18. PROCEDIMIENTOS Y FUNCIONES
18.1. Razones de Uso.
Los procedimientos y funciones tienen un papel fundamental en el diseño de programas.
Debido a su importancia existen distintas razones para su utilización, las que se describirán a
continuación.
18.1.1. Estructura del algoritmo.
Como se vió en la introducción del concepto en forma informal, los procedimientos permiten
describir una tarea en términos de subtareas, destacando la estructura dominante y
suprimiendo los detalles. Permitiendo de esta forma el desarrollo jerárquico (top-down) de
programas, y también facilitando un lenguaje apto para el método de desarrollo por
refinaciones sucesivas.
Los nombres que se emplean en el programa principal, y que representan subtareas, se
conocen como llamadas o invocaciones al procedimiento. Sintácticamente un identificador de
procedimiento es una instrucción (o statement), y la acción que se realiza es la ejecución del
bloque asociado al nombre mediante la declaración del procedimiento. Una vez ejecutado el
bloque del procedimiento, se retorna a la instrucción que sigue a la que produjo la ejecución
del bloque.
La declaración del procedimiento define las acciones que serán realizadas; es en esta parte
en la que se especifican los detalles que se abstraen con el nombre que identifica el
procedimiento.
Los procedimientos permiten dividir y estructurar un programa en componentes lógicamente
coherentes; facilitando así la verificación (prueba por etapas); mejorando la documentación y
entendimiento del programa.
El estilo y calidad de un programa depende en gran medida de la adecuada elección de los
procedimientos a emplear. Una forma de aprender eficientemente la técnica de "dividir para
vencer", escogiendo procedimientos simples y poderosos, se logra mediante el análisis de
programas (ojalá complejos) escritos por buenos programadores. Otro aspecto, que ayuda,
es un proceso reflexivo, casi meditativo, respecto del problema: es decir, pensar en el
problema. También ayuda el trabajo previo con papel y lápiz, y no dudar en volver a
reescribir varias veces el programa principal y algunas descripciones de procedimientos
secundarios.
Prof. Leopoldo Silva Bijit.
07-07-2003
217
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
En largos programas y algoritmos complejos es particularmente útil el concepto de
procedimiento. En casos simples y programas cortos, pueden reemplazarse los
procedimientos por las acciones que los representan; sin embargo, si se desea tener claridad
en la estructura del programa, es recomendable usar procedimientos explícitos, aún en casos
simples.
18.1.2. Reducción de espacio.
Si el mismo procedimiento será invocado en diversas partes del programa, su uso implica
reducir el largo del programa. Lo cual lleva asociado una disminución del tiempo de edición
del texto, ya que no es necesario copiar repetidas veces las secuencias de instrucciones que se
repiten. Este uso ve aumentada su potencialidad con el concepto de parámetros, que se verá
más adelante, y que hace posible invocar el mismo procedimiento, en diferentes puntos de un
programa, pasándole al procedimiento diferentes valores y variables determinados en el punto
de invocación.
Si el largo del texto es menor, la posibilidad de cometer errores es menor. Además una
reducción del texto lleva a una reducción del tamaño del código compilado, produciendo
ahorro de memoria. También el tiempo de compilación es menor.
18.1.3. Facilidad de verificación y pruebas.
En Pascal, la sintaxis de declaración de procedimientos es similar a la de un programa. En
este sentido es fácil editar un procedimiento como un programa, y luego de probarlo,
incorporarlo, a través del editor de textos, al programa. Algunos compiladores ofrecen la
posibilidad de compilación separada de procedimientos; en estos casos, se logran
disminuciones notables en el tiempo de desarrollo de un programa.
18.1.4. Acciones especiales.
Dado un ambiente de programación, por la estructura de datos que se emplee, pueden
conceptuarse acciones especiales (más elaboradas que las del lenguaje de alto nivel) para ese
ambiente. Es decir procedimientos que manipulen las estructuras a través de operaciones.
Se logra entonces, especializar el repertorio de instrucciones para el ambiente dado. Luego
con este Macrolenguaje puede efectuarse la programación en forma más eficiente. Lo anterior
está relacionado con la técnica de programación conocida como máquinas virtuales;
consistente en recubrir las primitivas instrucciones de máquina por diferentes capas de
Prof. Leopoldo Silva Bijit.
07-07-2003
218
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
software (programas) que permiten al programador ver una máquina especializada con las
instrucciones más adecuadas para su aplicación.
18.2. Sintaxis de Procedimientos. Parámetros.
<invocación> ::=
<identificador de procedimiento> [<lista parámetros actuales>]
<declaración> ::=
'PROCEDURE'
<identificador> [<lista parámetros formales>] ';'
<bloque> ';'
En un ambiente de programación se dice que un parámetro es un mecanismo de substitución
que permite repetir un proceso con una variación de sus argumentos.
Los parámetros describen la comunicación entre un procedimiento y su ambiente. La lista de
parámetros del programa principal también establece la comunicación entre el ambiente
externo, teclado, consola y archivos, y el programa.
De esta forma los parámetros equivalen a las instrucciones de entrada y salida (read y write)
del programa principal.
La sintaxis de lenguajes actuales de alto nivel, como el Ada, califican los parámetros
formales como de entrada, salida y entrada/salida; haciendo énfasis en el aspecto de
comunicación. En Pascal, en forma más tradicional, se habla de paso de parámetros y retorno
de éstos.
Una práctica recomendable es que la comunicación de un procedimiento con su ambiente
sea sólo a través de los parámetros; evitando la comunicación mediante asignaciones a
variables globales dentro de procedimientos. Esto último se conoce como efectos laterales y
es equivalente a tener salidas secundarias; quebrantando la regla de programación
estructurada de que cada acción tenga sólo una entrada y una salida.
Prof. Leopoldo Silva Bijit.
07-07-2003
219
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
En Pascal existen cuatro tipos de parámetros: parámetros de valor, parámetros variables,
parámetros función y parámetros procedimientos. En este curso introductorio sólo se
desarrollarán los dos primeros; considerándose demasiado especializados los dos últimos.
Con estas consideraciones:
<lista parámetros formales> ::=
'(' {( ['var'] {<identificador>* ','} ':' <tipo>)* ';' } ')'
<lista parámetros actuales> ::=
'(' {( <expresión>)* ',' } ')'
Nótese que los parámetros formales se separan con un punto y coma y lo s actuales por
comas. También hay que notar que los formales deben especificar el tipo. Para cada
parámetro formal debe existir uno actual asociado, éste último debe tener igual tipo que el
formal correspondiente. La correspondencia se establece por las posiciones de los
parámetros en las listas. Esto permite al compilador verificar si se ha suministrado un
parámetro actual apropiado y si las listas son compatibles. Conviene dibujar los grafos
sintácticos de las producciones anteriores.
Los parámetros variables van precedidos por la palabra reservada var en la lista de
formales; y deben tener asociado una variable (caso más simple de expresión) en la lista de
actuales, y cuyo tipo debe ser igual al declarado para la formal.
Los parámetros valor, no van precedidos por var, en la lista de formales; y deben tener
asociado una expresión (en el caso más simple una variable o constante) en la lista de
actuales, y el tipo de la expresión debe ser compatible con el tipo declarado para el formal.
Todos los identificadores que aparecen en la lista de parámetros formales son locales al
procedimiento; así también todos los objetos declarados o definidos en el bloque
correspondiente. Es decir, ellos no son conocidos fuera del bloque. Específicamente las
variables locales tienen indefinidos sus valores al iniciar la parte ejecutable del bloque.
Es importante notar que en la lista de parámetros formales debe aparecer un nombre de un
tipo. En Pascal estándar no puede efectuarse una definición de tipo en la lista de parámetros.
Prof. Leopoldo Silva Bijit.
07-07-2003
220
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Versiones recientes permiten definir tipos en la lista de parámetros; facilitando así el
tratamiento de arreglos.
Prof. Leopoldo Silva Bijit.
07-07-2003
221
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
18.3. Tipos de Procedimientos.
18.3.1. Sin parámetros. Sólo acción.
En estos procedimientos no se suministran datos, desde el ambiente hacia el procedimiento;
ni se esperan resultados, desde el procedimiento hacia el punto de invocación.
Se emplean sólo para ejecutar una serie de instrucciones al invocar o llamar al identificador
que da nombre al procedimiento.
Ejemplo: Procedimientos sin parámetros.
Limpiar la pantalla, dejándola en blanco.
procedure limpiepantalla;
var i:integer;
begin
for i:=1 to 24 do writeln
end;
Al invocar a limpiepantalla, se desplazan (scroll en inglés) las líneas, quedando el cursor en
el borde inferior izquierdo; no importando la posición inicial del cursor.
Nótese que la variable i es local al procedimiento, y existe mientras se ejecuta éste.
Se emplean procedimientos sin parámetros cuando se desea realizar una acción compleja,
bajo un nombre abstracto que las represente. El bloque del procedimiento debe quedar
completamente especificado y no se espera realizar variaciones de la acción.
Algunos programadores emplean estos procedimientos, y se comunican con otros bloques a
través de variables globales. Esto debe evitarse, pues dificulta el análisis y las pruebas del
programa.
Una variante del ejemplo anterior es:
procedure clearscreen;
const ff = 12;
begin write(chr(ff)) end;
Prof. Leopoldo Silva Bijit.
07-07-2003
222
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Esta acción deja el cursor en el borde superior izquierdo. Sin embargo debe probarse en la
práctica, pues algunos terminales no reconocen dicho carácter de formato. En este caso debe
consultarse el manual técnico del terminal que se esté empleando.
18.3.2. Parámetros de valor. Sólo entrada.
Se pasan valores desde el punto de invocación hacia el procedimiento. Es decir, sólo se
suministran datos de entrada y no se esperan resultados. El bloque de accio nes, asociado al
procedimiento, depende de los valores que se le pasen.
El parámetro formal es una variable local. El parámetro actual es una expresión. Se evalúa,
el parámetro actual, y el valor de la expresión sustituye el correspondiente parámetro formal.
Es decir, se asigna inicialmente el valor a la variable local o parámetro formal.
A este tipo de procedimientos se los denomina sustitución por valor, o llamado por valor, o
paso de parámetros valor.
Una vez realizado el procedimiento, se retorna a la instrucción siguiente a la que produjo la
invocación, sin producir cambios en este ambiente; salvo que dentro del bloque se hayan
modificado variables accesibles en el ambiente y en el bloque. Esta última práctica es posible,
pero no es recomendable.
Ejemplo. Procedimiento con parámetro valor.
Se desea lograr un margen variable a la izquierda.
procedure margen(x:integer);
const blanco = ' ';
var i:integer;
begin
for i:=1 to x do write(blanco)
end;
El parámetro formal es un parámetro valor y corresponde a la variable local x. La variable i
es local, sólo existe mientras dure el procedimiento. La constante blanco también es local.
Nótese que el tipo queda definido en la declaración; es decir, x es de tipo integer.
Prof. Leopoldo Silva Bijit.
07-07-2003
223
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Dentro de un segmento, donde el procedimiento margen es accesible, puede invocarse a
margen con diferentes valores:
.
.
m:=5;
{m debe ser entero}
margen(m);
{se llama con variable; produce 5 espacios}
.
.
margen(3);
{se llama con constante; produce 3 espacios}
.
.
margen(m+3);
{se llama con expresión; produce 8 espacios}
.
.
x:=6;
{x debe ser entero}
margen(x);
{se pasa valor 6}
{no se modifica valor de x; este x no tiene que ver}
{con la variable local del procedimiento margen}
.
.
Cuando se invoca a un procedimiento de este tipo, se crea espacio para las variables
locales, incluídas las variables formales. Luego, estas últimas se inician con los valores
calculados de las expresiones asociadas a los parámetros actuales. Dentro del bloque, no
quedan iniciadas las variables estrictamente locales, lo cual es tarea del programador; también
dentro del bloque pueden modificarse, mediante manipulaciones, todas las variables
accesibles. Una vez terminado el bloque, desaparece el espacio asignado a todas las
variables. Los parámetros formales tienen igual comportamiento que las variables locales,
excepto que comienzan con valores asignados al iniciar el bloque del procedimiento.
Si un parámetro valor es de tipo estructurado, deben copiarse los valores de las expresiones
en los elementos de la estructura; esto puede consumir tiempo y espacio.
Si en las expresiones ocurren variables estructuradas, debe accesarse a la estructura (en el
caso de un arreglo, debe evaluarse el índice) y obtener el valor.
Una técnica que es general para todo tipo de procedimientos es detectar todos los objetos
que no se usan fuera del procedimiento, y declararlos locales a éste.
Prof. Leopoldo Silva Bijit.
07-07-2003
224
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
En general, los parámetros valor son los más usados.
18.3.3. Parámetros variables. Entrada y Salida.
Este tipo de procedimiento permite transferir información desde el punto de invocación
hacia el procedimiento; y el retorno de resultados desde el procedimiento.
Los resultados los entrega modificando variables visibles o accesibles en el punto de
invocación, que se pasan al procedimiento. Es en el parámetro actual, en el que se retorna el
resultado del procedimiento.
Los parámetros formales variables van precedidos por var en su declaración.
También se llaman sustitución por variable, o llamado por referencia. Cuando se invoca a un
procedimiento de este tipo, no se crea nuevo espacio para el parámetro formal; sino que se
hace referencia a la variable actual. Es decir, el parámetro formal representa a la variable
actual, durante la ejecución del procedimiento. El parámetro formal es realmente una variable
muda.
Si las variables son estructuradas, todos los accesos se realizan en el tiempo de la
invocación. Si una variable es una componente de un arreglo se evalúa el índice cuando se
invoca al procedimiento.
Al no crear espacio adicional para los parámetros formales, no hay pérdida de tiempo en la
copia y accesos. Por esta razón es preferible definir parámetros variables, cuando éstos sean
estructurados; existe ahorro de espacio y tiempo. Adicionalmente, en Pascal estándar se
impide emplear estructuras empaquetadas como parámetros variables.
Si existen varios parámetros variables, debe evitarse, en el momento de la invocación, que
existan nombres duplicados de variables en la lista. Es decir, la lista de parámetros actuales
debe ser disjunta.
Ejemplo. Procedimiento con parámetros variables.
Se desea descartar espacios y leer un carácter.
procedure getchr(var ch:char);
begin
repeat read(ch) until ch<>' '
Prof. Leopoldo Silva Bijit.
07-07-2003
225
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
end;
Se tiene que ch es un parámetro formal variable, de tipo char.
En un segmento, en que sea accesible getchr, pueden asignarse valores a variables de tipo
char, que sean visibles en el momento de la invocación.
.
.
getchr(a); {se asigna valor a variable a}
.
.
getchr(b); {se asigna valor a b}
.
.
El ejemplo ilustra el uso de un parámetro variable para depositar el resultado. O sea se usa
sólo de salida. También pueden emplearse para pasar una variable (con su valor) como
entrada, y luego de procesar sacar el resultado. En este caso se usa el valor viejo de la
variable actual, antes de cambiarlo. Esta subclase es realmente de entrada/salida.
Ejemplo. Procedimiento con entrada/salida.
Se desea incrementar variables enteras que funcionan como contadores.
procedure incremente(var n:integer);
begin
n:=n+1
end;
Si v1 y v2 son contadores enteros:
.
.
incremente(v1);
.
.
incremente(v2);
.
.
Prof. Leopoldo Silva Bijit.
07-07-2003
226
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Como observación final se destaca que un parámetro actual no puede ser una expresión o
una constante; debe ser una variable. Se recomienda usar este tipo de procedimientos para
manipular estructuras de datos; por ejemplo: arreglos y archivos.
Prof. Leopoldo Silva Bijit.
07-07-2003
227
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
18.3.4. Mezcla de parámetros.
Los puntos anteriores, con objeto de aclarar conceptos, han usado sólo un parámetro de
determinado tipo. Sin embargo, en un caso general, pueden existir parámetros de diferente
tipo en una lista.
Ejemplo. Paso por valor y por referencia.
program mezcla(output);
var a,b:integer;
{globales}
procedure h(x:integer; var y:integer);{x par. valor}
begin
{y par. variable}
x:=x+1; y:=y+1; {p1}
writeln(x,y)
{p2}
end;
{h}
begin
a:=0; b:=0;
h(a,b);
writeln(a,b)
end.
{mezcla}
{1}
{2} {se pasa valor cero y var b}
{3}
Traza: # a
b
Observaciones.
-------------------------------------------------------1
0
0
Se inician a y b.
2
y
x
Se entra a proc. h.
-----------------------------------------0
0
Se inicia x con valor de a y toma lugar de b.
p1 1
1
Se incrementa x e y.
p2
Se escribe: 1 1
-----------------------------------------1
Al salir, desaparece x.
b toma el valor de y. La variable a, no cambia.
3
Se escribe: 0 1
---------------------------------------------------------
Prof. Leopoldo Silva Bijit.
07-07-2003
228
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Si en el paso 2, se hubiera invocado:
h(b, a)
puede comprobarse que se escribe:
11
10
En este caso al salir del procedimiento, se modifica el valor de a; y b no cambia su valor.
Nótese que en la traza, se crea espacio sólo para parámetros formales de valor. Los
parámetros variables ocupan igual columna que las variables que reemplazan.
18.4. Procedimientos Estándares.
Se asumen declarados en un bloque que anida al programa principal. Y por lo tanto son
accesibles en cualquier lugar del programa. También puede advertirse, que si se emplea un
procedimiento de igual nombre que uno estándar; éste tendrá vigencia en el bloque que define
su alcance, de acuerdo a la regla de alcance de nombres. Esto permite redefinir las acciones
de los procedimientos estándar.
Las instrucciones primitivas: read, write, writeln y readln, son efectivamente procedimientos
en Pascal. Se las ha introducido como instrucciones básicas, por las ventajas conceptuales
que esto presenta. Debe notarse que son procedimientos especiales, ya que aceptan un
número variable de parámetros; y además se pueden pasar parámetros de distintos tipos.
18.5. Funciones.
18.5.1. Definiciones.
Conceptualmente los procedimientos son una abstracción de acciones especiales o
complejas.
Una función es una abstracción de una expresión compleja.
Su utilización es muy similar a la matemática; en la que se emplea una función para calcular
un valor a partir de sus argumentos.
Prof. Leopoldo Silva Bijit.
07-07-2003
229
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
La función permite emplear un resultado computado, como un paso intermedio, en una
expresión.
Ejemplo:
x:=sin(y)*2
Se invoca a la función estándar seno, con argumento y; el valor calculado, se multiplica por
2 y se asigna a x.
El identificador de una función representa el bloque de acciones asociado, así como también
el resultado computado.
La declaración de función se caracteriza por tener una indicación del tipo del resultado,
después de la lista de parámetros. Es decir queda asociado un tipo al nombre de la función.
En Pascal, el tipo de la función no puede ser estructurado. Se aceptan los primitivos
estándares y los escalares definidos (enumeración y subrango).
Es importante destacar que una función sólo retorna un valor como resultado. Si se desea
pasar más valores debe hacerse a través de parámetros variables, o asignaciones a variables
no locales al bloque de la función (lo que se denomina efectos laterales); en estos casos es
preferible desarrollar un procedimiento en lugar de una función.
18.5.2. Sintaxis.
<invocación> ::=
<nombre de función> '(' { <expresión>* ',' } ')'
<declaración de función> :: =
'FUNCTION' <nombre><lista parámetros formales>':'<tip o>';'
<bloque> ';'
La invocación es una posibilidad de factor dentro de la sintaxis general de expresiones.
La lista de parámetros formales será similar a la vista en procedimientos. No se verán
parámetros función y parámetros procedimientos.
Prof. Leopoldo Silva Bijit.
07-07-2003
230
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
En general se recomienda emplear parámetros valor; y restringir el uso de parámetros
variables a pasar datos estructurados de entrada solamente.
El empleo de parámetros variables, que sean modificados en el cuerpo de la función, genera
salidas secundarias, lo cual dificulta el manejo conceptual de una función como un objeto
asociado a un valor computado.
Una característica del bloque asociado a la función es que debe contener, por lo menos una
asignación al nombre de la función. Este es precisamente el valor retornado.
Es responsabilidad del programador la iniciación de las variables locales. Los parámetros
formales por valor, son iniciados por los correspondientes valores de las expresiones (o
parámetros actuales). Los parámetros variables también tienen sus valores iniciales dados por
las variables actuales correspondientes.
18.5.3. Ejemplos de funciones.
a) Elevar al cuadrado un entero. Parámetro valor.
function cuadrado(x:integer):integer;
begin
cuadrado:=x*x {se retorna resultado}
end;
Puede invocarse a cuadrado en expresiones:
y := cuadrado(5);
y := y+cuadrado(y); {y debe ser variable entera}
a[i] := cuadrado(y+5)*a[i];
y := cuadrado(a[i]); {se evalúa i; luego el valor de la componente}
b) Función con espacio local.
function sqrt(x:real):real;
const eps=1.0e-8;
var x1, x0:real; {espacio local}
begin {método de Newton para x>1}
x1:=x;
Prof. Leopoldo Silva Bijit.
07-07-2003
231
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
repeat
x0:=x1; x1:=(x0+x/x0)*0.5
until abs(x1-x0)<eps*x1;
sqrt:=x1 {retorno}
end;
También puede retornarse el valor x0, pero es mejor aproximación el valor de x1.
Para deducir el algoritmo puede aplicarse el método de Newton a la función:
f(x) = x ^ 2 - a = 0.
Para valores del argumento entre 0 y 1 se suele emplear el siguiente algoritmo:
function sqrt(x:real):real; {0<x<1}
const eps=1.0e-5;
var x1,x0:real;
begin
x0:=x; x1:=1-x;
while abs(x1)>eps do
begin
x0:=x0*(1+0.5*x1);
x1:=sqr(x1)*(0.75+0.25*x1)
end;
sqrt:=x0 {retorno}
end;
Como ejercicio puede desarrollarse una función que trate todo el rango. Con tratamiento
especial para 0 y 1; además puede protegerse contra argumentos negativos.
c) Sumar los primeros n enteros.
Se desea obtener:
j =n
sigma(n)=
∑j
j =1
Podría plantearse:
Prof. Leopoldo Silva Bijit.
07-07-2003
232
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
function sigma(n:integer):integer;
var j:integer;
begin
sigma:=0;
for j:=1 to n do
sigma:=sigma+j
{error}
end;
Pero no puede usarse un nombre de función en una expresión. Al nombre de la función sólo
puede asignarse un valor, y debe figurar a la izquierda del signo de asignación. Como veremos
más adelante dentro de una expresión puede usarse una invocación a la misma función que se
está definiendo; esto se denomina recursividad.
En forma correcta, debe usarse una variable local suma:
function sigma(n:integer):integer;
var j, suma:integer;
begin
suma:=0;
for j:=1 to n do suma:=suma+j;
sigma:=suma {retorna el valor}
end;
Puede considerarse:
sigma(n)=1+ 2 + 3 +........+(n-2)+(n-1)+n
sigma(n)=n+(n-1)+(n-2)+........+ 3 + 2 +1
Las dos expresiones, a la izquierda, son equivalentes; sólo se ha cambiado el orden.
Sumando las dos ecuaciones, puede comprobarse que:
sigma=n(n+1)/2
Entonces:
function sigma(n:integer):integer;
begin
sigma:=(n*(n+1)) div 2
end;
Prof. Leopoldo Silva Bijit.
07-07-2003
233
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Obsérvese que se asegura efectuar primero el producto, que será par; y por lo tanto
divisible por dos.
d) Sobre efectos laterales.
En general consisten en asignar valores a variables que no son locales al bloque o cuerpo de
la función.
Existen raras excepciones en que se desea este efecto. Una situación típica es cuando se
desea contar el número de veces que se efectúa una función.
Por ejemplo, en el caso de la función cuadrado vista en el caso a), se desea como resultado
primario obtener el valor del cuadrado; y como valor secundario el número de veces que se
ha invocado a esta función
Sea ncuad la variable en que se almacenará la cuenta, entonces:
function cuadrado(x:integer):integer;
begin
ncuad:=ncuad+1;
cuadrado:=x*x
end;
En este caso, ncuad no puede ser local; si lo fuera, desaparecerá al salir de la función. Se
sobreentiende cual será el uso de ncuad, fuera de la función.
Pero consideremos ahora, en forma hipotética, que en segmentos donde son accesibles
ncuad y la función cuadrado se construyeran las expresiones:
i) cuadrado(y)+ncuad
ii) ncuad+cuadrado(y)
Puede comprobarse que las sumas anteriores no serán iguales; violando la ley de
conmutatividad de la suma, aún cuando no se exceda el máximo entero. Estos efectos pueden
producir resultados inesperados cuando la función, que los contiene, es usada
inadecuadamente.
Prof. Leopoldo Silva Bijit.
07-07-2003
234
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
e) Diseño de funciones especiales.
Asumiendo que se dispone de un tipo vector:
type vector=array [1..nmax] of real;
Pueden desarrollarse funciones especiales para manipular variables que tengan la estructura
anterior. Además se intenta demostrar como se pueden manejar arreglos de largo variable;
esto es posible si el número variable de componentes se mantiene menor que nmax. Es decir
habrá un espacio reservado que no se utilizará.
e1) Función que retorne el máximo valor en un vector de n componentes; con n<=nmax.
function max(a:vector; n:integer):real;
var x:real; i:integer;
begin
x:=a[1];
for i:=2 to n do
if x<a[i] then x:=a[i];
max:=x {retorno}
end;
En general, obtiene el máximo valor entre las primeras n componentes del vector.
Nótese que se pasan parámetros de valor; y adicionalmente no se efectúa asignaciones a las
componentes del vector. Esto permite diseñar:
function max(var a:vector; n:integer):real;
var x:real; i:integer;
begin
x:=a[1];
for i:=2 to n do
if x<a[i] then x:=a[i];
max:=x
end;
La ventaja de esta implementación, es que mientras está activa la función se ocupa menos
espacio de memoria; ya que no se crea espacio local, como en la primera implementación.
También es más rápida ya que no hay necesidad de copiar los valores iniciales en el espacio
local. La economía de espacio y tiempo puede ser significativa si nmax es elevado.
Prof. Leopoldo Silva Bijit.
07-07-2003
235
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
e2) Función que retorna la suma de las n primeras componentes.
function sum(var a:vector; n:integer):real;
var i:integer; s:real;
begin
s:=0.0;
for i:=1 to n do s:=s+a[i];
sum:=s {retorno}
end;
18.5.4. Funciones estándares.
Cuando se estudió tipos de datos, en la parte correspondiente a manipulación, se
describieron las funciones estándar.
Es un buen ejercicio escribir los encabezados de las funciones estándar. Como ejemplos:
function round(x:real):integer;
function odd(i:integer):boolean;
function eoln(t:text):boolean;
Lo cual facilita reconocer el ambiente en que se aplica la función. Lo que puede observarse
en la lista de parámetros formales y en el tipo del resultado.
18.6. Ejercicios.
18.6.1. Dado el siguiente programa:
a) Redefinir variables tal que faciliten el análisis. (Pero conservando exactamente el significado
del algoritmo.)
Prof. Leopoldo Silva Bijit.
07-07-2003
236
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
b) Determinar lo que escribe.
program parametros;
var i,j,k:integer;
procedure wrtglb;
begin writeln('globales
:i,j,k',i:4,j:4,k:4) end;
procedure p(var i:integer);
begin
writeln('al entrar a p:i,j,k',i:4,j:4,k:4);
i:=i+1;
writeln('al salir de p:i,j,k',i:4,j:4,k:4)
end;
procedure q(h:integer; var j:integer);
var i:integer;
procedure r;
begin i:=i+1 end;
begin
writeln('al entrar a q:i,j,k',i:4,j:4,k:4);
i:=j;
if h=0 then p(j) else if h=1 then p(i) else r;
writeln('al salir de q:i,j,k',i:4,j:4,k:4)
end;
begin
i:=0;j:=1;k:=2;
wrtglb; q(0,k);
wrtglb; q(1,i);
wrtglb; q(2,j);
wrtglb
end.
18.6.2. Limpia la pantalla.
El llamado :
write(clear);
Prof. Leopoldo Silva Bijit.
07-07-2003
237
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
{limpia la pantalla y toca la campanilla}
function clear : char;
var i : integer;
begin
for i:=1 to 24 do writeln;
clear:=chr(07)
end;
18.6.3. Calendario.
Determinar una función que retorne el número de días de un mes, dado el mes y el año.
Deben considerarse los bisiestos.
18.7. Ejemplos.
18.7.1. Determinar qué escribe el programa. Explicar qué principio de la programación
estructurada no cumple el programa test.
program test(output);
var a,b : integer;
function h(x:integer); integer;
begin b:b-x; h:=sqr(x) end;
begin
b:=10; a:=h(b); writeln(a,b);
b:=10; a:=h(10)*h(b); writeln(a,b);
b:=10; a:=h(b)*h(10); writeln(a,b)
end.
Solución.
La función h modifica una variable global. Lo cual produce un efecto lateral o secundario;
es decir, el bloque h tiene una entrada (parámetro formal x) y dos salidas : el valor h de la
función y la modificación de b.
100
0
0
0
Prof. Leopoldo Silva Bijit.
07-07-2003
238
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
10000 -10
18.7.2. Determinar que escribe el programa. Explicando características de la función y el
procedimiento (parámetros, forma de intercambio de datos).
program demo(output);
var x,y,n : integer;
function gcd(m,n : integer):integer;
begin if n=0 then gcd:=m else gcd:=gcd(n,m mod n) end;
procedure try(a,b : integer);
begin writeln(a,b,gcd(a,b)) end;
begin try(18,27); try(61,53); try(98,868) end.
Solución.
La función gcd es RECURSIVA, con dos parámetros formales enteros y de tipo entero.
El procedimiento tiene dos parámetros formales enteros; efectúa una acción que depende de
los valores que se pasen (parámetros valor).
Obtiene el máximo común divisor entre dos enteros , y escribe, en una línea, los enteros y el
mcd.
18 27 9
61 53 1
98 868 14
18.7.3. Determinar la función que realiza Max. Explicar el ambiente (tipos y variables) en que
se la puede usar y dar a un ejemplo de invocación.
function Max(a:vector; n:integer)real;
var x:real; i:integer;
begin
x:=a[1]; for i:=1 to n do if x<a[i] then x:=a[i]; Max:=x
end;
Solución.
Prof. Leopoldo Silva Bijit.
07-07-2003
239
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
El tipo vector debe ser un arreglo de reales de 1 a N. La constante N al definir el tipo
vector fija la máxima dimensión de éste (en Pascal no hay arreglos dinámicos; es una
estructura estática que reserva un espacio determinado al inicio y que luego no puede
cambiarse durante la computación). Esto implica que al invocar la función Max el parámetro
actual asociado al formal n, no debe ser mayor que N.
La función obtiene el valor máximo de las componentes de un vector cuyo tipo base es
real. Por esta razón la variable local x es real, y también el tipo de la función.
La presencia del parámetro formal entero n permite obtener el valor máximo de un
subconjunto. Por ejemplo : el valor máximo de las primeras 10 componentes (si n es 10); o el
de las 20 primeras si n es 20.
Ejemplo :
Si b y c son de tipo vector (N=100):
a:=Max(b,5); d:=Max(b,50);
Max(c,10);
Max(c,<expresión entera con valor menor o igual que 100>);
18.7.4. Se tiene:
Type charset = set of char;
...
Procedure salte(var ch:char; conjunto: charset);
begin while ch in conjunto do read(ch) end;
...
a) Explicar acción realizada por el procedimiento en general.
b) Explicar acción específica para el llamado:
salte(x,['a'..'z']);
Solución.
a) El procedimiento salte lee caracteres desde el archivo estándar de entrada; y al no
asignarlos a ninguna variable esto implica que dichos caracteres son descartados como
información (se vuelve a asignar sobre ch).
Prof. Leopoldo Silva Bijit.
07-07-2003
240
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
Se descartan todos los caracteres que pertenezcan al conjunto, que se pasa como
parámetro valor (de entrada).
El parámetro formal ch es variable; y permite retornar valores (salida) en la variable
actual correspondiente. En ésta retorna el primer caracter que no pertenezca al conjunto.
b) salte(x,['a'..'z']); Retorna en x (que debe ser definida con tipo char) el primer caracter que
no sea letra minúscula.
18.7.5. Se tiene la matriz a dada por:
 2 1 3
a =  3 3 1


 1 2 1 
a) Obtener una traza de la ejecución de:
for i:=1 to 3 do
for j:=1 to 3 do c[i,j]:=a[a[i,j]a[j,i]];
b) Escribir la matriz c resultante.
Solución.
a) i j a[i,j] a[j,i] a[b,d] c[i,j]=
1 1
2
3
2 1
2
3
3 1
2
3
2
1
3
3
3
1
1
2
1
2
3
1
1
3
2
3
1
1
Prof. Leopoldo Silva Bijit.
3
3
1
1
1
1
3
3
2
c[1,1]= 3
c[1,2]= 3
c[1,3]= 1
c[2,1]= 1
c[2,2]= 1
c[2,3]= 1
c[3,1]= 3
c[3,2]= 3
c[3,3]= 2
07-07-2003
241
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
b)
3 3 1 
c = 1 1 1 


3 3 2
18.7.6. Determinar qué escribe el programa. Explicar.
program ocho(output);
var a,b,c : integer;
procedure p(x:integer; var y:integer; z:integer);
begin z:=x+y+z; y:=x+z; writeln(x:4,y:4,z:4) end;
begin a:=5; b:=8; c:=3;
p(a,b,c); p(a+b,b,a+c); p(a*b,c,a div b)
end.
Solución.
___5__21__16
26 81 55
405 813 408
• El parámetro formal y es variable; esto implica que se modificará la variable actual (al
salir del procedimiento)
• Variables globales a,b,c
• Variables locales x,y,z (el procedimiento las escribe)
• Debe observarse que dentro del procedimiento, la primera acción modifica a z; luego
la segunda ya toma el valor recién modificado.
• Los parámetros actuales (correspondientes a los formales x,z) pueden ser
expresiones. Son parámetros valor (o de entrada)
Traza
a b c x y z
5 8 3 5 8 3
P(a,b,c)
16
21
5 21 3
--> escribe 5 21 16
Se modifica la global b.
Prof. Leopoldo Silva Bijit.
07-07-2003
242
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
Programación en Pascal
Capítulo 18. Procedimientos y Funciones.
18.7.7. Dado el segmento:
const n=10;
type matriz = array[1..n,1..n] of integer;
var a,b,c : matriz;
begin
lea(a); lea(b);
sume(a,b,c);
escriba(c)
end.
{lee por columnas desde el estándar de entrada}
{suma matriz a con b y deja resultado en c}
{escribe por reglones}
Diseñar los procedimientos para manipular matrices: lea, sume y escriba.
Solución.
Procedure lea(var m:matriz); {debe ser variable para asignar valores a [a] y [b]}
var i,j : 1..n; {índices locales}
begin for j:=1 ton do
for i:=1 to n do read(m[i,j]) end;
{lazo interno i->lee secuencialmente los elementos de una columna}
Procedure escriba(m:matriz); {paso de valores; solo entrada}
var i,j : 1..n; {índices locales}
begin for i:=1 to n do
{lazo externo : el reglón}
begin for j:=1 to n do write(m[i,j]); writeln end
end;
Procedure sume(m1,m2 : matriz; var m:matriz);
var i,j : 1..n;
begin for i:=1 to n do
for j:=1 to n do m[i,j]:=m1[i,j]+m2[i,j] end;
Prof. Leopoldo Silva Bijit.
07-07-2003
243
Descargar