
Instrucción Perform
Creo que por méritos propios esta instrucción se merece un apartado
para ella sola. Es una instrucción que nos permite
tranferir el control a otro u otros procedimientos o
bien realizar una serie de sentencias dentro de ella
misma mientras se cumplan las condiciones que le hayamos
indicado. Es la instrucción mas importante tanto
por su variedad de formatos, como por el número
de veces que se suele usar dentro de un programa, además
nos puede hacer mucho mas sencillo el realizar una programación
estructurada.
Cuando decimos que un programa está estructurado,
no cabe duda que es debido al uso de ésta instrucción.
Pero creo que lo importante no es tanto hablar de ella,
sino comenzar a explicarla.
Empecemos a ver sus formatos desde el mas simple
al mas complicado: Siempre debéis de tener en
cuenta que los ejemplos son solo para aclarar la explicación,
nunca los toméis como programas completos y con
una lógica aplastante.
Formato 1: Con este formato transferimos el control del programa a un párrafo,
cuando éste termine vuelve el control a la instrucción que sigue al
PERFORM .
PERFORM nombre_parrafo
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(30). 01
OP PIC X. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE. DISPLAY
'HOLA ' LINE 10. DISPLAY
NOMBRE LINE 10 COL 6. ACCEPT
OP LINE 20. STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. ... | |
Nota: Simplemente hemos hecho que el programa salte
a un párrafo que lo ejecute y que vuelva el control a la secuencia. |
Formato 2: Una extensión del anterior es indicarle que ejecute mas de un
párrafo, especificando el inicio y el fin.
PERFORM nombre_parrafo
THRU nombre_parrafo
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 OP
PIC X. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE THRU PIDEAPELLIDO. DISPLAY
'HOLA ' LINE 10. DISPLAY
NOMBRE LINE 10 COL 6. DISPLAY
APELLIDO LINE 10 COL 20. ACCEPT
OP LINE 20. STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21. ACCEPT
APELLIDO LINE 21 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. DISPLAY
SPACES LINE 21 SIZE 70. ... | |
Nota: En este caso PIDENOMBRE y PIDEAPELLIDO van seguidos,
pero al poner el THRU lo que conseguimos es que el control no se devuelva hasta llegar
al párrafo indicado después del THRU. Es decir que entre PIDENOMBRE
y PIDEAPELLIDO podrá haber cinco párrados mas y todos ellos se hubieran ejecutado.
|
Formato 3: Seguimos ampliando las capacidades, ahora conseguimos que el
PERFORM se realice tantas veces como se indique en el número o variable que va
delante de TIMES.
PERFORM nombre_parrafo
THRU nombre_parrafo número-variable
TIMES
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 OP
PIC
X. 01 LI PIC
99 VALUE 10. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE THRU PIDEAPELLIDO. PERFORM
SALUDAR 3 TIMES. STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21. ACCEPT
APELLIDO LINE 21 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. DISPLAY
SPACES LINE 21 SIZE 70. SALUDAR. ADD
1 TO LI. DISPLAY
'HOLA ' LINE LI. DISPLAY
NOMBRE LINE LI COL 6. DISPLAY
APELLIDO LINE LI COL 20. ACCEPT
OP LINE 20. ... | |
Nota: Ahora hemos conseguido que el saludo nos lo muestre 3
veces. Por supuesto THRU y TIMES pueden ir perfectamente juntos.
Ya os he dicho al principio que los ejemplos pueden no ser muy lógicos, pero si hacen la
función de explicación. |
Formato 4: Igual que el antrior formato solo
que el número de veces que se ejecute dependerá de una condición y no de un número fijo.
PERFORM nombre_parrafo
THRU nombre_parrafoUNTIL
condición
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 OP
PIC
X. 01 LI PIC
99 VALUE 10. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE THRU PIDEAPELLIDO. PERFORM
SALUDAR UNTIL LI = 15. STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21. ACCEPT
APELLIDO LINE 21 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. DISPLAY
SPACES LINE 21 SIZE 70. SALUDAR. ADD
1 TO LI. DISPLAY
'HOLA ' LINE LI. DISPLAY
NOMBRE LINE LI COL 6. DISPLAY
APELLIDO LINE LI COL 20. ACCEPT
OP LINE 20. ... | |
Nota: En este caso el compilador comprueba antes de iniciar
el PERFORM que la condición no se cumple para ejecutarla, en el momento que
se cumpla salta a la siguiente instrucción. En el ejemplo ejecutará el
PERFORM hasta que la variable LI alcance el valor 15. |
PRIMERA CONCLUSION
En los dos primeros formatos, como podréis comprobar a menos que sean instrucciones
que se vayan a llamar desde nuestro programa en mas de una ocasión, éstas
podían haber ido en el lugar del PERFORM, es decir las instrucciones
una detrás de otra y evitar el PERFORM.
Hasta ahora se ha explicado una manera de utilizar la sentencia PERFORM
en la que el control pasa a otro lugar del programa. Como véis el
STOP RUN está antes de los párrafos que han sido llamados con los
PERFORM lo cual indica que éstos no se ejecutarán sino es precisamente
por los PERFORM. Si bien con esto conseguimos una estructuración para
nuestro programa la instrucción PERFORM nos permite un mayor
grado de estructura incluyendo las sentencias de los párrafos llamados dentro de la propia
sentencia PERFORM.
Para ello hay que tener en cuenta que la utilización del punto en las instrucciones
daría lugar al fin de la instrucción y nos daría errores, por ello, para
finalizar la instrucción nos basamos en END-PERFORM. Veamos
un ejemplo de ello con los dos últimos formatos explicados anteriormente.
PERFORM número-variable
TIMES
sentencias
END-PERFORM
PERFORM UNTIL condición
sentencias
END-PERFORM
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 OP
PIC
X. 01 LI PIC
99 VALUE 10. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE THRU PIDEAPELLIDO. PERFORM
3 TIMES ADD
1 TO LI DISPLAY
'HOLA ' LINE LI DISPLAY
NOMBRE LINE LI COL 6 DISPLAY
APELLIDO LINE LI COL 20 ACCEPT
OP LINE 20 END-PERFORM STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21. ACCEPT
APELLIDO LINE 21 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. DISPLAY
SPACES LINE 21 SIZE 70. ... |
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 OP
PIC
X. 01 LI PIC
99 VALUE 10. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE THRU PIDEAPELLIDO. PERFORM
UNTIL LI = 15 ADD
1 TO LI DISPLAY
'HOLA ' LINE LI DISPLAY
NOMBRE LINE LI COL 6 DISPLAY
APELLIDO LINE LI COL 20 ACCEPT
OP LINE 20 END-PERFORM STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21. ACCEPT
APELLIDO LINE 21 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. DISPLAY
SPACES LINE 21 SIZE 70. ... | |
Nota: Esta es una manera mas lógica de utilizar el PERFORM
en estos formatos, como veís se consigue una visión muy clara de lo que estamos
haciendo y no hay saltos de secuencia innecesarios. Por supuesto el COBOL permite cualquier
modalidad de uso y siempre funcionaría igual. Como veis no puede haber puntos entre
el PERFORM y el END-PERFORM puesto que eso haría terminar con
error la sentencia. |
Formato 5: En esta ocasión utilizaremos el PERFORM
basándonos en un valor inicial el cual podremos y aumentar o disminuir y terminar cuando
se cumpla una condición. No se si me he liado un poco con la explicación pero lo
que conseguimos es ahorrarnos varias instrucciones y resumirlas en una sola, para que lo
comprendáis veamos su formato y un ejemplo. Como he explicado anteriormente podemos
hacer que el PERFORM invoque a uno o varios párrafos
o bien incluir el conjunto de sentencias entre PERFORM y END-PERFORM.
En el ejemplo veremos este último caso, porque creo que es mas aconsejable.
PERFORM VARYING variable
FROM número, variable
BY número, valor
UNTIL condición
sentencias
END-PERFORM
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 OP
PIC
X. 01 LI PIC
99. PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE. PERFORM
PIDENOMBRE THRU PIDEAPELLIDO. PERFORM
VARYING LI FROM 10 BY 1 UNTIL LI = 15 DISPLAY
'HOLA ' LINE LI DISPLAY
NOMBRE LINE LI COL 6 DISPLAY
APELLIDO LINE LI COL 20 ACCEPT
OP LINE 20 END-PERFORM STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20. ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21. ACCEPT
APELLIDO LINE 21 COL 30 PROMPT. DISPLAY
SPACES LINE 20 SIZE 70. DISPLAY
SPACES LINE 21 SIZE 70. ... |
La instrucción realiza los siguientes pasos: Inicializa la variable LI con el
valor que sigue al FROM, es decir 10, a continuación va incrementado el valor
de LI en 1 que es lo que va después del BY y ejecuta las sentencias que van
a continuación hasta que se cumple la condición de LI = 15. Es decir las sentencias se ejecutarían
para el valor 10, 11, 12, 13 y 14.
La instrucción PERFORM se puede anidar tantas veces como
se quiera, teniendo en cuenta que el PERFORM contenido debe de ejecutarse completamente
interno o completamente externo al que lo contiene.
Si necesitamos que por alguna circunstancia finalice la ejecución de un
PERFORM aún cuando la secuencia no corresponde, podemos utilizar la sentencia
EXIT, que precisamente lo que propicia es eso, que se interrumpa la sentencia
PERFORM.
Para finalizar vamos a ver un ejemplo con varios PERFORM anidados:
|
... WORKING-STORAGE
SECTION. 01 NOMBRE PIC X(12). 01
APELLIDO PIC X(12). 01 SALUDO
PIC X(30). 01 OP
PIC
X. 01 LI PIC
99. 01 CONTA1 PIC 99. 01
CONTA2 PIC 9(6). PROCEDURE DIVISION.
INICIO.
DISPLAY 'PROGRAMA DE SALUDO' LINE
1 ERASE PERFORM
PIDENOMBRE THRU PIDEAPELLIDO STRING
'HOLA ' DELIMITED BY SIZE NOMBRE DELIMITED
BY ' ' '
' DELIMITED BY SIZE APELLIDO DELIMITED BY
' ' INTO SALUDO PERFORM
VARYING LI FROM 10 BY 1 UNTIL LI = 15 PERFORM
VARYING CONTA1 FROM 1 BY 1 UNTIL CONTA1
> 30 DISPLAY
SALUDO(CONTA1:1) LINE LI COL CONTA1 LOW PERFORM
VARYING CONTA2 FROM 1 BY 1 UNTIL CONTA2
> 400000 MOVE
' ' TO OP END-PERFORM END-PERFORM END-PERFORM DISPLAY
'FINALIZADO' LINE 22 ACCEPT
OP STOP
RUN. PIDENOMBRE. DISPLAY
'INTRODUZCA EL NOMBRE ..' LINE 20 ACCEPT
NOMBRE LINE 20 COL 30 PROMPT. PIDEAPELLIDO. DISPLAY
'INTRODUZCA EL APELLIDO ..' LINE 21 ACCEPT
APELLIDO LINE 21 COL 30 PROMPT DISPLAY
SPACES LINE 20 SIZE 70 DISPLAY
SPACES LINE 21 SIZE 70. ... | |
Nota: En el ejemplo como véis, después de aceptar el nombre y el apellido construimos una
frase y la guardamos en la variablen SALUDO utilizando el comando STRING. A continuación
y para mantener los mismos ejemplos de toda la sección hacemos que aparezca en
pantalla el SALUDO 5 veces, (dependiendo del valor de LI, que como dijimos antes sería
para 10, 11, 12, 13 y 14).
Pero ahora hemos intercalado dos PERFORM dentro de éste, el primero para que nos muestre
el mensaje letra a letra y el segundo para hacer de retardo y así conseguir
un efecto como si escribiéramos el SALUDO con una máquina de escribir.
Como pódeis observar el único punto de toda la secuencia se haya en el STOP RUN. El hecho
de mantener los márgenes izquierdos, es para dar mas claridad a la programación
y conseguir que ésta sea lo mas estructurada posible.
|
AUN HAY MAS
Pues sí, podemos desarrollar aún mas la instrucción incluyendo dos nuevos elementos.
EJECUTANDO ANTES O DESPUES
En primer lugar, por defecto el contenido del PERFORM se ejecuta después de hacer
la comprobación de la condición que precede a UNTIL
, pero podemos hacer que ésta se realice antes.
PERFORM WITH TEST [AFTER - BEFORE ] VARYING
variable FROM
número, variableBY
número, valorUNTIL
condición
sentencias
END-PERFORM
Con la opción TEST BEFORE, que es la opción por defecto
se comprueba primero la condición y si se cumple se ejcuta el resto, con lo cual es posible que las sentencias
no se ejecuten ninguna vez, si al comenzar ya está rota la condición.
Con la opción TEST AFTER, se ejecutan las sentencias
antes de comprobar la condición, con lo cual las sentencias se van a ejecutar al menos en una ocasión,
incluso aunque entremos en el PERFORM con la condición rota.
AUMENTANDO LAS CONDICIONES
Efectivamente además de la primera condición podemos incrementar el número
de condiciones para que se cumplan los requisitos y así ejecutar las sentencias. Esto lo conseguimos
incluyendo mas cláusulas precedidas de AFTER.
PERFORM WITH TEST [AFTER - BEFORE ] VARYING
variable FROM número, variable
BY número, valor
UNTIL condición
AFTER variable
FROM número, variable
BY número, valor
UNTIL condición
sentencias
AFTER ......
END-PERFORM
Al aplicar este formato cuando se cumpla la primera condición pasará el control al
AFTER y comprobará de nuevo la condición que precede al siguiente
UNTIL según los valores especificados en la línea que contiene
AFTER. Además podemos ir incrementando el número de
condiciones a nuestro antojo, consiguiendo de éste modo hacer unos anidamientos y un desarrollo
mas completo de la sentencia, obteniendo por consiguiente unos niveles de perfeccionamiento muy altos.
RESUMIENDO
Una mayor utilización de PERFORM sin duda traerá un uso menor
de la declaración GO y con ello conseguimos una programación estructurada.
Las ventajas de la programación estructurada las quiero explicar en un apartado dentro de ésta
misma sección de Manuales, una vez explique las sentenicas GO e IF,
que serán la siguiente aportación al manual.
En esa nueva sección se verá un caso mas práctico y real de
utilización de PERFORM con uso de lecturas de ficheros y demás
experiencias cotidianas en el mundo de la programación en el ámbito de la gestión.
|
|