Manual de Cobol
Manual de Cobol
Manual de Cobol
Al pensar en Cobol como lenguaje de programación debemos de tener presente que nos
referimos a un lenguaje dedicado a gestión de datos con una magnífica transportabilidad entre
los distintos sistemas, yo he ejecutado el mismo programa en MS-DOS y UNIX sin modificar ni
una linea de código y copiando solo el objeto.
IDENTIFICATION DIVISION.
IDENTIFICATION DIVISION. Esta es la primera linea de todo programa Cobol e identifica a la
primera división donde se especifica el nombre del programa, el del autor y demás datos, su
sintaxis sería la siguiente:
IDENTIFICATION DIVISION.
PROGRAM-ID. Nombre del programa.
AUTHOR. Nombre del autor.
INSTALLATION. Lugar donde está instalado.
DATE-WRITTEN. Fecha de creación.
DATE-COMPILED. Fecha de compilación.
REMARKS. Comentarios.
Vemos que el único párrafo obligatorio además del nombre de división es el que hace referencia
al nombre del programa, los demás nombre de autor, lugar de instalación, fechas de creación y
compilación y comentarios son opcionales, eso si, si se incluyen se deben de poner cumpliendo
las normas.
Podemos incluir además todos los comentarios o explicaciones que creamos oportunas
incluyendo en la columna 7 un asterisco (*) que nos indica que el compilador hará caso omiso de
lo que venga a continuación, por ejemplo.
* /////// Este programa es para hacer algo ///////
* // atención a la sección de la fecha ////
Ejemplo:
IDENTIFICATION DIVISION.
PROGRAM-ID. MANCLI.
AUTHOR. ANDRES MONTES.
INSTALLATION. WWW.
REMARKS. Programa para mantenimiento de fichero de clientes.
Nota final:
Poco mas podemos decir de ésta division, obviamente las demás no son tan
pequeñas, sin embargo posee dos de las lineas mas importantes de cualquier
programa cobol.
ENVIRONMENT DIVISION.
ENVIRONMENT DIVISION. Es la segunda division por orden de aparición, y en ella se
especifican, el ordenador donde se escribió y se ejecutará el programa, asi como la relacion entre
los ficheros a utilizar con sus correspondencias externas, es decir con los dispositivos a los que
hará referencia el programa objeto cuando vaya a establecer comunicación con dicho fichero.
Diremos antes de continuar que en los primeros cobol había muchas partes que eran obligatorias
en cada programa, pero hoy en dia, por ejemplo, ésta división ya no es obligatoria, asi como
ninguna de sus partes. Su sintaxis sería la siguiente:
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
3
SOURCE-COMPUTER. Ordenador donde se escribió el fuente.
OBJECT-COMPUTER. Ordenador donde se ejecuta el objeto.
SPECIAL-NAMES. Cambiar valores para constantes del lenguaje, pueden variar
en cada compilador.
Como se aprecia en su sintaxis, ésta segunda division se divide a su vez en dos secciones, que
se describen a continuacion:
CONFIGURATION SECTION: Donde describimos los tipos de ordenadores en que
se escribio y se ejecutará el programa, o bien el nombre del compilador y
asignación de valores a ciertas constantes utilizadas por el compilador, estos
valores se introducen en sus respectivas lineas como se ve arriba.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
CURRENCY SIGN IS literal , suele ser un solo caracter y no puede coincidir con
ninguno de los que usamos para definir las variables, es decir ni A,ni Z,ni 9,ni -,ni
+,ni X, etc...
O hacer que todas las letras introducidas sean mayúsculas o minúsculas o que no
haya diferencias entre ambas con la clausula ALPHABET.
INPUT-OUTPUT SECION: Es la siguiente sección dentro de la Environment,
donde se especificarán todos los ficheros que vamos a utilizar, su tipo, su modo de
acceso asi como el medio en que estarán, esta sección solo será obligatoria cuando
vayamos a utilizar ficheros. Esta tiene dos párrafos FILE-CONTROL e I-O-
CONTROL.
123456789012
A B
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT Nombre-de-archivo
ASSIGN TO Tipo-de-dispositivo
ORGANIZATION IS Tipo de organizacion
ACCESS MODE IS Mode de acceso al fichero
RECORD KEY IS Clave del registro
ALTERNATE RECORD KEY IS Claves alternativas registro
WITH DUPLICATES
FILE STATUS IS Variable de estado del fichero.
Vamos a explicar cada una de las cláusulas que encontramos dentro de la Input-Output Section.
Cláusula SELECT es aqui donde especificamos el nombre lógico que va a tener el
fichero dentro del programa, suele ser una palabra que identifique lo mas claro
posible el contenido del fichero, por ejemplo ARTICULOS, PROVEEDORES,
CLIENTES.
Cláusula ALTERNATE RECORD KEY solo para ficheros indexados e identifican una
o mas claves alternadas para nuestros registros, por ejemplo en un fichero de
clientes cuya clave principal sería el código, podríamos assignar como clave
alternativa el NIF, y podríamos acceder a el por las dos claves, bien por código o
bien por NIF, será también alfanumérico y deberá también estar declarado en la
FD. Si aparece WITH DUPLICATES, indica que ésta clave alternativa pudiera estar
duplicada, por ejemplo si hubieramos escogido como clave alternada además del
NIF, el Nombre del cliente, podría darse el caso de que dos clientes tuvieran el
mismo nombre.
Ejemplo:
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. RMCOBOL.
OBJECT-COMPUTER. RMCOBOL.
SPECIAL-NAMES. DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CLIENTES ASSIGN TO RANDOM "C:\DATOS\
5
Nota final:
Creo que es una de las partes mas interesantes de la programación cobol y que
cuando he utilizado alguno de éstos nuevos lenguajes orientados a objetos y que
utilizan bases de datos, siempre he echado en falta. Para mi siempre es grato
dirigirme a la Environment de cualquier programa y saber con exactitud todos los
ficheros que se van a utilizar en ese programa.
Apreciar que para cada especificación de fichero en la Select solo se pone el punto
al final de todas las clausulas del párrafo.
En realidad haciendo ésto último podemos asignar cualquier archivo que esté en
cualquier dirección de la red, ya que el nombre que damos es lógico y su
asignación la podemos definir con una variable de entorno donde queramos.
DATA DIVISION.
DATA DIVISION. Es la tercera division por orden de aparición, y es donde se declaran
absolutamente todos los nombres de campos, registros, variables, es decir donde nombramos
cada dato que vayamos a utilizar en nuestro programa. Para almacenar todos estos nombres de
datos, ésta DIVISION se divide en varias secciones, cada una de ellas orientada a un tipo de
datos diferente.
FILE SECTION. Aqui describiremos todos los campos que componen los
registros de todos los archivos que vayamos a utilizar, que previamente
habremos declarado en la INPUT-OUTPUT SECTION dentro de la
ENVIRONMENT DIVISION.
Número de Nivel ...... Nombre de campo ...... PIC, VALUE, REDEFINES, OCCURS,
JUST, SIGN, SYNC.
A continuación pondremos el nombre del campo, que no podrá ser ninguna palabra
cobol ni llevar ningún carácter extraño, principalmente se utilizarán letras y
números o guiones. Es posible que algún campo que definamos nunca vaya a ser
usado por el programa pero si en cambio es necesario que exista para que nos
reserve el espacio, le llamaremos FILLER.
PICTURE / PIC esta palabra es la que utilizamos para identificar el tipo de datos
que va a contener la variable. Los posible valores son:
DE CAMPOS.
9 - Para campos numéricos.
A - Para campos alfabéticos.
X - Para campos alfanuméricos.
S - Indica variable con signo.
V - Indica punto decimal.
DE EDICIÓN.
$ - Representa la aparición del signo $ delante del campo numérico.
. - Indica separación de miles.
8
, - indica punto decimal. (estas dos pueden variar según hayamos
especificado en SPECIAL-NAMES DECIMAL-POINT IS COMMA).
Z - Representa un espacio para el 0 a la izquierda en campos
numéricos.
* - Igual pero se cambia el 0 por *.
B - Indica un espacio en blanco.
- ó + Indican la aparición del signo correspondiente.
Puede haber mas pero los mas utilizados son los que se han comentado.
Para indicar la longitud del campo se puede repetir el símbolo tantas veces como
longitud tenga o expresarla entre paréntesis, es decir para definir una variable
alfanumérica de 10 caracteres se pondría:
PIC X(10) o PIC XXXXXXXXXX. Los valores S y V solo pueden aparecer una vez por
cada variable.
A continuacion vamos a ver un ejemplo de todo lo que hemos explicado para que
se vaya quedando claro.
123456789012
A B
WORKING-STORAGE SECTION.
01 DOMICILIO.
02 TIPO PIC XX.
02 NOMBRE PIC X(20).
02 NUMERO PIC 9(4).
Fijaros que hemos definido 4 variables, la primera no tiene PIC, por que indica que
está subdividida en las 3 restantes. La segunda "TIPO" nos dice que es una
variable alfanúmerica y que puede contener 2 caracteres como máximo, la
utilizariamos para guardar el tipo de calle, avenida, paseo, plaza, etc.. Para la
tercera "NOMBRE" va a ser también alfanumérica pero con una longitud máxima
de 20 caracteres y nos servirá para guardar el nombre de la calle, plaza, avenida,
etc y la última "NUMERO" indica una variable numérica de 4 dígitos, que quiere
decir que puede contener valores entre 0 y 9999.
Observad que en Cobol no se guardan las varables numéricas por bytes como
ocurre con todos los lenguajes actuales sino por número de dígitos, con ello quizás
desaprovechamos mas la memoria pero en cambio tenemos un control mejor del
dato que puede contener nuestra variable.
Si TIPO fuera "AV", NOMBRE "DE LOS DESAMPARADOS " y NUMERO "15", si nos
refiriéramos a la variable DOMICILIO ésta tendría el siguiente valor:"AVDE LOS
DESAMPARADOS 0015".
VALUE esta palabra a continuación del PIC indica el valor inicial que contendrá la
variable hasta que éste sea modificado. Por ejemplo podemos definir una variable:
123456789012
A B
WORKING-STORAGE SECTION.
01 RAYA PIC X(10) VALUE "----------".
01 MINOMBRE PIC X(30) VALUE "ANDRES MONTES".
Asi tendremos una variable llamada RAYA que contiene 10 guiones y otra llamada
MINOMBRE que contiene eso, mi nombre, si os fijais con ésta cláusula convertimos
cualquier variable en una constante. En cualquier momento del programa
podremos cambiar ese valor. Para las variables numéricas es conveniente ponerlas
siempre con VALUE 0 para que al empezar cada programa estemos seguros de que
no nos arrastra ningún valor. Normalmente al ejecutar un programa se ponen
todas las variables a 0, pero si ese programa ha sido llamado desde otro no pasará
eso, por eso no viene mal inicializarlas todas a 0.
OCCURS esta cláusula es la que se utiliza para declarar tablas. Una tabla es un
conjunto de elementos con un mismo tipo y longitud que se denominan con el
mismo nombre y se diferencian por un subíndice. No se puede especificar en
niveles 01, 77 88. Puede tener varios formatos:
123456789012
A B
WORKING-STORAGE SECTION.
01 NUMERO-DIAS PIC 99.
01 TABLA.
02 DIA PIC XXX OCCURS 7 TIMES.
02 MES PIC 99 OCCURS 28 TO 31 DEPENDING NUMERO-DIAS.
02 OTRA PIC X(5) OCCURS 5 INDEXED BY IN-OTRA.
En la primera "DIA" indico que esa tabla va a tener 7 elementos que llamaremos
DIA (nn) y entre paréntesis el orden dentro de la tabla. Si hubiéramos guardado
en ésta tabla las 3 primeras letras de cada dia de la semana, para obtener el valor
del lunes pediriamos DIA (1), para el del Jueves DIA (4) y para el del domingo DIA
(7).
10
En la segunda "MES" le indicamos que los elementos de la tabla pueden variar
dependiendo del valor de la variable "NUMERO-DIAS" que ha de estar definida
antes de la tabla y siempre dentro de los márgenes de 28 y 31.
JUST la justificación de los valores de los campos suele ser a la izda. para los
alfanuméricos y a la derecha para los numéricos, si en cambio queremos cambiar
este orden tendremos que incluir ésta cláusula.
123456789012
A B
WORKING-STORAGE SECTION.
01 NOMBRE PIC X(10).
01 NOMBRE1 PIC X(10) JUST RIGHT.
Si le diéramos el mismo valor a las dos variables "ANDRES", la primera nos daría
"ANDRES " y la segunda " ANDRES", la diferencia, su justificación.
DISPLAY, es la forma por defecto e indica que cada dígito ocupará un byte,
es la que se toma por defecto y la que memoria ocupa.
Cuando el tamaño es impar el signo no ocupa ya que comparte byte con el último
dígito, el punto decimal tampoco ocupa espacio, ya que solo indica su posición.
Estas tres formas que he utilizado son las mas comunes, yo por ejemplo como las
capacidades de los ordenadores son tan grandes ahora, cuando defino las variables
en la WORKING nunca utilizo ninguna compactación es decir no utilizo la cláusula
USAGE (que por cierto y como habreis visto se puede omitir) y por defecto toma
DISPLAY (un byte por caracter), en cambio cuando trabajo con campos de registro
de ficheros si me gusta compactar lo máximo para que el tamaño de los archivos
no se dispare.
11
LINKAGE SECTION. En ésta sección se declaran las variables de igual forma solo
que las que aqui declaremos nos van a servir de enlace para pasar información a
otro programa que será llamado por el principal.
Ejemplo:
DATA DIVISION.
FILE SECTION.
FD CLIENTES BLOCK CONTAINS 4 RECORDS
RECORD CONTAINS 128 CHARACTERS
LABEL RECORD STANDARD.
01 REG-CLIENTE.
02 KEY-CLIENTE.
r 03 CLICOD rPIC 9(4) COMP-6.
02 CLINOM PIC X(30).
02 CLIDIR PIC X(30).
02 CLIPOB PIC X(20).
02 CLIPRO PIC X(20).
02 CLINIF PIC X(9).
02 FILLER PIC X(17).
Como veis he diseñado el fichero CLIENTES para que cada bloque de 512
Kb, ocupe 4 registros, dejando 17 caracteres (FILLER), para una posible
ampliación del registro.
En la descripción del archivo IMPRESORA se declara una variable a nivel
01 que hace referencia al total del registro para luego ir moviendo a éste
campo el valor de lo que queramos imprimir.
Nota final:
La DATA DIVISION nos sirve para tener todas nuestras variables bien definidas, ya
sean independientes o que formen parte de algún fichero para poder operar con
ellas en la PROCEDURE DIVISION. Me acuerdo de cuando empezamos a estudiar
que para otros lenguajes no era necesaria la declaración de variables previamente
y en cambio ahora en la mayoría de los lenguajes se exige que se declaren, eso
significa que el Cobol no iba mal encaminado.
Tenemos que tener siempre muy claro que con cualquier campo podemos hacer lo
que queramos, por ejemplo si en un registro de 120 caracteres nosotros en un
12
programa solo vamos a utilizar los 40 primeros podemos definir todo lo restante
como un campo FILLER y listo o viceversa si un campo de un registro lo tenemos
definido como alfanumérico de 30 en un programa necesitamos los 10 primeros
caracteres por un lado y los veinte restantes por otro, puese nada se subdivide
para ese programa y no pasa nada.
Espero que haya quedado por lo menos medio clara la explicación de ésta tercera
DIVISION, evidentemente con la práctica es con lo que mas vamos a aprender
siempre claro está que tengamos al menos unas nociones mínimas.
Tenemos que tener en cuenta que como en todos los lenguajes, ya sean de
programación o de habla (español, inglés, frances) son muchas las opciones que
nos ofrecen pero al final siempre utilizamos las que mas nos gustan o las que
consideramos mas útiles.
Una cosa que considero importante es dar a las variables un nombre un poco
lógico que nos recuerde su contenido, por ejemplo si queremos guardar la fecha,
pues llamarla FECHA, si queremos guardar el N.I.F. del gerente, NIFGEREN, etc ...
PROCEDURE DIVISION.
PROCEDURE DIVISION. Bien, hemos llegado a la última división que existe un los programas
Cobol, en ella encontramos todos los procesos necesarios para que el programa funcione, que
haga para la que fue concebido.
Todo ésto se realiza con instrucciones (ordenes, verbos, comandos, etc..), como explicaremos a
continuación. Cada uno de ellos con un formato y una solución que resolver.
Como son muchos los verbos de que se compone el lenguaje, vamos a ver éstos divididos por
grupos: De cálculo, De archivos, De pantalla, Resto.
Ya sabemos que Cobol es un lenguaje estructurado, pues bien no pensemos que la Procedure va
a ser un caos de instrucciones escritas secuencialmente, no, en ella podremos definir tantas
Secciones (SECTION) y Párrafos como queramos para organizar mejor las instrucciones y para
delimitar acciones concretas, eso si siempre se ejecutarán secuencialmente, excepto cuando
encuentre algún verbo de bifurcación como GO, PERFORM que haciendo referencia a esos
nombres de párrafo harán que se rompa la secuencia lógica de ejecución.
Tambien podemos utilizar para las condiciones complejas los operandos lógicos, AND, OR y NOT
según se requieran, todas las condicionea que incluyan AND han de ser correctas para que pase
la condición, si se utiliza OR solo alguna de ellas ha de ser correcta, cuando se utilice NOT no
podrá ser correcta para que la condición sea válida.
PROCEDURE DIVISION
INSTRUCCIONES DE CALCULO. Debido a que el lenguaje Cobol fue concebido para la gestión
de grandes cantidades de datos y a resolver problemas de tipo comercial y de administración, no
se incluyeron dentro de sus especificaciones verbos que nos puedieran ayudar a resolver cálculos
complejos como integrales, trigonometría, raices cuadradas, etc..., sino simplemente las
orientadas a los cálculos básicos, suma, resta, multiplicación y división que son las que vamos a
ver a continuación:
14
add, subtract, multiply, divide, compute.
ADD, ésta es la instrucción que utilizaremos para realizar sumas y tiene los siguientes formatos:
1.- ADD variable ó literal variable ó literal ... TO variable (ROUNDED) (ON SIZE
ERROR) instrucción
2.- ADD variable ó literal variable ó literal ... GIVING variable (ROUNDED) (ON
SIZE ERROR) instrucción
3.- ADD CORR variable TO variable (ROUNDED) (ON SIZE ERROR) instrucción
Para ver las explicaciones de cada uno de los formatos partiremos de la misma WORKING, y a
continuación pondremos un ejemplo y su explicación.
...
WORKING-STORAGE SECTION.
01 VALORES.
02 UNO PIC 99 VALUE 10.
02 DOS PIC 9(6) VALUE 280.
02 TRES PIC 9(4) VALUE 540.
01 OTROS
02 OTRO1 PIC 9.
02 DOS PIC 9(6) VALUE 110.
01 RESULTADO PIC S9(8) VALUE 10.
01 RESTO PIC 99.
PROCEDURE DIVISION.
INICIO.
Formato 1:
ADD UNO TRES 5 TO RESULTADO.
Se sumarán todas las variables o literales numéricos (cifras) al valor de la
variable que se de a continuación del TO, guardandose el resultado también
en ésta última.
Por tanto al realizar ésta operación el valor de la variable RESULTADO, será
de: 10 (de la variable UNO) + 540 (de la variable TRES) + 5 + 10 (de
Resultado) = 565.
Como veis UNO + TRES + 5 suman 555 pero ésto se suma al valor que ya
tenía la variable RESULTADO, con lo que la suma total es de 565.
Este formato se usa mucho para hacer de contador y hacer que una varable
aumente en uno su valor poniendo:
ADD 1 TO RESULTADO.
Formato 2:
ADD UNO TRES 5 GIVING RESULTADO.
Formato 3:
ADD CORR VALORES TO OTROS.
Con éste formato conseguimos que las variables del campo compuesto
VALORES se sumen al valor de las variables con el mismo nombre del
campo compuesto OTROS, obteniendo como resultado: 280 (de la variable
DOS del campo VALORES) + 110 (de la variable DOS del campo OTROS) =
15
390.
Si hubiera coincidido alguna variable mas con el mismo nombre en ambos
campos también se hubiese sumado.
SUBTRACT, ésta es la instrucción que utilizaremos para realizar restas y tiene los siguientes
formatos:
1.- SUBTRACT variable ó literal variable ó literal ... FROM variable (ROUNDED)
(ON SIZE ERROR) instrucción
2.- SUBTRACT variable ó literal variable ó literal ... FROM variable ó literal
GIVING variable (ROUNDED) (ON SIZE ERROR) instrucción
3.- SUBTRACT CORR variable FROM variable (ROUNDED) (ON SIZE ERROR)
instrucción
Para ver las explicaciones de cada uno de los formatos partiremos de la misma WORKING que
hemos utilizado con la instrucción ADD, poniendo a continuación un ejemplo y su explicación.
Formato 1:
SUBTRACT UNO TRES 5 FROM RESULTADO.
Formato 2:
SUBTRACT UNO 5 FROM TRES GIVING RESULTADO.
Formato 3:
SUBTRACT CORR VALORES FROM OTROS.
Al igual que con la instrucción ADD, con éste formato conseguimos que las
variables del campo compuesto VALORES se resten al valor de las variables
16
con el mismo nombre del campo compuesto OTROS, obteniendo como
resultado: 280 (de la variable DOS del campo VALORES) - 110 (de la
variable DOS del campo OTROS) = 170.
Si hubiera coincidido alguna variable mas con el mismo nombre en ambos
campos también se hubiese restado.
Nota: Tened en cuenta que al utilizar restas el signo puede ser negativo y si
no tenemos bien declarada la variable que va a contener el resultado, ésta
cojerá su valor absoluto.
MULTIPLY, ésta es la instrucción que utilizaremos para realizar multiplicaciones y tiene los
siguientes formatos:
1.- MULTIPLY variable ó literal BY variable (ROUNDED) (ON SIZE ERROR)
instrucción
Formato 1:
MULTIPLY 5 FROM RESULTADO.
Formato 2:
MULTIPLY 5 BY TRES GIVING RESULTADO.
DIVIDE, ésta es la instrucción que utilizaremos para realizar divisiones y tiene los siguientes
formatos:
1.- DIVIDE variable ó literal INTO variable (ROUNDED) (ON SIZE ERROR)
instrucción
2.- DIVIDE variable ó literal (BY ó INTO) variable ó literal GIVING variable
(ROUNDED) (REMAINDER) variable (ON SIZE ERROR) instrucción
Utilizando la misma WORKING que hemos utilizado con las instrucciones ADD y SUBTRACT,
veremos a continuación unos ejemplos y su explicación.
Formato 1:
DIVIDE 10 INTO TRES.
Formato 2:
DIVIDE 7 INTO TRES GIVING RESULTADO REMAINDER RESTO.
17
Aquí dividiremos el valor del la variable TRES entre 7 guardando el
resultado en la variable RESULTADO, sin tener en cuenta su valor inicial, y
además el resto de la operación lo guardará en la variable RESTO,
quedando así: 540 / 7 = 77, pero como 7 x 77 son 539 el resto es 1 que
será el valor de RESTO.
Si en vez de utilizar INTO utilizamos BY cambia el orden de los operandos,
es decir en vez de dividir TRES entre 7 dividiríamos 7 entre TRES.
COMPUTE, con ésta orden podemos realizar todos los cálculos aritméticos posibles en una sola
instrucción, utilizando los operadores +(suma) -(resta) *(multiplicación) /(división)
**(potenciación), además de utilizar paréntesis para especificar mejor la operación a realizar.
1.- COMPUTE variable (ROUNDED) = expresión aritmética (ON SIZE ERROR)
instrucción
Utilizando la misma WORKING que hemos utilizado anteriormente vamos a ver un ejemplo:
Formato 1:
COMPUTE RESULTADO = DOS OF VALORES * 16 / 100.
COMPUTE RESULTADO = 2 + 3 * 5.
Para todas éstas instrucciones de cálculo que hemos visto la opcion ROUNDED significa lo mismo
y quiere decir que fuerza al redondeo del resultado para cada operación y siempre teniendo en
cuenta la definición de la variable que va a guardar ese resultado, por ejemplo si tras una
operación resulta 18,76 éste podría quedar como sigue:
77 RESULTADO PIC 99V99. (valor = 18,76)
77 RESULTADO PIC 99V9. (valor sin redondeo = 18,7 - valor con redondeo
= 18,8)
PROCEDURE DIVISION
INSTRUCCIONES DE ARCHIVOS. Sin duda son las instrucciones mas importantes con las que
cuenta el lenguaje Cobol, con ellas tendremos la oportunidad de manipular toda la información
contenida en nuestros archivos, es decir, podremos abrir archivos, cerrarlos, leerlos, guardar
información nueva o modificar datos existentes. Todo ésto lo haremos con las instrucciones que
voy a explicar a continuación:
Antes de empezar a explicar éstas instrucciones me gustaría que entendiéseis bien algunos
conceptos como fichero, registro y campo, para que podais comprender mas claramente, la
explicación de todas las instrucciones que se verán en ésta sección.
¿Que es una clave? Una clave, es un campo de nuestra agenda que nos sirve para
identificar a cada amigo, en la agenda normal la clave podría ser la lengüeta con la letra
del abecedario correspondiente a los apellidos del amigo. Informáticamente es mas
completa y con ella podremos identificar a cada uno de ellos, por ejemplo con su nombre
o su teléfono o un código que le asignemos nosotros personalmente.
Ahora quizás entendais mejor el resto, si veo alguna aclaración necesaria, ampliaré este párrafo.
OPEN, ésta es la instrucción que utilizaremos para abrir un archivo, o lo que es lo mismo hacerlo
disponible para operar sobre el, obviamente éste archivo debe de haberse descrito en la
Environment y la Data según se explicó, su formato es el siguiente:
OPEN (EXCLUSIVE) modo nombre de archivo (WITH LOCK) (WITH NO
REWIND)
Donde modo, indica como se abrirá el archivo y puede tener los siguientes valores según su
utilización:
INPUT, el archivo se abrirá solo para lectura, es decir no podremos grabar
ni modificar datos del mismo.
Nota: Con éstas tres instrucciones estamos abriendo tres archivos, cada
uno de una forma diferente. Tambien podriamos haberlos puesto en una
sola linea de la siguiente forma:
OPEN INPUT ARTICULOS I-O CLIENTES EXTEND IMPRE.
CLOSE, ésta es la instrucción contraria a OPEN, es decir termina la conexión establecida con el
archivo, a partir del momento que aparezca ésta instrucción el archivo no estará disponible para
operar con él, hasta la próxima vez que se abra. Obviamente antes de cerrarlo debe de estar
abierto.
CLOSE nombre de archivo (WITH LOCK) (WITH NO REWIND)
El nombre de archivo corresponderá a algún archivo abierto anteriormente.
Las opciones WITH LOCK y WITH NO REWIND, tienen la misma explicación que la vista en la
orden OPEN.
...
PROCEDURE DIVISION.
INICIO.
OPEN INPUT ARTICULOS.
OPEN I-O CLIENTES
OPEN EXTEND IMPRE.
...
...
...
CERRAR.
CLOSE ARTICULOS CLIENTES IMPRE.
...
READ, es la instrucción que utilizamos para leer registros de un archivo, debe de estar abierto.
Con ella conseguimos que los datos referentes al registro accedido queden en la descripción de
20
dicho fichero, es decir, conseguimos que los campos declarados en la FD, tengan el valor
correspondiente al registro leido.
La sentencia READ, se utiliza para leer ficheros secuanciales o indexados, o para leer indexados
de manera secuencial, por lo que su sintaxis tiene dos formatos principales.
Formato para leer ficheros de manera secuncial. (Indexados o secuenciales)
READ nombre de archivo (NEXT/PREVIOUS RECORD) (INTO descripción) (AT
END / NO AT END sentencia) END-READ
La opción INTO, indica cual de las descripciones de registro que hayamos podido
declarar será la que almacene los datos del registro leido. Tenemos que tener en
cuenta que Cobol nos permite mantener mas de una descripción de registro para
un mismo archivo. Si tuvieramos mas de una, ésta sería la opción para indicarle
cual es la que queremos utilizar en ésta lectura.
Nota: Si bien este formato nos sirve para leer cualquier tipo de archivo de
manera secuencial, en el caso de que el archivo fuera secuencial, éste solo
se podría leer así.
Existen muchas ocasiones en que un archivo indexado nos interesa leerlo de
manera secuencial. Si lo hicieramos éste sería su formato, además en éste
caso podriamos leerlo tanto del principio al final con la opción NEXT, como
del final al principio con la opción PREVIOUS.
Las opciones que se repiten con con el formato anterior tienen el mismo formtato y
producen el mismo resultado.
21
La opción KEY, indica por que clave se va a leer el fichero, siempre que éste tenga
mas de una.
La sentencia después de INVALID KEY se utiliza para ejecutar una acción cuando
se intenta acceder a un registro que no existe. En el caso de utilizar NOT INVALID
KEY sería al contrario, es decir cuando el registro existe.
...
PROCEDURE DIVISION.
INICIO.
OPEN INPUT ARTICULOS.
LECTURA.
MOVE 100 TO CLAVE-ARTICULO.
READ ARTICULOS INVALID KEY GO ERROR.
...
...
...
GO LECTURA.
ERROR.
...
...
CERRAR.
CLOSE ARTICULOS.
...
Nota: Sin duda la forma mas usual de acceder a un registro será por su
clave. Asi por ejemplo para acceder a un fichero de poblaciones cuya clave
fuera su código postal, dando cualquier código accederiamos a ese registro
en concreto.
La acción que hagamos después de un INVALID KEY, dependerá del
contexto en que se encuentre, podremos volver a solicitar otra clave,
permitir crear un registro, etc ..
WRITE, con ésta instrucción se consigue grabar la información contenida en ese momento en los
campos del registro de un fichero. Es decir, si introducimos una ficha nueva en la agenda con los
datos de un nuevo amigo, ésta instrucción será la que nos sirva para almacenar en el fichero los
datos. A partir de ese momento estarán disponibles tantas veces como queramos para leerla. Y
por supuesto el fichero debe de estar abierto como OUTPUT o I-O.
WRITE nombre de registro (FROM descripción) (INVALID KEY / NOT INVALID
KEY sentencia)
END-WRITE
La opción FROM, indica con cual de las descripciones de registro que hayamos
podido declarar se graben los datos en el fichero. Hay que señalar que ésta
descripción puede estar definida en la WORKING, y lo que nos ahorra en realidad
es mover los datos de esa descripción que hemos usado como "temporal" a la
auténtica descripción del registro.
Las cláusulas de INVALID KEY y NOT INVALID KEY, tienen la misma función dada
en la instrucción READ. Solo que aqui, INVALID KEY, se produciría cuando al
grabar el registro, éste ya existiese o hubiera algún error por el cual no se
pudieran grabar los datos.
...
PROCEDURE DIVISION.
INICIO.
OPEN I-O ARTICULOS.
LECTURA.
MOVE 100 TO CLAVE-ARTICULO.
MOVE "ANDRES MONTES" TO NOMBRE.
22
WRITE REGISTRO-ARTICULO INVALID KEY GO ERROR.
...
...
GO CERRAR.
ERROR.
...
...
CERRAR.
CLOSE ARTICULOS.
...
Además de éste formato, existe para ésta instrucción otro muy común. Y es el que utilizamos
para enviar datos a la impresora, es decir para listar, para imprimir.
Es en éste caso, donde se hace indispensable el uso de mas de una descripción por registro.
¿Porque? Sencillo, definiremos nuestro fichero con un registro de tamaño igual al ancho de
nuestro listado, y luego en la WORKING, describiremos el formato de cada una de las lineas que
utilizaremos en la impresión. Quiero hacer un ejemplo mas extenso para éste caso, que será
muy utilizado y distinto en su filosofía al resto.
WRITE nombre de registro (FROM descripción) (AFTER número de lineas)(PAGE)
END-WRITE
Nota: Como podeis ver, hemos definido el registro como REG-IMPRE, pero
al escribir sobre el fichero impresora utilizamos las descripciones de LINEA1
y LINEA2, de ésta manera conseguimos que se impriman las dos lineas en
una impresora conectado al puerto LPT1 y que antes de escribir la primera
linea, salte a una página en blanco.
REWRITE, ésta instrucción se utiliza para regrabar datos de un registro ya existente. Toda la
sintaxis es exactamente igual que la explicada en WRITE.
REWRITE nombre de registro (FROM descripción) (INVALID KEY / NOT
INVALID KEY sentencia) END-REWRITE
Todas las opciones igual que en WRITE. Por lo que en el ejemplo vamos a ver
ambos casos juntos.
...
PROCEDURE DIVISION.
INICIO.
OPEN I-O ARTICULOS.
LECTURA.
MOVE 100 TO CLAVE-ARTICULO.
MOVE "ANDRES MONTES" TO NOMBRE.
WRITE REGISTRO-ARTICULO INVALID KEY GO ERROR.
MOVE "OTRO NOMBRE" TO NOMBRE.
REWRITE REGISTRO-ARTICULO INVALID KEY GO ERROR.
...
...
GO CERRAR.
ERROR.
...
...
CERRAR.
CLOSE ARTICULOS.
...
DELETE, instrucción para borrar un registro de un fichero. La explicación es corta, pero tiene
pocos mas matices, lo que conseguimos es borrar todos los datos de un registro. Su sintaxix es
la siguiente:
DELETE nombre de fichero (INVALID KEY / NOT INVALID KEY sentencia)
END-DELETE
Las únicas cláusulas INVALID y NOT INVALID KEY, se usan exactamente igual que
en las demás relativas a ficheros, es decir ejecutará la sentencia que pongamos a
continuación cuando una de las condiciones se cumpla, que la clave exista o que
no exista.
24
Si nos fijamos vemos que la gran diferencia está en que aquí la orden hace
referencia al nombre del fichero y no al del registro, como en las instrucciones
anteriores.
...
PROCEDURE DIVISION.
INICIO.
OPEN I-O ARTICULOS.
LECTURA.
MOVE 100 TO CLAVE-ARTICULO.
READ ARTICULOS INVALID KEY GO ERROR.
DELETE ARTICULOS INVALID KEY GO ERROR.
...
...
GO CERRAR.
ERROR.
...
...
CERRAR.
CLOSE ARTICULOS.
...
...
Nota: Obviamente para borrar un registro, primero hemos de tenerlo en
memoria, por eso en el ejemplo lo he leido primero.
START, ésta instrucción es de suma importancia en el tratamiento de ficheros, y nos sirve para
posicionarnos en cualquier parte del mismo, para una lectura mas rápida. Si imaginamos un
fichero con 10.000 clientes, clasificados por código, para ver todos los que cuyo código es mayor
a 9.000, tendríamos que leernos el fichero secuencialmente hasta llegar al sitio correcto, en
cambio con ésta orden, podremos colocarnos en la posición del fichero que queramos dentro de
unas normas, que veremos a continuación.
START nombre de fichero KEY (expresión) nombre de clave (INVALID KEY /
NOT INVALID KEY sentencia) END-START
Las únicas cláusulas INVALID y NOT INVALID KEY, se usan exactamente igual que
en las demás relativas a ficheros, es decir ejecutará la sentencia que pongamos a
continuación cuando una de las condiciones se cumpla, que la clave exista o que
no exista.
Si nos fijamos vemos que la gran diferencia está en que aquí la orden hace
referencia al nombre del fichero y no al del registro, como en las instrucciones
anteriores.
RESUMIENDO
En la programación estructurada es conveniente sustituir el punto como final de una instrucción
por la cláusula END-....... para cada instrucción. De esta manera conservamos la estructura y no
obligamos con el punto a finalizar ninguna instrucción o bucle en el que estemos metidos.
Una vez vistas todas las intrucciones relativas a ficheros, quiero dejar bien claro su utilización.
Tendremos siempre en cuenta que cuando leemos, realmente le damos el valor del registro que
hemos leido a los campos o variables que lo componen. Que cuando grabamos o regrabamos, le
estamos dando el valor de las variables en ese momento al registro para que se grabe en disco y
cuando borramos, estamos quitando fisicamente del disco esa información.
PROCEDURE DIVISION
INSTRUCCIONES DE PANTALLA Y MOVIMIENTO. Sin duda alguna e independientemente del
lenguaje de programación escogido, las instrucciones que mas se suelen utilizar, serán las que
hagan uso de la pantalla, ya sea como salida o entrada de información.
Vamos a utilizar ésta sección para hacer un análisis profundo de dichas instrucciones.
accept, display.
ACCEPT, es la instrucción que usaremos para la entrada de datos. Aunque su sintaxis principal
nunca ha variado, ésta ha sido una de las instrucciones que mas cláusulas se le han ido
añadiendo, incluso diferentes según el compilador, aquí vamos a explicar las comunes y
principales.
26
Aunque la forma mas usual de utilizarla, es para aceptar datos por el teclado, también es posible
utilizarla para "cogerlos" también del sistema, para aceptar valores de variables de entorno
definidas previamente a nivel de sistema o para aceptar pantallas completas definidas en la
SCREEN-SECTION. Además siguen aumentando sus posibilidades. Veamos sus formatos
principales:
DAY, devuelve el año y el día del año en que estamos con el formato
AADDD, siendo el valor 1, para el 1 de Enero y así sucesivamente. Debe de
estar definida con PIC 9(5).
CENTURY-DAY, igual que DAY, pero acepta 4 dígitos para el año, quedando
el formato AAAADDD. Definir con PIC 9(7).
UPPER, LOWER, (ACCEPT) con éstas opciones obligamos a que el valor del
campo aceptado esté en Mayúsculas (UPPER) o Minúsculas (LOWER).
...
DISPLAY, es la instrucción que usaremos como salida de datos en pantalla. Con ella
mostraremos cualquier texto, cualquier variable, cualquier constante o cualquier valor, en
resumidas es la instrucción para que aparezca lo que sea en pantalla. Las cláusulas asociadas a
esta instrucción son practicamente las mismas que hemos visto para ACCEPT, con lo que solo las
indicaré, su explicación la obtendréis arriba. De todas maneras ésta instrucción está siendo
implementada en muchos mas campos, por determinados compiladores y no sería justo pensar
que su única función es la que voy a explicar aquí, lo que si es cierto es que ésta es la común a
todos los compiladores. Mas abajo hablaré un poco de todo esto que os digo y de su futuro.
DISPLAY variable, literal CLAUSULAS ...
LINE, COL, SIZE, HIGH, LOW, REVERSE, BEEP, BLINK, ERASE. Todos
funcionana igual que con la sentencia ACCEPT.
TIPOS DE CONTROL. Además de los vistos en ACCEPT, en DISPLAY podemos
utilizar otros:
CONTROL "FCOLOR=color, .............".
FCOLOR, igual que en ACCEPT.
...
Nota: Una cosa a tener en cuenta tanto con FCOLOR, como con BCOLOR,
es que los colores que tomen seguirán activos hasta encontrar otra orden
que los cambie, por eso al comenzar con esa primera linea conseguimos
31
que toda la pantalla se muestre blanca y el texto en azul para todo el
programa, hasta que se encuentre el compilador con otra linea que lo
cambie. O sea que no será necesario seguir incluyendo la cláusula
CONTROL, en todos los ACCEPT y DISPLAY que vayamos a utilizar mientras
queramos mantener éste formato.
Otros formatos de DISPLAY:
DISPLAY nombre de pantalla CLAUSULAS ..., podemos mostrar una pantalla
completa que previamente hayamos definido en la SCREEN SECTION.
PROCEDURE DIVISION
INSTRUCCIONES DE MOVIMIENTO DE VARIABLES.
Daré cabida en esta sección a la explicación de todas las instrucciones que hacen referencia a las
variables y sus valores. Como todas, este grupo de instrucciones tiene su vital importancia en la
programación y son usadas habitualmente.
MOVE, es la instrucción que usaremos para enviar datos de una variable a otra u otras.
Lo que en realidad hace es que la una variable adquiera un valor determinado, ya sea procedente
de otra variable o bien desde un valor fijo o constante.
TEXTO1=LENGUAJE COBOL
TEXTO2=LENGUAJE C
TEXTO3= LENGUAJE COBOL
Formato 2:
MOVE CORR Identificador1 TO Identificador2
No es necesario que tengan el mismo PIC, ni que estén en el mismo orden, solo
que coincidan en su nombre.
...
33
WORKING-STORAGE SECTION.
01 DATOS1.
02 NOMBRE PIC X(30).
02 REGION PIC X(20).
02 PAIS PIC X(15).
01 DATOS2.
02 PAIS PIC X(10).
02 REGION PIC X(10).
02 NOMBRE PIC X(10).
...
PROCEDURE DIVISION.
INICIO.
MOVE "ANDRES MONTES" TO NOMBRE IN DATOS1.
MOVE "ANDALUCIA" TO REGION IN DATOS1.
MOVE "ESPAÑA" TO PAIS IN DATOS1.
MOVE CORR DATOS1 TO DATOS2.
...
Nota: Para partir con unos valores, primero los he movido a las variables del
primer grupo (DATOS1). Después de aplicar el MOVE CORR, el valor de las
variables de DATOS2 sería:
DATOS2:
PAIS=ESPAÑA
REGION=ANDALUCIA
NOMBRE=ANDRES MON
INITIALIZE, se utiliza para inicializar variables según su descripción, es decir pondrá a ceros
todas las variables numéricas o de edición y a espacios en blanco las alfabéticas y alfanuméricas.
No funciona con campos definidos como FILLER, (evidente). Y puede ser muy útil para inicializar
tablas completamente cuando nos referimos al nivel mas alto de la misma.
...
WORKING-STORAGE SECTION.
77 TEXTO PIC X(10) VALUE "HOLA MUNDO".
77 NUMERO PIC 9(8) VALUE "12345678".
...
PROCEDURE DIVISION.
INICIO.
INITIALIZE TEXTO NUMERO.
...
INSPECT, esta sentencia se utiliza para contar, reemplazar o contar y reemplazar caracteres o
grupos de caracteres dentro de un campo. Se puede contar las veces que aparece un caracter, o
cambiar todos esos caracteres por otros, etc ...
34
Esta instrucción tiene formatos diferentes según lo que se desee hacer, así que vamos a ver cada
uno de ellos por separado.
Formato 1:
INSPECT campo1
TALLYING variable1 FOR (CHARACTERS)
((BEFORE/AFTER) INITIAL) Cadena1
(ALL)(LEADING) Cadena2 ...
(Se puede repetir de nuevo)
CHARACTERS indica que cuente todos los caracteres del campo incluso los
espacios en blanco.
ALL indica que tiene que buscar en todos los caracteres del campo, la
cadena especificada en Cadena2.
Formato 2:
INSPECT campo1
REPLACING variable1 CHARACTERS BY Cambio1
((BEFORE/AFTER) INITIAL) Cadena1
(ALL)(LEADING)(FIRST) Cadena2 ...
(Se puede repetir de nuevo)
Formato 3:
INSPECT campo1
CONVERTING Identificador1 TO Identificador2
36
((BEFORE/AFTER) INITIAL) Cadena1 ...
(Se puede repetir de nuevo)
Veamos algunos ejemplos, se suele utilizar mucho para que al aceptar un campo
nos de igual se ha sido introducido en mayúsculas o en minúsculas ya que lo
convertiriamos a alguno de los formatos.
...
WORKING-STORAGE SECTION.
77 TEXTO PIC X(15) VALUE "PAGINA DE COBOL".
...
PROCEDURE DIVISION.
INICIO.
INSPECT TEXTO CONVERTING "AO" TO "12".
...
El valor de TEXTO será "P1GIN1 DE C2B2L", convertirá todas las A por 1 y
todas las O por 2.
INSPECT TEXTO CONVERTING
"ABCDEFGHIJKLMNÑOPQRSTUVWXYZ" TO
"abcdefghijklmnñopqrstuvwxyz".
...
El valor de TEXTO será "pagina de cobol" ya que ha convertido todas las
letras mayúsculas por minúsculas.
Para finalizar con el comando INSPECT, decir que es un comando muy particular y cada uno
deberá decidir en cada momento y con que situaciones utilizarlo.
STRING, se utiliza para unir o concatenar campos o partes de estos y el resultado almacenarlo
en otro campo. En la unión se pueden incluir tanto variables como literales o constantes de
texto.
STRING campo1, literal1
DELIMITED BY (campo2, literal2)(SIZE)
INTO Campo3
(WITH POINTER Identificador1)
(ON OVERFLOW Sentencia1)
(NOT ON OVERFLOW Sentencia2)
DELIMITED BY, indica hasta donde vamos a "coger" del campo para concatenar sin contar
ese caracter o cadena que se especifique en campo2 o literal2, es decir si tenemos un
campo con un valor = "HOLA" y especificamos DELIMITED BY "L" a la hora de la
concatenación nos hubiera cogido solo el HO, ya que al encontrarse la primera L hubiera
parado.
SIZE, indica que se pasará todo el contenido del campo1 o literal1 sin limitaciones.
UNSTRING, hace exactamente lo contrario de que hemos visto que hacía STRING, es decir
divide el contenido de un campo en otros.
UNSTRING campo1, literal1
DELIMITED BY (campo2, literal2)(ALL)
OR (campo2, literal2)(ALL)
(Se puede repetir de nuevo)
INTO Campo3, Campo4, ....
(DELIMITER Identificador1)
(COUNT Identificador2)
(Se puede repetir de nuevo)
(WITH POINTER Identificador3)
(TALLYING Identificador4)
(ON OVERFLOW Sentencia1)
(NOT ON OVERFLOW Sentencia2)
DELIMITED BY, indica el límite hasta donde vamos cogiendo el campo1 para partirlo. Igual
que en STRING, solo que con la función a la inversa.
OR es igual que DELIMITED y se utiliza si hay varios delimitadores sobre los que buscar.
INTO indica en que campo o campos se guardará la información que vaya fragmentando.
POINTER indica desde que posición va a ser examinado el campo que desea
desfragmentar, por defecto su valor es 1, es decir desde el primer caracter.
TEXTO2 = ES
TEXTO3 = DE
TEXTO4 = DE
ELMES = JUNIO
DIA = 22
ANIO = 2001
FECHA = 22062001
LETRAS = 5
PALABRAS = 7
La variable PALABRAS nos ha guardado el número de variables utilizadas en la
fragmentación, en este caso 7. La variable LETRAS ha guardado el número de caracteres
que ha cogido en la separación que ha guardado en ELMES, que han sido 5 (JUNIO).
Podiamos haber puesto un COUNT para cada una.
El PERFORM de después lo hemos hecho para encontrar en la tabla la posición que
ocupaba el nombre del mes y así poder construir la variable FECHA completa en
númerico.
Vamos a hacer un ejemplo de como podríamos separar un nombre completo, por ejemplo para el
nuevo modelo de la Seguridad Social (en España) y el sistema R.E.D.:
...
WORKING-STORAGE SECTION.
01 TEXTO PIC X(30) VALUE "MONTES ROBLES, ANDRES".
01 APELLI1 PIC X(20).
01 APELLI2 PIC X(20).
01 NOMBRE PIC X(20).
01 SEPARA PIC X.
01 SEGURIDAD.
02 AP1 PIC XX.
02 AP2 PIC XX.
40
02 NOM PIC X.
...
PROCEDURE DIVISION.
INICIO.
UNSTRING TEXTO DELIMITED BY " " OR ", "
INTO APELLI1 APELLI2 NOMBRE.
Aquí conseguimos separar cada apellido y el nombre en campos diferentes.
(APELLI1, APELLI2, NOMBRE)
PROCEDURE DIVISION
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: 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_parrafo UNTIL 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.
...
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.
43
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
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.
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.