Sunteți pe pagina 1din 62

Módulo Cobol Avanzado

COBOL AVANZADO
Contenido
1. OBJETIVO DEL CURSO
1.1. Objetivo.................................................................................................................
1.2. Alcance..................................................................................................................
1.3. Prerequisitos.........................................................................................................
1.4. Duración................................................................................................................
2. TEMAS
2.1. Usos de la Environment Division...........................................................................
2.2. Construcciones de Programación Estructurada....................................................
2.2.1. Estructura CASE............................................................................................
2.2.2. IF anidados.....................................................................................................
2.2.3. WHILE-DO.....................................................................................................
2.2.4. REPEAT-UNTIL..............................................................................................
2.2.5. FOR-DO.........................................................................................................
2.3. COPY-REPLACING...............................................................................................
2.4. Nuevas instrucciones de estándar ANSI-85..........................................................
2.4.1. INITIALIZE......................................................................................................
2.4.2. EVALUATE.....................................................................................................
2.4.3. Finales de instrucción explícitos (END-IF, END-PERFORM, etc.).................
2.5. Declaraciones de Datos "complicadas".................................................................
2.5.1. Niveles 88 y 77...............................................................................................
2.5.2. Manejo de tablas............................................................................................
2.5.3. Representación interna de datos....................................................................
2.5.4. REDEFINES y RENAMES.............................................................................
2.6. SORT y MERGE....................................................................................................
2.6.1. Dectaración de archivos y formato de instrucciones......................................
2.6.2. Especificación del criterio de ordenamiento...................................................
2.6.3. Input y Output Procedure...............................................................................
2.6.4. RELEASE.......................................................................................................
2.6.5. Registros especiales para el SORT................................................................
2.7. Subprogramas.......................................................................................................
2.7.1. Transferencia de control a otro programa.......................................................
2.7.2. Programas anidados.......................................................................................
2.7.3. Parámetros por referencia y por contenido....................................................
3. PRÁCTICAS
3.1. Ejercicio 1..............................................................................................................
4. EVALUACIÓN Y REFERENCIAS
4.1. Evaluación.............................................................................................................
4.2. Referencias...........................................................................................................

COBOL AVANZADO -i- Página i de 64


1. Objetivo del Curso

1.1. Objetivo
Dominar declaraciones de datos complicadas como instrucciones de sort y
transferencia de control a otros programas

1.2. Alcance
Instrucciones de Cobol-II

1.3. Prerequisitos
Haber tomado el curso de Cobol Básico, que incluye:
 Programacion estructurada
 Introduccion a los metodos de acceso
 Elementos del lenguaje cobol
 Descripcion de la IDENTIFICATION DIVISION
 Descripcion de la ENVIRONMENT DIVISION
 Descripcion de la DATA DIVISION
 WORKING-STORAGE SECTION
 LINKAGE SECTION
 PROCEDURE DIVISION
 Clasificación de Archivos
 Revisión de Diferencias
 Revisión de Conceptos MVS/JCL

1.4. Duración
El curso tiene 1 duración de 3 días y está compuesto de:
Teoría 6 hrs.
Práctica 17 hrs.
Examen 1 hr.

COBOL AVANZADO -1- Página 1 de 64


2. Temas

2.1. Usos de la Environment Division

La sintaxis de la Environment Division es la siguiente:

ENVIRONMENT DIVISION.
[CONFIGURATION SECTION.
SOURCE-COMPUTER. <comentario.> OBJECT-COMPUTER.
<comentario>
[PROGRAM COLLATING SEQUENCE IS <alfabeto>].
SPECIAL-NAMES. <cláusulas>. 1
[INPUT-OUTPUT SECTION.
FILE-CONTROL. <entrada de archivo>)

La sintaxis de las cláusulas del párrafo SPECIAL-NAMES es:

SPECIAL-NAMES.
<nombre de entorno> IS <mnem6nico>...
ALPHABET <nombre alfabeto> IS
{ STANDARD-1 }
{ STANDARD-2 )
{ NATIVE )
( EBCDIC )
( literal-l [ALSOITROUGHI literal-2]... )

SYMBOLIC CHARACTERS <nombre simbólico>


[IS,ARE] <entero>
(IN <nombre alfabeto]
CLASS <nombre clase> IS <literal-3> [TROUGH
<literal-4>1...
CURRENCY SIGN IS <literal-5>
[DECIMAL-POINT IS COMMA).

COBOL AVANZADO - 2 Página 2 de 64


La mayoría de las cláusulas que se encuentran en esta división de
COBOL, no se utilizan. Generalmente solo empleamos la ENVIRONMENT
DIVISION para especificar los archivos a utilizar. Sin embargo, esta
división puede llegar a tener aplicaciones útiles en algún momento que
serían complicadas de obtener mediante simple codificaci6n. Este tipo de
usos son los que aquí se tratan.

En la CONFIGURATION SECTION se especifica el tipo de máquina en


que se escribe el código y el tipo de máquina en el cual se vá a ejecutar.
Estas cláusulas por lo general son únicamente para documentación; en la
mayoría de los compiladores es simplemente tratada como comentario, ya
que en realidad los compiladores se construyen para generar c6digo para
una máquina específica y no para varias máquinas. En esta misma secci6n
se pueden realizar las siguientes tareas:

Establecer indicadores de estado (UPSI's, obsoleto).


Especificar la secuencia de ordenamiento.
Especificar el carácter para usar como el signo de moneda.
El intercambio de funciones de separador decimal entre la coma y el
punto.
Especificar caracteres simbólicos.
Especificar una clase definida por el usuario.

Los indicadores de estado son ahora obsoletos, en su lugar se utilizan los


parámetros, es por eso que se omitieron en los cuadros de sintaxis. Aquí se
verán aquellas opciones que son las usuales y más útiles.

PROGRAM COLLATING.
La cláusula PROGRAM COLLATING especifica la secuencia de
ordenamiento, asociando con él un mnemónico definido en el párrafo de
SPECIAL-NAMES.

Párrafo SPECIAL-NAMES.
Este párrafo especifica características especiales del sistema, tales como
el nombre del alfabeto que el programa usará para la secuencia de
ordenamientos. Esta secuencia puede ser un código predefinido y soportado
por el compilador como el c6digo ASCII o EBCDIC, pero también se puede
definir un alfabeto personalizado.

También asocia nombres con funciones del sistema, tales como los
dispositivos de salida y entrada para ACCEPT/DISPLAY y las acciones en
un WRITE ADVANCING,

Especificaci6n de la secuencia de ordenamiento.

COBOL AVANZADO - 3 Página 3 de 64


Usando la cláusula PROGRAM COLLATING SEQUENCE y la cláusula
ALPHABET se puede establecer la secuencia de ordenamiento usada al
ejecutar las siguientes operaciones:
En comparaciones no numéricas.
En la especificación de HIGH-VALUES y LOW-VALUES.
En la instrucción SEARCH-ALL.
En los verbos SORT y MERGE.
Los pasos para cambiar la secuencia de ordenamiento comienzan por
especificar en la cláusula de PROCRAM -COLLATING el nombre del
alfabeto a usar. Este nombre de alfabeto es cualquier nombre definido por
el programador. Enseguida en la cláusula ALPHABET de la SPECIAL-
NAMES se especifica el ordenamiento a seguir. Este puede ser uno de los
preestablecido o alguno defínido por el usuario. Entre los alfabetos
predefinidos están generalmente dos disponibles: ASCII y EBCDIC, los
cuales tienen el ordenamiento correspondiente de cada uno de los códigos.
El nombre con el que reconoce el compilador cada uno de los alfabetos,
variará de uno a otro. Pero, en el VS COBOL II de IBM, El EBCDIC lleva su
propio nombre y el código ASCII es STANDARD-I,

En seguida se muestra un ejemplo en el cual se establece como


el alfabeto de ordenamiento el ordenamiento EBCDIC:

ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE~COMPUTER. IBM-PC.
OBJECT-COMPUTER. IBM-370
PROGRAM COLLATING SEQUENCE IS ALFBTO-EBCDIC.
SPECIAL-NAMES.
ALPHABET ALFBTO-EBCDIC IS EBCDIC.
Utilizando el mismo procedimiento se puede establecer una secuencia
propia. Para esto, hay que especificar el orden escribiendo la secuencia de
caracteres deseada de menor a mayor. La sintaxis está establecida para
abreviar la descripción. Siempre hay que tomar en cuenta que el
ordenamiento personalizado se basa en el nativo de la máquina en que se
esté trabajando, en un sistema 9121 el código nativo es el EBCDIC y en una
PC es el ASCII-extendido, por ejemplo. La sintaxis aplicada para establecer
la lista de forma abreviada es la siguiente:

'A' TROUGH 'Z' Es una abreviatura de:


'A' 'B' 'C'…... 'Y' 'Z'
'A' ALSO ' Significa que el carácter 'A' y el carácter 'al tienen el mismo
valor lógico en un ordenamiento.

De esta manera, si se necesitara ordenar un archivo en el cual se tratarán


letras minúsculas y mayúsculas equivalentes, además de que las letras

COBOL AVANZADO - 4 Página 4 de 64


tendría precedencia sobre los números, se haría la siguiente declaración en
el programa:

ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. IBM-PC.
OBJECT-COMPUTER. IBM-370
PROGRAM COLLATING SEQUENCE IS ALFBTO-MAY-MIN~IGLS.
SPECIAL-NAMES.
ALPHABET ALFBTO-MAY-MIN-IGLS IS
'A' ALSO 'a'
'B' ALSO 'b'
'C'ALSO 'c'
'D' ALSO 'd'


'Y' ALSO 'y'
'Z' ALSO 'Z'
'O' TROUGH '9'

El resto de los caracteres que no aparecen en la lista del alfabeto se


suponen implícitamente como en seguida del último carácter especificado,
de acuerdo al orden que tienen en el alfabeto nativo de la máquina.

Con la declaración anterior solo resta ejecutar el verbo SORT de una


forma normal para obtener el ordenamiento deseado del archivo. Dentro
del código se pueden hacer las comparaciones no numéricas de la forma
común, teniendo presente que se utilizará como regla de comparación el
ordenamiento definido en el alfabeto.

CARÁCTERES SIMBÓLICOS Y CLASES DEFINIDAS POR EL


USUARIO.
Estas cláusulas son útiles para escribir código más claro y evitar
comparaciones largas. Los caracteres simbólicos se utilizan para definir un
carácter del teclado con un nombre. Por ejemplo, para definir con un
nombre simbolico los caracteres BACKSPACE y ESCAPE se declara:

SPECIAL-NAMES.

COBOL AVANZADO - 5 Página 5 de 64


SYMBOLIC CHARACTERS BACKSPACE IS 23
ESCAPE IS 27.
Estos nombres así definidos se pueden usar de la misma forma en que se
utilizan los nombres SPACE o QUOTES. El entero especificado es el orden
en el que aparece el carácter en el alfabeto nativo, tomando en cuenta que
el carácter X'00' es el número 1.

Ejemplo: La siguiente instrucción posiciona el cursor en el inicio de la


pantalla en una terminal ANSI:

DISPLAY ESCAPE '1;IH'

En COBOL existen los nombres de condición de clase: ALPHABETIC,


NUMERIC y NUMERIC. Pero además, el programador puede definir los
suyos propios, por ejemplo:

SPECIAL~NAMES.
CLASS VOCAL IS 'A' 'E' '0' 'U'
CLASS DIGITO IS 'O' TROUGH '9'
CLASS REGSTRO-VALDO IS 'A' TROUGH 'D'.

Estos nombres de clase se. pueden usar de la misma forma que los
nombres ya predeclarados: ALPHABETIC o NUMERIC.

Ejemplo: En seguida se muestra el uso de los nombres de clase con el


código equivalente sin nombre de clase.

IF OPCN-1 IS VOCAL THEN...


IF OPCN-1 IS EQUAL TO 'A' OR 'E' OR 'I' OR
'O' OR 'U' THEN ...
IF CADNA-DIGTOS IS DIGITO THEN...
En la instrucción anterior si la variable CADNA-DIGTOS es de longitud
mayor a un carácter se valida que cada uno de ellos sea un carácter de tipo
DIGITO, si alguno no lo es la condición es falsa. En el caso de que la
variable CADNA-DIGTOS sea de longitud mayor a 1 como se supone por su
nombre, se tendría que redefinir en un arreglo de caracteres y escribir el
c6digo de validación para cada uno de ellos.
IF PE-TIPO~REGSTRO IS REGSTRO-VALDO THEN ...
IF PE-TIPO-REGSTRO IS EQUAL TO 'A' OR 'B' OR
'C' OR 'D' THEN ...

Los detalles relativos a La Secci6n INPUT-OUTPUT, se verán en la


sección 5. Manejo de Archivos.

COBOL AVANZADO - 6 Página 6 de 64


2.2. Construcciones de Programación Estructurada.
El lenguaje COBOL no puede considerarse propiamente un lenguaje
estructurado, ya que no cuenta con todas la herramientas para escribir
c6digo verdaderamente estructurado como: Procedimientos, funciones,
paso de parámetros, variables locales, etc. Sin embargo, es
responsabilidad del programador escribir código que sea lo más
estructurado posible. En el caso de COBOL esto significa aprovechar las
herramientas con las que cuenta el lenguaje y codificar bajo una disciplina
en la cual el código sea modular, lo cual si permite COBOL. También es
conveniente declarar variables para un propósito específico y evitar las
variables "multiusos". Como parte de esta disciplina está el hecho de saber
trasladar un diagrama de flujo de su forma estructurado a su formato en
COBOL, aquí se muestra como se efectúa este proceso.

Se asume que se cuenta con los conocimientos básicos de programación


estructurada y que se sabe distinguir cada una de las estructuras de la
programación en un diagrama.

Como primer lineamiento, se debe tomar en cuenta que en COBOL todas


las variables son globales, pero si se restringe su uso a bloques específicos
de código se podrá mantener la modularidad en las variables. El siguiente
paso es distinguir la codificación de cada una de las estructuras de
programación en COBOL.

2.2.1. Estructura CASE


En el COBOI, ANSI-74 no se contaba con una instrucción para implantar
esta estructura, por lo que se simulaba como se muestra en el punto 1.2.2.
En el COBOL ANSI-85 existe una nueva instrucción la cual implanta la
estructura en COBOL. Esta instrucción tiene una sintaxis extendida la cual
permite manipular condiciones de una forma más complicada a la forma en
la cual funcionan las instrucciones CASE en otros lenguajes. En este punto
veremos el uso de esta instrucción para codificar una estructura CASE en
su forma simple (sobre una sola variable) en el punto 1.4.1. se mostrará la
sintaxis extendida.
La estructura CASE es como se muestra en el diagrama:

COBOL AVANZADO - 7 Página 7 de 64


En COBOL esta estructura se codifica con la siguiente instrucción:

EVALUATE <variable>
WHEN <valor-l>
<instrucciones opción l>
WHEN <valor-2>
strucciones opción 2>
WHEN <valor-3>
<instrucciones opción 3>
WHEN....

[WHEN OTHER
<instrucciones opción default>]
END-EVALUATE.

Ejemplo:
EVALUATE PE-TIPO-EMPLDO

COBOL AVANZADO - 8 Página 8 de 64


WIIEN 'A'
PERFORM CALCLO-IMPSTO-A
WHEN 'B'
WHEN 'C'
PERFORM CALCLO-IMPSTO-BC
WHEN 'D'
PERFORM CALCLO-IMPSTO-D
WHEN OTHER
PERFORM REPRTA-TIPO-INVLDO
END-EVALUATE.

2.2.2. IF anidados
Los IF anidados se utilizan cuando se requiere una decisión múltiple y no
se cuenta con una estructura CASE
en el dialecto que se esté empleando.

Esta estructura es una estructura compuesta de varios IF's. En el


diagrama siguiente se muestran los pseudocódigos de la estructura básica y
su codificaci6ii COBOL:

IF simple:

IF (condición) THEN
< bloque de instrucciones >
END-IF.

IF completo:
IF (condición) THEN
< bloque de instrucciones -THEN- >
ELSE
< bloque de instrucciones -ELSE- >
END-IF.

La codificación de la decisión múltiple es como sigue:

IF (condición l) THEN

COBOL AVANZADO - 9 Página 9 de 64


<instrucciones opción l>
ELSE IF (condición 2) THEN
<instrucciones opción 2>
ELSE IF (condición 3) THEN
<instrucciones opción 3>
ELSE IF ...


ELSE IF (condición n) THEN
<instrucciones opción n>
ELSE
<instrucciones opci6n default>
END-IF END-IF
END-IF END-IF

END-IF. (n veces)

Ejemplo:

ACCEPT OPCN-MENU.
IF OPCN-MENU EQUAL TO '1' THEN
PERFORM DRIVR-OPCN-l
ELSE IF OPCN-MENU EQUAL TO '2' THEN
PERFORM DRIVR-OPCN~2
ELSE IF OPCN-MENU EQUAL TO '3' THEN
PERFORM DRIVR-OPCN~3
ELSE IF OPCN-MENU EQUAL TO '4' THEN
PERFORM DRIVR-OPCN-4
ELSE
PERFORM MENSJE-OPCN-INVLDA
END-IF END-IF
END-IF END-IF.

2.2.3. WHILE-DO

La estructura de esta instrucción se muestra en el diagrama:

COBOL AVANZADO - 10 Página 10 de 64


En pseudocódigo se escribe:

WHIILE (condición) DO
INICIO
<instrucciones>
FIN
En COBOL está estructura se codifica con la instrucción PERFORM-
UNTIL, pero hay que notar que en el WHILE-DO anterior el grupo de
instrucciones se ejecutan mientras la condición sea verdadera y en el
PERFOPM-UNTIL se ejecutan mientras sea falsa. Por eso la estructura
queda de la siguiente forma:

PERFORM UNTIL NOT (condición)


<instrucciones>
END-PERFORM.
Las condiciones negativas como la anterior son más difíciles de interpretar
que las condiciones simples. Se debe, siempre que sea posible, "traducir"
la condición a su forma positiva.
Ejemplo:El siguiente pseudoc6digo

COBOL AVANZADO - 11 Página 11 de 64


WHILE (A > B) DO
INICIO

FIN.

No se debe codificar:
PERFORM UNTIL NOT (A > B)

END-PERFORM.

Lo correcto sería:
PERFORM UNTIL (A <= B)

END-PERFORM.
Cuando la condición es compuesta, puede que no sea fácil convertirla a
su forma positiva, para eso se deben memorizar las siguientes
equivalencias básicas para traducir condiciones compuestas:

NOT ( (condl) OR (cond2) ) = (NOT cond1) AND (NOT cond2)


NOT ( (condl) AND (cond2) ) = (NOT condl) OR (NOT cond2)

Ejemplo: Enseguida se muestran dos pseudocódigos con su


correspondiente codificación en COBOL.
WHILE (A > B) OR (C = 3) DO
INICIO

FIN
PERFORM UNTIL (A <= B) AND (C <> 3)

END-PERFORM.

WHILE (A < B) AND (C <= D) DO ...



FIN.
PERFORM UNTIL (A => B) OR (C > D)

END-PERFORM.

2.2.4. REPEAT-UNTIL

El diagrama de esta estructura se muestra en la siguiente figura:

COBOL AVANZADO - 12 Página 12 de 64


En pseudoc6digo se escribe:

REPEAT
<instrucciones>
UNTIL (condición)

Este pseudocódígo es equivalente a:


<instrucciones>
WHILE NOT (condición)
INICIO
<instrucciones>
FIN

De esto se ve que la codificaci6n debe ser:


<instrucciones>
PERFORM UNTIL (condición)
<instrucciones>
END-PERFORM.

Es recomendable agrupar el grupo de instrucciones en un párrafo para que


el código quede de la siguiente forma:

PERFORM PARRFO-GRUPO-INSTRCCNS.

COBOL AVANZADO - 13 Página 13 de 64


PERFORM UNTIL (condición)
PERFORM PARRFO-GRUPO-INSTRCCNS
END-PERFORM.

2.2.5. FOR-DO
El diagrama de esta estructura es el siguiente:

El pseudocódigo de esta estructura es:

FOR <variable-entera> = <inicio> TO <final> Do


INICIO
<instrucciones>
FIN

La codificación en COBOL debe ser:

PERFORM VARYING <variable-entera>


FROM <inicio> BY 1

COBOL AVANZADO - 14 Página 14 de 64


UNTIL <variable-entera> GREATER THAN <final>
<instrucciones>
END-PERFORM.

Ejemplo. Se muestra la traducción del pseudocódigo siguiente:

FOR 1 = 1 TO TOTL-REGSTROS DO
INICIO
IMPRME-ESTDSCTCA
FIN.

PERFORM VARYING I FROM 1 BY 1


UNTIL I GREATER THAN TOTL-REGSTROS
PERFORM IMPRME-ESTDSTCA
END-PERE'ORM.

2.3. COPY-REPLACING.

La cláusula COPY es común verla en todos los programas COBOL, sin


embargo la opción REPLACING es raro encontrarla. Se dan muchos casos
en los que sería apropiado usarla, pero ya sea por desconocimiento o
inseguridad en su uso, se opta por escribir varios COPY's tal como se
necesitan. La sintaxis de esta cláusula es la siguiente:

COPY <nombre-copy>
REPLACING <cadenas> BY <cadena-2>.

En el VS COBOL II se pueden delimitar las cadenas con un símbolo doble


de “=” para dar mayor claridad o incluir apóstrofos en la cadena de
sustitución.

Ejernplo. Se tiene el siguíente


Copy: QE799MYl
01 LINEA-ENCBZDO-l.
05 NOMBRE-PROGRMA PIC X(20) VALUE NOMBPROG.
05 FILLER PIC X(45) VALUE SPACES.

COBOL AVANZADO - 15 Página 15 de 64


05 VERSN-PROGRMA PIC X(15) VALUE VERSPROG.

En un programa la siguiente macro-instrucción:


COPY QE799MYl
REPLACING ==NOMBPROG== BY =='PGM. PQ00LXB0'==
==VERSPROG == BY =='VERSION. 3.2.1'
La sustitución será:
01 LINEA-ENCBZDO-l.
05 NOMBRE-PROGRMA PIC X(20) VALUE 'PGM.PQ00lXBO '.
05 FILLER PIC X(45) VALUE SPACES.
05 VERSN~PROGRMA PIC X(15) VALUE 'VERSION.3.2.1'.

Esta opción es útil en la declaración de datos. En cualquier lugar del


código donde se necesite sustituir cualquier cadena de caracteres por otra,
esta opción funciona. Por ejemplo, si se tuviera una declaración genérica
de un archivo, y se quisiera utilizar esa misma declaración es distintos
lugares de un programa modificando únicamente el prefijo de las variables,
se deben seguir los siguientes pasos:

Primero se declara en un COPY el grupo de datos con un prefijo


limitado al inicio y al final con ':' :

Copy: PEDDO.COB
01 :PE:-REGSTRO-PEDDO.
05 :PE:-NUMRO PIC 9(06).
05 :PE:-FECHA PIC 9(06).
05 :PE:-ESTDO PIC X(Ol).
05 :PE:-VENDDR PIC X(08).

Esta declaración se agrega al programa mediante un COPY REPLACING


especificando las cadenas a convertir, dependiendo el lugar donde se
requiera la copia:

En la FD

COPY PEDDO

COBOL AVANZADO - 16 Página 16 de 64


REPLACING ==:PE:== BY ==FD==.

En la Working~Storage

COPY PEDDO
REPLACING --:PE:== BY ==WS==.

De esta forma el COPY quedará insertado respectivamente de la siguiente


manera:

En la FD:
01 FD-REGSTRO-PEDDO.
05 FD-NUMRO PIC 9(06).
05 FD-FECHA PIC 9(06).
05 FD-ESTDO PIC X(01).
05 FD-VENDDR PIC X(08).

Y en la Workinq-Storage:
01 WS-REGSTRO-PEDDO.
05 WS-NUMRO PIC 9(06).
05 WS-FECHA PIC 9(06).
05 WS-ESTDO PIC X(01).
05 WS-VENDDR PIC X(08).

El emplear esta facilidad tiene la ventaja de que se asegura la


correspondencia de los datos en dondequiera que se les use.
La desventaja es que se debe ser más cuidadoso en la nomenclatura de
las variables.

Ejemplo. Se tiene el siguiente


Copy: CONTIMPR
01 CONTRLS-IMPRSN.
05 NIJMRO-LINEAS PIC 9 (02) VALUE NL.
05 NTJMRO-COLMNAS PIC 9(02) VALUE NC.
05 TAMNIO-ENCBZDO PIC 9 (02) VALUE TE.
05 CARCTRS-LINEA PIC 9 (02) VALUE CL.

COBOL AVANZADO - 17 Página 17 de 64


En un programa la siguiente macro-instrucción:
COPY CONTIMPR
REPLACING NL BY 60
NC BY 02
TE BY 04
CL BY 132.

La sustitución será:
01 CONTRLS-IMPRSN.
05 NUMRO-LINEAS PIC 9 (02) VALUE 60.
05 NUMRO-COLMNAS PIC 9 (02) VALUE 02.
05 TAMNIO-ENCBZDO PIC 9(02) VALUE 04.
05 CARCTRS-LINEA PIC 9(02) VALUE 132.

2.4. Nuevas instrucciones de estándar ANSI-85


El estándar ANSI-85 es el más reciente que se ha producido. La mayoría
de los compiladores soportan parte o el estándar completo. La versión
anterior al ANSI-85 fue la ANSI-74. En general el ANSI-85 es una versión
ANSI-74 extendida. Los diferentes dialectos que se pueden encontrar de
COBOL, se deben a que cada compilador dependiente de una máquina
ajusta el estándar a una forma más conveniente al entorno del sistema en
que vá a operar y también debido a que no todos soportan el estándar
completo. El VS COBOL II es un compilador ANSI-85 el cual se dice
soporta el estándar en su nivel intermedio. Esto significa que no lo soporta
completamente. Las características de las que adolece son: Soporte para
SCREEN SECTION y soporte para la REPORT WRITER. La primera
sección es para el manejo de paneles interactivos con el usuario. La
segunda es para el manejo de reportes, relativamente automatizados.

Las tres principales extensiones al lenguaje son las siguientes:

2.4.1. INITIALIZE
La sintaxis de esta instrucción es:
INITIALIZE <varble-l>, <varble-2>,...

La función de esta instrucción es la de inicializar las variables numéricas a


cero y alfanuméricas en blanco. Si el campo que se está inicializando es un
campo de grupo, inicializa cada campo subordinado a su respectiva
categoría. Esto lo hace útil para inicializar en una sola instrucción registros

COBOL AVANZADO - 18 Página 18 de 64


completos con la seguridad de que en cada campo existirá información
válida.

Ejemplo: Si se tiene la siguiente declaración:

01 REGSTRO-PRESTCNS.
05 NUMRO-EMPLDO PIC 9(06).
05 TIPO-NOMNA PIC X(01).
05 PRESTMSS.
10 PRESTMO-CASA PIC 9(06).99 COMP-3.

10 PRESTMO-AUTMVL PIC 9(06).99 COMP-3.


10 PRESTMO-EFCTVO PIC 9(05).99 COMP-3.
05 COMSN-VENTS PIC 9(05).99 COMP-3.

La instrucción

INITIALIZE REGSTRO-PRESTCNS.

moverá ceros tipo display a NUMRO-EMPLDO;


blanco a TIPO-NOMNA; y ceros empacados a PRESTMO-
CASA,PRESTMO-AUTMVL.
PRESTMO-EFCTVO y a COMSN-VENTS.

2.4.2. EVALUATE

La sintaxis es:
EVALUATE <adjetivos> [ALSO <adjetivo-2>... 1
WHEN <objetos> [ALSO <objeto-2>... 1
<instrucciones>
[WHEN OTHER
<instrcciones> 1
END-EVALUATE.

Donde:
adjetivo~l y 2 pueden ser: Un identificador, una literal, una expresión,
TRUE o FALSE.
objetos y 2 pueden ser: ANY, una condición, TRUE, FALSE, un
ídentificador, una literal o una expresión aritmética.

La instrucción es un selector. Los <adjetivos> especifican los valores de

COBOL AVANZADO - 19 Página 19 de 64


selección.
Los <objetos> especifican las distintas posibilidades que se tienen por
cada selección.
Cuando se utilizan varios <adjetivos> estos deben corresponder en
número a los <objetos> en cada WHEN. El c6digo que se ejecutará será
aquel. en el que el valor de cada <adjetivo> sea igual a cada <objetivo>
correspondiente.

Ejemplo:

EVALUATE OPCN ALSO TRUE


WHEN 'l' ALSO (TOTL-REGSTROS >= 24)
PERFORM PROCSA-LISTA-COMPLTA
WHEN '2' ALSO (TOTL-REGSTROS < 24)
PERFORM PROCSA-LISTA-PARCL
WHEN '3' ALSO (TOTL-REGSTROS > O)
PERFORM BORRA-LISTA
WHEN '4' ALSO TRUE
PERFORM TERMNA-PROCSO
WHEN OTHER
PERFORM OPCN-INVLDA
END-EVALUATE.

2.4.3. Finales de instrucción explícitos (END-IF, END-PERFORM, etc.)


Toda instrucción COBOL que puede alojar en sí mísma grupos de
instrucciones a ejecutarse en diversos casos, deben terminarse con un final
de instrucción explícito. Es decir, con la palabra reservada END-<verbo>.
Generalmente, esto antes se hacía utilizando un punto hasta el final del
grupo de instrucciones, pero esto conduce a errores y en ocasiones es difícil
de detectar.
Ejemplo. :

Incorrecto.
IF (A < B) THEN
<instrucciones>
IF (C > D) THEN
<instrucciones>
ELSE

COBOL AVANZADO - 20 Página 20 de 64


<instrucciones>.

Correcto.
IF (A < B) THEN
<instrucciones>
IF (C > D) THEN
<instrucciones>
ELSE
<instrucciones>
END-IF
END-IF.

2.5. Declaraciones de Datos "complicadas".


Parte importante de la programación en COBOL es la declaración de los
datos. Una buena declaración de datos facilitará la codificación del
programa y facilitará su lectura. Aquí se muestran aquellas declaraciones
útiles para simplificar declaraciones complicadas.

2.5.1. Niveles 88 y 77
Los niveles 77 son variables de datos que se manejan
independientemente de cualquier otra. Es decir, no están agrupadas con
otra. Estas variables por lo tanto no están asociadas a ningún registro y
solo son variables de uso interno del programa. De acuerdo al estándar
estar variables no deben usarse. En el caso de que se tengan, estas
debieron agruparse en conjuntos simbólicos. En realidad ninguna variable
es totalmente independiente, ya que todas están relacionadas directa o
indirectamente. Al agruparse se debiera analizar su uso específico y unirse
a aquellas otras que tengan usos similares, dándoles un nombre de grupo
que sea el común denominador de todas.

Ejemplo:

Incorrecto.
77 NIJMPO-PAGNA PIC 9 (03) VALUE ZERO.
77 CONTDR-REGSTROS PIC 9(06) VALUE ZERO.
77 CONTDR-LINEAS-ESCRTAS PIC 9(02), VALUE ZERO.
77 ACMLDR-IMPSTOS PIC 9(08) VALUE ZERO.
77 CONTDR-REGSTROS-INVLDOS PIC 9(06) VALUE ZERO.

COBOL AVANZADO - 21 Página 21 de 64


Correcto.
01 VARBLES-GENRLS.
05 CONTDRES.
10 CONTDR-REGSTROS PIC 9(06)VALUE ZERO.
10 CONTDR-REGSTROS-INVLDOS PIC 9(06)VALUE ZERO.
05 ACMLDRS.
10 ACMLDR~IMPSTOS PIC 9(08)VALUE ZERO.
05 CONTRLS-IMPRSN.
10 NUMRO-PAGNA PIC 9(03)VALUE ZERO.
10 CONTDR-LINEAS-ESCRTAS PIC 9(02)VALUE ZERO.

Los niveles 88 son nombres de condición. Es decir, si se tiene una


condición (NUMRO-REGSTROS > O) esta podría tener el nombre “¿HAY
REGISTROS?". Evidentemente es más claro leer en un programa el
nombre de la condición que interpretar la expresión.

Sin embargo, solo se pueden definir nombres de condición en los que


intervenga una igualdad de una variable con respecto a un valor o un grupo
de valores. Condiciones compuestas se 9 tendrían que codificar uniendo
varios nombres de condición.

Para definir un nombre condici6n, se declara este como un cualquier otro


dato enseguida de la variable de la cual depende la condición. obviamente,
este nombre de condición debe tener nivel 88 para que sea reconocido por
el compilador como tal. Después le sigue a la declaración un valor o una
lista de valores, los cuales hacen verdadera la condición.

Ejemplo:

01 FILE-STATS PIC X(02).


88 FILE-STATS-OK VALUE '00'.
88 END-OF-FILE VALUE '10'.
88 FILE-NOT-FOUND VALUE '32'.

Las declaraciones anteriores definen los siguientes nombres de condici6n:

(FILE-STATS = '00') FILE-STATS-OK

COBOL AVANZADO - 22 Página 22 de 64


(FILE-STATS - '10') END-OF-FILE
(FILE-STATS - '32') FILE-NOT-FOUND

Si se tuviera que codificar:

OPEN INPUT ARCHVO-MAESTRO.


IF FILE-STATS = '32' THEN
PERFORM ERRR-ARCHVO-NO-EXSTE
ELSE
PERFORM PROCSO-NORML
END-IF.

Sería más claro hacerlo de la siguiente forma:

OPEN INPUT ARCHVO-MAESTRO.


IF FILE-NOT-FOUND THEN
PERFORM ERRR-ARCHVO-NO-EXSTE
ELSE
PERFORM PROCSO-NORML
END-IF.

Esto es evidente en casos que, como el anterior, no sería fácil recordar el


significado de cada uno de los códigos de FILE STATUS.

Los nombres de condici6n se pueden traslapar, es decir, varios nombres


de condici6n pueden tener valores comunes como en el siguiente ejemplo:

01 TIPO-REGSTRO PIC X(0l).


88 REGSTRO-VALDO VALUE 'A' TROUGH 'H'
88 REGSTRO-NOMNA VALUE 'A' TROUGH 'C'
88 REGSTRO-COMSNS VALUE 'E' TROUGH 'G'
88 REGSTRO-VARIOS VALUE 'D', 'H'.
88 REGSTRO-COMPNSCN VALUE 'B', 'E' TROUGH 'G'.

COBOL AVANZADO - 23 Página 23 de 64


En esta declaración cuando TIPO-REGSTRO contenga el valor 'F', las
condiciones verdaderas serán:
REGSTRO-VALDO, REGSTRO-COMSNS y REGSTRO~COMPNSCN.

Las nombres de condición se pueden hacer verdaderos con la siguiente


instrucción:

SET <nombre-condición> TO TRUE.

Cuando el nombre-condici6n tiene asociado un solo valor esta instrucción


equivale a un MOVE a la variable de la condición. Cuando se tiene un
nombre-condici6n con varios valores asociados normalmente el compilador
opta por el primero de la lista, sin embargo no debiera contarse con ello.

2.5.2. Manejo de tablas


Definici6n de una tabla.
Las tablas se definen mediante la cláusula OCCURS de la definición de
datos. Esta cláusula no se puede aplicar a nombres de datos con nivel 01.
De acuerdo al número de ocurrencias que se especifique es la longitud de la
tabla. Esta longitud es fija a lo largo del programa.

Ejemplo: Definici6n de una tabla de 1 columna de 1 carácter de 80


renglones.

01 TABLA.
05 CAMPO -ELMNTO PIC X(0l) OCCURS 80 TIMES.

Si un campo que ocurre varias veces contiene campos subordinados,


entonces cada uno de los campos subordinados tendrá tantas ocurrencias
como el campo "padre”.

Ejemplo: Definición de una tabla de 3 columnas de 25 renglones.

01 TABLA-2.
05 RENGLNS OCCURS 25 TIMES.
10 COLMNA-1 PIC 9(09).
10 COLMNA-2 PIC 9(09).
10 COLMNA-3 PIC 9(09).

COBOL AVANZADO - 24 Página 24 de 64


Acceso a los elementos de una tabla.
Se puede accesar el nombre de varíable 05 o los subniveles 10 de la
misma forma en que !;e manejan las estructuras de datos normales. Con la
diferencia de que ahora se deberá agregar un subíndice para indicar que
elemento se quiere accesar de la tabla:

<nombre-campo>(subíndice).
Ejemplo. Mover ceros a la columna 2 en el renglón 12.
MOVE ZEROS TO COLMNA-2(12).
Ejemplo. Sumar todos los renglones de la columna 3.

MOVE ZERO TO ACMLDR.


PERFORM VARYING I FROM 1 BY 1
UNTIL I > 12
ADD COLMNA~3(I) TO ACMLDR
END-PERFORM.

Tablas de longitud variable (ODO)


Las tablas anteriores son tablas con un número de ocurrencias fijo. En
ocasiones el número de ocurrencias puede variar constantemente y se
necesita asegurarse de que el c6digo que se escribe no accese una tabla
fuera de una localidad válida.

También es posible que al grabar una tabla en un archivo se requiera de


salvar espacio, si se grabara una tabla de tamaño fijo existiría un
desperdicio de espacio por todas aquellas ocurrencias que no se estén
ocupando.
La sintaxis para declarar una tabla de longitud variable se muestra
mediante el siguiente ejemplo:

01 VARBLES-GENRLS.
05 NUMRO-ELMNTOS PIC 9(03).

01 TABLA.
05 CAMPO-ELMNTO PIC X(0l)
OCCURS 1 TO 100 TIMES
DEPENDING ON NUMRO-ELEMNTOS.

En el ejemplo anterior el número de ocurrencias está en funci6n de


NUMRO~ELEMNTOS; este número de elementos solo puede ser de 1 hasta

COBOL AVANZADO - 25 Página 25 de 64


100. Si la variable que controla el tamaño contuviera un tamaño mayor a
100, la tabla solo "crecería" hasta llegar a 100 elementos.

El campo NUMRO-ELMNTOS puede estar contenido dentro de la misma


tabla como se muestra:

01 TABLA.
05 NUMRO-ELMNTOS PIC 9(03).
05 CAMPO-ELMNTO PIC X(0l)
OCCURS 1 TO 100 TIMES
DEPENDING ON NUMRO-ELEMNTOS.

índices de tablas
El acceso a una tabla se puede optimar, utilizando como subíndice un
índice de tabla.
Solo es necesario definir un nombre de índice con la cláusula INDEXED
BY, como se muestra en el ejemplo:

01 TABLA.
05 CAMPO-ELMNTO PIC X(0l) OCCURS 80 TIMES
INDEXED BY IDX-CAMPO.

Las manipulaciones de la tabla utilizando el índice son más veloces que


utilizando subíndices comunes.
Para posicionar un índice para accesar un elemento 'n' se ejecuta la
siguiente instrucción:

SET IDX-CAMPO TO n.
Donde n es el número del elemento que se desea accesar.
Para avanzar al siguiente elemento se ejecuta:
SET IDX-CAMPO UP BY 1.

El último dígito en la instrucción especifica la cantidad de elementos a


desplazarse.

La instrucción inversa es:


SET IDX-CAMPO DOWN BY 1.

Si se desea recorrer la tabla se puede utilizar un perform varying:

PERFORM VARYING IDX-CAMPO FROM 1 BY 1


UNTIL IDX-CAMPO > 80

COBOL AVANZADO - 26 Página 26 de 64


<proceso de campo tabla>
END-PERFORM.

De lo anterior se puede ver que un índice puede ser comparado con


enteros.

Tablas de dos o más dimensiones

Una tabla de dos o más dimensiones es aquella que contiene


declaraciones OCCURS anidadas.

Una tabla de dos dimensiones sería la siguiente:

01 TABLA-DOS-DIMNSNS.
05 RENGLNS OCCURS 24 TIMES.
10 COLMNAS OCCURS 80 TIMES.
15 CARCTR PIC X(0l).
15 ATRBTO PIC X(0l).

Esta tabla evidentemente es de dos dimensiones donde cada celda esta a


su vez subdividida en dos campos: CARCTR, ATRBTO. Ahora para accesar
un elemento de la tabla es necesario especificar dos índices, el primero
debe ser el externo y el segundo el interno.
Ejemplo. Mover 'A' al carácter 23 del rengl6n 15.
MOVE 'A' TO CARCTR(15, 23).

Una tabla de tres dimensiones se asemeja a una tabla de tablas de


dos dimensiones.

01 TABLA-TRES-DIMNSNS.
05 NUMRO-PANTLLA OCCURS 5 TIMES.
10 RENGLN OCCURS 24 TIMES.
15 CARCTR OCCURS 80 TIMES.
20 CARCTR PIC X(0l).
20 ATRBTO PIC X(0l).

Ahora para accesar un elemento se necesitan 3 subíndices, el primero


para indicar el número de pantalla, el segundo para indicar el renglón de
esa pantalla y el tercero para indicar la columna.

COBOL AVANZADO - 27 Página 27 de 64


Ejemplo. Limpia el primero y último rengl6n de todas las pantallas.

PERFORM VARYING NP FROM 1 BY 1


UNTIL NP > 5
MOVE SPACES TO RENGLN(NP, l)
MOVE SPACES TO RENGLN(NP, 24)
END-PERFORM.

Búsquedas en tablas

Se entiende por una búsqueda en una tabla el reconocer la posición en la


que se encuentra un elemento de la misma. Esta búsqueda puede ser
serial (elemento por elemento) o binaria (cuando la tabla está ordenada).
Este último tipo de búsqueda es el más rápido y debiese usarse siempre
que sea posible.

Búsqueda Serial
Esta búsqueda puede realizarse de dos formas:

- Utilizando PERFORM... VARYING.


Considerando que se tiene la siguiente declaración:

01 TABLA-UNA-DIMNSN.
05 RENGLNS OCCURS 25 TIMES INDEXED BY IDX-1.
10 CAMPO-1 PIC X(08).
10 CAMPO-2 PIC X(08).
Si se desea buscar la posición del elemento 'AAAA' en CAMPO-1, se
ejecutaría:

SET ELMNTO-NO-ENCNTRDO TO TRUE.


PERFORM VARYING IDX-1 FROM 1 BY 1
UNTIL IDX-1 > 25 OR ELMNTO-ENCTRDO
IF CAMPO-l (IDX-l) , 'AAAA'
SET ELMNTO-ENCNTRDO TO TRUE
END-IF
END-PERFORM.

Si ELMNTO~ENCNTRDO es verdadera la posición del elemento está


apuntada por IDX-L.

- Utilizando instrucción SEARCH

COBOL AVANZADO - 28 Página 28 de 64


La utilización de esta instrucción requiere que se tenga forzosamente un
índice definido.
La sintaxis es la siguiente:

SEARCH <identificador-l>
VARYING {<identificador-2>I<índice-l>}
AT END <instrucciones>
WHEN (condición) <instrucciones>...
END-SEARCH.

<identificador-l> Especifica el campo sobre el cual se ejecutará la búsqueda,


forzosamente debe tener más de una ocurrencia dicho campo. La cláusula
VARYING especifica el índice o el entero que se irá incrementando para apuntar
a la tabla. El grupo de instrucciones de AT END se ejecuta si la búsqueda no fue
exitoso. Las cláusula WHEN especifican las condiciones de búsqueda las cuales
pueden ser varias, en cuanto se cumple alguna de las condiciones la búsqueda se
detiene y se ejecutan las instrucciones especificadas o NEXT SENTENCE. La
variable índices puede ser el índice de otra tabla, en dicho caso al finalizar
apuntará al mismo elemento que el índice de la tabla en la que se realiz6 la
búsqueda. Es decir, si el elemento en el que se detuvo la búsqueda fue el tercero,
entonces el índice de la otra tabla también apuntará al tercero.

Ejemplo. Tomando la misma declaración de tabla anterior y realizando la


misma búsqueda.

SET IDX-1 TO 1.
SEARCH CAMPO-1
VARYING IDX-1
AT END
SET ELMNTO-NO-ENCNTRDO TO TRUE
WHEN CAMPO-l(IDX-l) = 'AAAAY
SET ELMNTO-ENCNTRDO TO TRUE
END-SEARCH.

En la instrucción anterior es necesario inicializar el índice en la primera


posición, ya que, la búsqueda se efectuará a partir de la posición en la que
se encuentre el índice. La cláusula VARYING es redundante, siempre
utilizará el índice de la tabla para la búsqueda.

COBOL AVANZADO - 29 Página 29 de 64


Si se codifican varias cláusulas WHEN, la búsqueda se termina cuando
ocurre cualquiera de ellas.

Búsqueda Binaria
La búsqueda binaria se efectúa utilizando la instrucción SEARCH ALL, la
cual es una variante de la instrucción SEARCH. La sintaxis es la siguiente:

SEARCH ALL <campo-l>


VARYING <índices 1 identificador-l>
AT END <instrucciones>
WHEN (condición) <instrucciones 1 NEXT SENTENCE>...
END-SEARCH.

Para utilizar esta instrucción es necesario definir la tabla con la cláusula


ascending, enseguida se muestra un ejemplo de declaración:

01 TABLA-UNA-DIMNSN.
05 RENGLNS OCCURS 25 TIMES
ASCENDING CAMPO-1
ASCENDING CAMPO-2
INDEXED BY IDX-1.
10 CAMPO-1 PIC X(08).
10 CAMPO-2 PIC X(08).

En la tabla anterior se puede efectuar una búsqueda por ambas columnas,


ya que ambas están ordenadas.

La instrucción actúa de la misma manera que la anterior, a diferencia que


ahora no "barrerá" la tabla para encontrar nuestra elemento, sino que
efectuará una búsqueda binaría la cual es muy veloz.

Ejemplo: Obtener la posición donde se encuéntra 'BBBB' en el campo-l.

COBOL AVANZADO - 30 Página 30 de 64


SEARCH ALL CAMPO-1
VARYING IDX-1
AT END
SET ELMNTO-NO-ENCNTRDO TO TRUE
WHEN CAMPO-I(IDX-l) = 'BBBB'
SET ELMNTO-ENCNTRDO TO TRUE
END-SEARCH.

En este caso no es necesario inicializar el índice, ya que, la búsqueda se


efectúa en toda la tabla.

2.5.3. Representación interna de datos

Parte importante para una buena declaración de datos es el saber cual es


su representación interna en la computadora, las ventajas y desventajas
de una y otra, etc. El dominio de estos tópicos es la base para manejar
la información de una manera sencilla y eficiente.
Datos numéricos (empacados, binarios, etc.)
Los datos numéricos son los datos más delicados de un programa. Es
necesario tomar en cuenta tanto su longitud como su representación
interna. Una longitud "corta" de un campo, significará tarde o temprano
pérdida de información; por otro lado, una longitud 'larga" de campo
significará no solo un desperdicio sino también unadisminución en la
eficiencia del c6digo. La representación influye también en la calidad del
c6digo generado por el compilador, aunque comúnmente se toman en
cuenta también consideraciones de estándar y de conversión de datos,
comparación de archivos, etc.

En todas las computadoras en las que se cuenta con un compilador


COBOL este ofrece por lo menos 3 representaciones diferentes de los
números:

DISPLAY.
En este formato el número ocupa tantos bytes como posiciones numéricas
tenga declaradas. Es decir, cada dígito del número se almacena en un
BYTE completo. La representación interna de este byte será el número
binario que le corresponda en el c6digo nativo de la máquina. Por ejemplo,
en una Pc el código nativo es el ASCII, y en el código ASCII el número 1

COBOL AVANZADO - 31 Página 31 de 64


se representa con el número hexadecimal '$31' si tuviéramos la siguiente
declaración:

05 CONTDR-X PIC 9(04).


al efectuar la siguiente instrucción:
MOVE 1 TO CONTDR-X.
Internamente el campo tendrá:

X '30' X '30' X '30' X '31'

Cuando el campo contiene signo, este se "anida" en la mitad de un byte


(nibble) . La representación del signo varía de máquina a máquina, pero
en la IBM PC el signo '+' se representa con el valor X'31' y el 1-1 con
X'21'en el nibble izquierdo del byte a la derecha.

Si se efectúa un DISPLAY a un número signado en formato display, se


verá que para valores negativos aparece siempre una letra o algún
símbolo, esto depende del valor almacenado en la variable, y de la
representación de ese número binario en c6digo ASCII.

Ejemplo. La representación interna de -1234 es

X '31' X '32' X '33' X '24'

1 2 3 $

En la segunda columna de la tabla se muestra la representación de este


campo de código ASCII.

En mainframes, el código nativo es el EBCDIC. En estas máquinas la


ausencia de signo de un número esta representado con el valor X'F' en el
nibble derecho del byte más a la derecha, el positivo con X'C' y el negativo
con X'D' . (Debe notarse que en PC no se distingue entre un número con
signo positivo o sin signo ya que ambos se representan con X'3'.

COBOL AVANZADO - 32 Página 32 de 64


En todo caso la posición del signo puede variar de acuerdo a las cláusulas
que uno especifique al declarar el campo. En general, los campos con
formato DISPLAY no son recomendables para operaciones aritméticas, ya
que una operación sobre un campo DISPLAY implica una conversión
primero a binario y luego su operación y aún más si el campo receptor es
un campo DISPLAY significa que el resultado tendrá que ser convertido a
formato DISPLAY (la computadora solo opera con números binarios).

BINARIO (COMP-O).
Un número binario se representa en su forma binaria en memoria
directamente.
La longitud del campo en memoria dependerá de cuantos bits sean
necesarios para alojar el mayor número posible que puede contener el
campo. Por ejemplo:

05 CAMPO-BINRIO PIC 9(04) USAGE COMP-0-


En esta declaración CAMPO-BINRIO debe ser capaz de contener hasta el
número 9999. Para representar este número en binario se necesitan n bits
tal que (2n - l) sea mayor o igual a 9999. En este caso se necesitan 14
bits. Por lo tanto, se requieren 2 bytes.

La representación interna del número 125 en CAMPO-BINRIO seria:

(125) = (0111 "01)


10 2

X'00' X'7D'

DECIMAL EMPACADO (COMP-3).


Es este formato los dígitos del 0 al 9 se representan en su formato binario
de 4 bits como en la siguiente tabla:

0 0000

1 0001

2 0010

3 0011

4 0100

COBOL AVANZADO - 33 Página 33 de 64


5 0101

6 0110

7 0111

8 1000

9 1001

Cada grupo de 4 necesita un nibble para almacenarse, por lo que en un


byte se pueden almacenar 2 dígitos. Es por esto que recibe el nombre de
empacado. El nibble de la derecha del último byte, se ociipa para anidar
el signo. La convención que se sigue para representar el signo es la
misma que para los números en formato DISPLAY; por ejemplo, en IBM la
ausencia de signo se representa con X'F', el signo positivo con X'C' y el
negativo con X'D'.
Ejempló: Representaci6n del número +34595 en IBM-370.

X '34' X '59' X '5C'

52 89 92

Por último para calcular el tamaño de una variable empacada, se cuenta


el número de dígitos de longitud que tiene el número (los 9´s solamente, el
signo no debe contarse. Este dígitos se divide entre 2 y se trunca la
fracción si hay. A este último resultado se le suma 1 y este será en bytes
que ocupará la variable, tenga o no signo.

Ejemplo: Calcular la longitud de una PIC S9(05) Y 9(04).


Para el primero se tiene: (5 / 2) + 1 = 3 bytes.
Y para el segundo: (4 / 2) + 1 = 3 bytes.
Esto quiere decir que ambas variables ocuparán el mismo espacio.
Este tipo de variables son muy eficientes para cálculos aritméticos en que
involucran cantidades de longitud mayores a 5 dígitos.

Datos alfanuinéricos

Los datos alfanuméricos son simplemente BYTES agrupados. Se debe

COBOL AVANZADO - 34 Página 34 de 64


tomar en cuenta que toda variable de grupo está definida implícitamente
como alfanumérica.

Ejemplo. La siguiente declaración


01 CONTDRS.
05 CONTDR-REGSTROS PIC S9(04) COMP-0.
05 ACMLDR-TOTL-GENRL PIC 9 (12) COMP-3.
05 ACMLDR-TOTL-PARCL PIC 9 (08) COMP-3.

Ejecuta la declaración implícita:

01 CONTDRS PIC X(14).

Esto debe tomarse en cuenta cuando se efectúan movimientos con la


variable de grupo o cuando se redefina este grupo.
Numéricos editados
Los numéricos editados funcionan como cadenas, pero poseen la ventaja
de que al recibir un valor numérico este es editado antes de ser trasladado
a la variable.

Ejemplo. Considere las siguientes declaraciones:


...
05 NUMRO-DISPLAY PIC 9(09)V99.
05 NUMRO-EDTDO PIC $$$$,$$$,$$9.99.
05 VARBLE~CADNA PIC

Al ejecutar las siguientes instrucciones, se produce respectivamente lo que


se muestra enseguida:
MOVE 12345.67 TO NUMRO-DISPLAY
NUMRO-DISPLAY = 12345v67
MOVE NUMRO-DISPLAY TO VARBLE~CADNA
VARBLE-CADNA = '1234567'
MOVE NUMRO-DISPLAY TO NUMRO-EDTDO
NUMRO-EDTDO = '$12,345.67'
MOVE NUMRO-EDTDO TO VARBLE-CADNA
VARBLE~CADNA = '$12,345.67'

COBOL AVANZADO - 35 Página 35 de 64


2.5.4. REDEFINES y RENAMES
Una vez entendidas las definiciones anteriores, es sencillo manejar las
redefiniciones. Una redefinicion es "redeclarar" una misma área de
memoria.

Más claramente, cuando se define una variable (en COBOL y en cualquier


lenguaje), se le dá un nombre a un pedacito de memoria y un atributo. El
nombre de ese pedacito de memoria es el nombre de nuestra variable, el
tamaño de ese pedacito de memoria depende de la longitud que uno
defina para la variable de su tipo; por último el atributo es el tipo de la
variable, es la forma en que se interpretará 'ese trozo de memoria, si se
interpretará como un número o una letra, como un número binario o un
empacado, etc. Cuando se necesita interpretar una misma área de
memoria de dos diferentes formas es cuando se utiliza una redefinición.
La redefinición más común es cuando se necesita el valor numérico de
una letra o cuando se necesita fragmentar un número display en varios
componentes. En los siguientes ejemplos se muestra la forma de hacer
ambas redefiniciones:

Ejemplo. Obtener el valor numérico del segundo componente del file-


status.

01 FILE-STATS PIC X(02).


01 FILE-STATS-COMPNNTES REDEFINES FILE-STATS.
05 PRIMR-DIGTO-FILE-STATS PIC X(0l).
05 SEGNDO-DIGTO-FILE-STATS PIC S9 (04) COMP-0.

Ejemplo. Fragmentar un número en varios de sus componentes.

01 NUMRO~LARGO PIC 9(18).


01 NUMRO-DESCMPSTO REDEFINES NUMRO-LARGO.
05 PRIMRA-PARTE PIC 9(06).
05 SEGNDA-PARTE PIC 9(06).
05 TERCRA-PARTE PIC 9(06).

Ejemplo. Otro uso útil es para inicializar tablas.

01 TEXTO-MESS PIC X(36) VALUE

COBOL AVANZADO - 36 Página 36 de 64


'ENEFEBMARABRMAYJUNJULAGOSEPOCTNOVDIC'.
01 TABLA-MESS REDEFINES TEXTO-MESS.
05 TEXTO-MES PIC X(03) OCCURS 12 TIMES.

La cláusula RENAMES se le utiliza para agrupar datos con un solo


nombre, estos datos no deben ser de nivel 01, sino, subordinados. En
general las declaraciones RENAMES se pueden evitar haciendo una
correcta declaración de los datos. Esta cláusula debe ser evitada, y de
hecho en todos los casos es posible hacerlo.

2.6. SORT y MERGE

2.6.1. Dectaración de archivos y formato de instrucciones


Cuando se desea ordenar un archivo es necesario declarar un archivo que
servirá como área de trabajo. Esta área de trabajo es un archivo de
SORT. Esto significa que en un programa que efectúa un ordenamiento
existirán por lo menos 2 archivos declarados. El primero será el archivo
de datos de entrada y el segundo será el área de trabajo para la
instrucción SORT.

Para declarar este archivo de SORT, primero se codifica un SELECT:


SELECT <nombre-archivo> ASSIGN TO SORTDISK.
Enseguida se declara una Sort Description en la File Section:

SD <nombre-archivo>
RECORD CONTAINS...
DATA RECORD IS ...

01.... (Descripci6n de registro).

La descripción de registro de un SD debe ser lo más simple posible, es


decir, solo debiera contener aquellos campos que son indispensables para
el proceso. Por ejemplo, si el archivo de datos contiene un campo
llamado DIRCCN-EMPLDO y este no será usado en el proceso
subsecuente, entonces no conviene incluir dicho campo en el archivo de

COBOL AVANZADO - 37 Página 37 de 64


SORT.

Ejemplo. Declaraci6n de archivo para SORT, con 80 caracteres de


longitud de registro, especificando los campos del ordenamiento.

SELECT ARCHVO-TRABJO-POLZS ASSIGN TO SORTDISK....


SD ARCHVO-TRABJO-POLZS
RECORD CONTAINS 80 CHARACTERS DATA RECORD IS
SD-POLZS-ORDNMNTO.

01 SD-POLZS-ORDNMNTO.
05 CAMPO-1 PIC 9(08).
05 CAMPO-2 PIC X(10).
05 FILLER PIC X(62).

La sintaxis de la instrucción SORT es la siguiente:

SORT <nombre-archivo-sort>
{CRITERIO DE ORDENAMIENTO}
{USING <nombre-archivo-datos>}
{INPUT PROCEDURE IS <nombre de sección>}
{GIVING <nombre-archivo-salida>}
{OUTPUT PROCEDURE IS <nombre de sección>}.

El nombre de archivo que sigue a la cláusula USING especifica el nombre


del archivo de entrada, y el de la cláusula GIVING el de salida. La INPUT
PROCEDURE y la OUTPUT PROCEDURE son métodos alternativos para
introducir los registros al archivo de ordenamiento y sacarlos de ahí, el uso
de estos métodos se detalla más adelante. Por ahora, basta con saber
que cuando se utiliza USING no se puede usar INPUT PROCEDURE y
viceversa. Y lo mismo para GIVING y OUTPUT PROCEDURE.

Cuando se utiliza USING y/o GIVING, los archivos de entrada y de salida


deben estar cerrados antes de ejecutar la instrucción SORT.

Por otro lado la instrucción MERGE se le utiliza para unir dos o más
archivos en uno solo. Los archivos de entrada deben estar ordenados por

COBOL AVANZADO - 38 Página 38 de 64


un idéntico criterio. A la salida produce un solo archivo ordenado por las
mismas llaves de los archivos originales. La sintaxis de esta instrucción
es:

MERGE <nombre-archivo-sort>
(CRITERIO DE ORDENAMIENTO)
USING <nombre-archivo-datos>...
(GIVING <nombre-archivo-salida>)
(OUTPUT PROCEDURE IS <nombre sección>)
En esta instrucción no existe la INPUT PROCEDURE. El criterio de
ordenamiento se detalla en el siguiente punto.

2.6.2. Especificación del criterio de ordenamiento


El criterio de ordenamiento tiene algunas variantes que se deben tomar en
cuenta:

Sentido del ordenamiento: Este puede ser ascendente o descendente.


En el sentido 'ascendente' los campos se ordenan de menor a mayor y en
el 'descendente' de mayor a menor. El ordenamiento ascendente se
especifica con las palabras reservadas: ON ASCENDING KEY. El
descendente se especifica con: ON DESCENDING KEY.

Duplicados (Solo para SORT) : Cuando se encuentran dos registros con


igualdad de condiciones el orden en que sean grabados será
indeterminado. Pero quizás, ie puede desear que los registros que sean
iguales queden en el orden en que fueron leídos. Para realizar esto se
utilizan las palabras reservadas: WITH DUPLICATES IN ORDER. 1

Alfabeto de secuencia: Se puede definir la secuencia de caracteres que


se desee para el ordenamiento. Para esto primero se define un alfabeto
(tal como se explic6 en el tema l) y se especifica que se va a usar con las
palabras reservadas: COLLATING SEQUENCE IS <alfabeto>.

Estas tres posibilidades se combinan para especificar un criterio de


ordenamiento de la siguiente forma:

ON (ASCENDINGIDESCENDING) KEY <nombre-campo>…


[WITH DUPLICATES IN ORDER]

COBOL AVANZADO - 39 Página 39 de 64


[COLLATING SEQUENCE IS <alfabeto>]

Ejemplo. Especificar ordenamiento ascendente en el CAMPO-1 y


descendente (en el CAMPO-2 con registros duplicados en orden y
ordenamiento EBCDIC.

SPECIAL-NAMES.
ALFBTO-EBCDIC IS EBCDIC.

SORT ARCIIVO-TRABJO-POLZS
ON ASCENDING KEY CAMPO-1
ON DESCENDTNG KEY CAMPO-2
WITH DUPLICATES IN ORDER
COLLATING SEQUENCE IS ALFBTO-EBCDIC
USING ARCHVO-POLZS
GIVING ARCHVO-POLZS-ORDNDAS.

Ejemplo. Si se tuvieran varios archivos ordenados con la instrucción


anterior, estos podrían unirse en un solo archivo ordenado con la siguiente
otra:
MERGE ARCIIVO-TRARJO-POLZS
ON ASCENDING KEY CAMPO-1
ON DESCENDING KEY CAMPO-2
COLLATING SEQUENCE IS ALFBTO-EBCDIC
USING ARCHVO-POLZS-l, ARCHVO-POLZS-2, ARCHVO-POLZS-3
GIVING ARHVO-POLZS-ORDNDAS.

2.6.3. Input y Output Procedure


Cuando se utilizan las cláusulas de INPUT y/u OUTPUT PROCEDURE
estas deben especificar nombres de secciones definidas por el
programador. Cuando se ejecuta la instrucción de SORT, si esta contiene
INPUT PROCEDURE el control del programa es transferido a la sección
que haya sido especificada. Una vez que termina de ejecutarse la INPUT
PROCEDURE se efectúa el proceso de SORT y después, en caso de que
se haya especificado una OUTPUT PROCEDURE, se transfiere el control
a esta.

COBOL AVANZADO - 40 Página 40 de 64


La INPUT PROCEDURE permite seleccionar o filtrar aquellos registros
que entrarán al SORT. Su función consiste en leer cada tino de los
registros del archivo de entrada y "liberarlos" para el sort. Cada registro
liberado es un registro que será recibido en el archivo de trabajo. Cuando
termine de ejecutarse la INPUT PROCEDURE se efectúa el proceso de
ordenamiento.
Una vez terminado el proceso de ordenamiento, los registros pueden ser
"recuperados" uno a uno para su proceso final. Cada registro será
recuperado en el orden especificado en la instrucción de SORT. Cuando
se recupera el último registro, ocurre una condición de fin de archivo sobre
el. archivo de trabajo del sort.

En el siguiente diagrama se esquematiza el orden de ejecución y el flujo


de datos de la instrucción SORT.

Ejemplo. En la siguiente instrucción:

SORT ARCHVO-MAESTRO-TRABJO
ON ASCENDING KEY GRIJPO-EMPRSA
ON ASCENDING KEY GRUPO-TIENDA
ON ASCENDING KEY GRUPO-DEPRTMNTO
WITH DUPLICATES IN ORDER
INPUT PROCEDURE FILTRDO-REGSTROS-MAESTRO

COBOL AVANZADO - 41 Página 41 de 64


OUTPUT PROCEDURE PROCSA-MAESTRO-ORDNDO.

El orden de ejecución será:

1. FILTRDO-REGSTROS-MAESTRO.
En esta secci6n deberán ser liberados los registros para ser ordenados.
2. SORT. Se ordenan los registros liberados.
3. PROCSA-MAESTRO-ORDNDO.
Son recuperados uno a uno los registros para su proceso final.

2.6.4. RELEASE
Para "liberar" los registros estos deben ser leídos previamente en la SD
del archivo de trabajo. Una vez que los datos están en la SD del archivo,
se liberan con la instrucción REALEASE. Esta instrucción actúa como un
WRITE en un archivo normal. Incluso, tiene una sintaxis semejante a la
de la instrucción WRITE.

RELEASE <registro SD> [FROM <registro de working>]

Cada registro liberado entrará en el proceso de SORT. De esta forma


cuando no se quiere que un registro en especial entre en el proceso,
simplemente no se libera y se continua con el resto de los registros.

Ejemplo. En el siguiente c6digo se ordenarán solo aquellos registros de


empleados que pertenezcan a la categoría Planta o mayor.

FILTRDO-REGSTROS-MAESTRO SECTION.
PERFORM LECTRA-MAESTRO.
PERFORM UNTIL NOT FILE-STATS-OK
IF CATGRIA-EMPLDO >= CATGRIA-PLANTA THEN
PERFORM LIBRA-REGSTRO-MAESTRO
END-IF
PERFORM LECTRA-MAESTRO
END-PERFORM.
....

COBOL AVANZADO - 42 Página 42 de 64


...
LIBRA-REGSTRO-MAESTRO.
RELEASE SD-MAESTRO-TRABJO FROM WS-REGSTRO-MAESTRO.

¿Puedes identificar a simple vista la lógica predeterminada utilizada en el


proceso FILTRDO~REGSTROS-MAESTRO?

RETURN
Una vez que los registros han sido ordenados, estos están disponibles en
la OUTPUT PROCEDURE.
Para "recuperarlos" del archivo de trabajo del sort se emplea la instrucción
RETURN. Esta instrucción es equivalente a un READ sobre un archivo
normal. La sintaxis es:

RETURN <archivo trabajo SORT> [INTO <registro working>]


AT END
<instrucciones de fin de archivo>
END-RETURN.

Las funciones de las cláusulas INTO y AT END son las mismas que en la
instrucción READ.
Ejemplo. Recuperar y procesar todos los registros ordenados del archivo
MAESTRO.

PROCSA-MAESTRO-ORDNDO SECTION.
SET NO-FIN-ARCHVO TO TRUE.
PERFORM RECPRA-REGSTRO-SORT.
PERFORM UNTIL FIN-ARCHVO
PERFORM PROCSA~REGSTRO-MAESTRO
PERFORM RECPRA-REGSTRO-SORT
END-PERFORM.


RECPRA-REGSTRO-SORT.
RETURN SD-MAESTRO-TRABAJO INTO WS-REGSTRO-MAESTRO
AT END
SET FIN~ARCHVO TO TRUE

COBOL AVANZADO - 43 Página 43 de 64


END-RETURN.

Codificación de las secciones


Para la codificación de las secciones solamente resta reunir lo aprendido
en los puntos anteriores.

En resumen:

1. Se declara el archivo de trabajo para el SORT (SELECT y SD) .


2. Se codifica la instrucción SORT especificando el criterio de
ordenamiento y las secciones deINPUT y OUTPUT PROCEDURE (de
ser necesarias).
3. Se codifica la INPUT PROCEDURE.
Esta sección debe contener por lo menos una instrucción RELEASE
(y por estándar debiera, ser solo una).
4. Se codifica la OUTPUT PROCEDURE.
En esta sección se procesan los registros ordenados y, por lo tanto,
debe contener una instrucción RETURN.

Solo hay que recordar que cada sección (SECTION) de c6digo inicia en
donde está el encabezado de la sección (nombre de la sección seguido de
la palabra reservada SECTION) . Y termina en donde comienza otra
sección. Esto significa que todo el código que este por debajo de un
encabezado de sección pertenece a dicha sección.

Otra punto a tener presente es que no existe una instrucción para finalizar
una sección. si a la mitad de la sección se decide terminar el proceso no
existe forma de detener la ejecución de la sección, ya que el proceso se
sigue en cascada.

Es por eso que se recomienda el siguiente ordenamiento del código:


PROCEDURE DIVISION.
<rutina principal>
<párrafos de la rutina principal>
<párrafos de la INPUT PROCEDURE>
<párrafos de la OUTPUT PROCEDURE>

COBOL AVANZADO - 44 Página 44 de 64


<encabezado de INPUT PROCEDURE>
<código principal de INPUT PROCEDURE>
<encabezado de OUTPUT PROCEDURE>
<codigo principal de OUTPUT PROCEDURE>

Nunca se deben incluir COPY's de c6digo al final de este archivo, ya que


las rutinas que se inserten pertenecerán a la OUTPUT PROCEDURE
(a menos que el COPY cuente con su propio encabezado de sección).

2.6.5. Registros especiales para el SORT.

En ocasiones es posible que ocurran errores durante el SORT, por


ejemplo, que no exista el espacio suficiente para crear el archivo de
trabajo, error en el acceso a disco, etc.
Para tener un poco de control sobre los errores de un proceso de SORT,
existen registros especiales los cuales dan información acerca de la forma
en que termino. Algunos otros sirven para especificar parámetros. Los
registros más usuales y su utilización son los siguientes:

SORT-RETURN.
Este registro contiene un valor numérico de o si la operación de SORT fué
exitoso o de 16 si no lo fue.
Dentro de la INPUT PROCEDURE o de la OUTPUT PROCEDURE se
puede mover un valor de 16 para terminar la ejecución del proceso SORT.
La finalización ocurrirá en el siguiente RETURN o RELEASE que se
ejecute.
SORT-CORE-SIZE.
Mediante este registro se le especifica al SORT la cantidad de
almacenamiento temporal que estará disponible en bytes.

SORT-FILE-SIZE.
En este registro se puede especificar una cantidad numérica (antes de
ejecutar la instrucción SORT) para especificar la cantidad aproximada de
registros que participarán en el SORT. Esto es útil para que el SORT se
prepare y optimize el uso de la memoria auxiliar.

SORT-MODE-SIZE.

COBOL AVANZADO - 45 Página 45 de 64


Si el archivo de entrada al SORT es un archivo de registros de , longitud
variable, es posible especificar aquí la longitud del registro que ocurrirá
más veces. Este registro también es para fines de mejoría del rendimiento.

Ejemplo. En el siguiente código se ordenará un archivo de longitud


variable, se supone que contendrá aproximadamente 6,000 registros, de
los cuales, el 75% son de 125 caracteres de longitud. Se dispone además
de hasta 750 MB de espacio auxiliar en disco.
MOVE 768000 TO SORT-CORE-SIZE.
MOVE 6000 TO SORT-FILE-SIZE.
MOVE 125 TO SORT-MODE-SIZE.
SORT SD-ACMLDOS-TRABJO
ON ASCENDING KEY GRUPO-EMPRSA
ON ASCENDING KEY GRUPO-TIENDA
ON ASCENDING KEY GRUPO-DEPRTMNTO
ON ASCENDING KEYGRUPO-SECCN
ON ASCENDING KEY RFC-EMPLDO
USING ARCHVO-CAPTPA~ACMLDOS
GIVING CAPTRA-ACMLDOS-ORDNDOS.
IF SORT-RETURN EQUAL TO 16 THEN
PERFORM NOTFCA-SORT-ERRNEO
END-IF.

2.7. Subprogramas.
Un subprograma es aquel que no realiza un proceso que sea ejecutado
directamente por el usuario, sino que es lanzado por otro proceso. Al
proceso que es ejecutado por el usuario directamente se le llama
Programa principal. Los programas que son ejecutados por otros
programas se les llama subprogramas.

Cuando un proceso ejecuta un subprograma, este toma el control


pudiendo además recibir algún o algunos parámetros. Cuando finaliza la
ejecución del subprograma te devuelve el control al programa principal.

La ejecución del programa principal continúa en la siguiente instrucción


que sigue al lugar donde se efectuó la llamada al subprograma.

COBOL AVANZADO - 46 Página 46 de 64


Los subprogramas pueden, a su vez, llamar a otros subprogramas, pero la
recursividad no esta permitida, ni directa ni indirectamente.

2.7.1. Transferencia de control a otro programa.

La llamada a un subprograma o transferencia de control se efectúa por


medio de la instrucción CALL. La sintaxis de este instrucción es la
siguiente:

CALL {<identificador>I<literal>}
USING [{BY REFERENCEIBY CONTENTII <variable-l> ..
ON OVERFLOW
<instrucciones error>
END-CALL.

La cláusula USING especifica los parámetros que se envían al


subprograma. Las cláusulas BY REFERENCE y BY CONTENT son
opcionales y se detallan más adelante.

Cuando se hace el llamado se especifica un nombre de programa. Este


nombre puede estar almacenado en una variable alfanumérica o puede
darse explícitamente mediante una literal. si el subprograma llamado se
ejecuta exitosamente el control del proceso se devuelve al programa
principal y el flujo del programa continúa en la siguiente instrucción al
CALL. Si no se ejecuta correctamente, ocurre una condición de
OVERFLOW, en ese caso se ejecutan las instrucciones de la cláusula ON
OVERFLOW.

Ejemplo. Ejecutar el subprograma del cálculo de ISPT.

CALL 'CALCISPT'
USING REGSTRO-EMPLDO-MAESTRO
CODGO-RETRNO
ON OVERFLOW

COBOL AVANZADO - 47 Página 47 de 64


PERFORM ERRR-EJCTR-CALCISPT
END-CALL.

Es necesario mencionar, que el subprograma que ha sido llamado debe


devolver el control al programa principal mediante una instrucción
GOBACK.

Ejemplo. Proceso principal de subprograma.

PROCEDURE DIVISION.
RUTNA-PRINCPL USING REGSTRO-MAESTRO
CODGO-RETRNO.
PERFORM VALDA-REGSTRO.
IF CATGRIA-EMPLDO > CATGRIA-PLANTA THEN
PERFORM CAI,CLA-ISPT-EMPLDO-PLANTA
ELSE
PERFORM CALCLA-ISPT-EMPLDO-EVNTL
END-IF.
GOBACK.

Si el programa del ejemplo anterior terminara su proceso con una


instrucción STOP RUN, terminaría todo el hilo de ejecución, es decir,
terminaría su propio proceso y al proceso que lo llamó.

2.7.2. Programas anidados

El VS COBOL II de IBM, permite además la modalidad de programas


anidados. En el siguiente diagrama se muestra una estructura de
programas anidados:

IDENTIFICATION DIVISION.
PROGRAM-ID. Al.

IDENTIFICATION DIVISION.
PROGRAM-ID. A2.
… A2
… A1
END PROGRAM A2 .

IDENTIFICATION DIVISION .
PROGRAM-ID. A3.
... A3
...

COBOL AVANZADO - 48 Página 48 de 64


END PROGRAM A3.
END PROGRAM Al .

Los programas anidados permiten modularizar la codificación y las


variables de un programa. Los programas pueden tener de esta forma
variables locales y globales, también los archivos pueden ser compartidos.

Los programas anidados o contenidos, pueden tener a su vez otros


programas anidados. Para declarar estos programas solo es obligatorio
definir una IDENTIFICATION DIVISION, el resto de las divisiones
son opcionales. El nombre de cada uno de los programas, además, debe
ser único.

Ejemplo. El siguiente código puede ser un programa anidado.

IDENTIFICATION DIVISION.
PROGRAM-ID. HOLA.
PROCEDURE DIVISION.
DISPLAY 'HOLA.... '.
END PROGRAM HOLA.

Los programas contenidos no pueden tener una CONFIGURATION


SECTION. Y es obligatorio que cada uno de los programas
contenidos termine con END PROGRAM.

Finalizaci6n y llamados entre programas anidados.


Para que un programa termine su ejecuclón, este debe ejecutar la
instrucción EXIT PROGRAM.
Si ejecuta un GOBACK 0 STOP RUN, esta se aplica globalmente a todo el
programa. Es decir, si un programa contenido ejecuta un STOP RUN,
todos los procesos son terminados, incluyendo al programa principal.

Un programa anidado solo puede ser llamado por el programa que esta
por encima de él directamente en la jerarquía, a menos que se declare al
programa como tipo COMMON. En tal caso, el programa puede ser
ejecutado por cualquier programa anteriormente declarado.

Ejemplo. El siguiente programa puede ser llamado por cualquier


programa previamente definido.

COBOL AVANZADO - 49 Página 49 de 64


IDENTIFICATION DIVISION.
PROGRAM-ID. PROGA IS COMMON.

END PROGRAM PROGA.

Variables y archivos locales y globales.

Las variables definidas dentro de cada programa se consideran variables


locales, y como tales, solo pueden ser accesadas por el programa que las
definió. Sin embargo, si se desea compartir datos o archivos, estos se
pueden declarar globales. Un dato o un archivo que ha sido declarado
como global, puede ser referenciado por cualquier programa contenido,
directa o indirectamente, en el programa que definió el dato global.

Las variables y archivos se declaran globales utilizando la cláusula


GLOBAL. En el caso de archivos esta se usa en la FD y en el caso de
datos se utiliza en la declaración del dato. El uso de la cláusula se
muestra en los siguientes ejemplos.
Ejemplo. Declaración de un archivo global.
SELECT ARCIIVO-LIQDCNS ASSIGN TO...
FD ARCHVO-LIQDCNS
IS GLOBAL
BLOCK CONTAINS 0 RECORDS
RECORD CONTAINS 120 CHARACTERS.

01 FD-ARCIIVO-LIQDCNS.

Ejemplo. Declaración de datos globales.

WORKING-STORAGE SECTION.
01 REGSTRO-FACTRA GLOBAL.
05 FOLIO-FACTRA PIC X(10)
05 FECHA-FACTRA PIC 9(06)
05 NUMRO-PEDDO PIC 9(06)
05 MONTO-FACTRA PIC 9(12)
05 CLAVE-LIQDCN PIC X(20)

01 VARBLES-GENRLS.

COBOL AVANZADO - 50 Página 50 de 64


05 SWITCHS.
10 SW-EXSTE~LIQDCN PIC X(Ol) GLOBAL.
88 EXSTE-LIQDCN VALUE 'E'.
88 NO-EXSTE-LIQDCN VALUE 'N'.

Ambas declaraciones de datos podrán ser usadas libremente por los


programas anidados que estén en las jerarquías inferiores. No es
necesaria ninguna definición adicional en los programas anidados.

En el ejemplo de la declaración de datos, la cláusula GLOBAL se aplica a


todos los campos que están incluidos en la declaración de REGSTRO-
FACTRA. Si solo se deseara compartir, por ejemplo, el campo
CLAVE-LIQDCN, entonces, solo se usaría la cláusula GLOBAL en este
campo.

Ejemplo. El siguiente c6digo está anidado en el programa que contiene las


declaraciones de los dos ejemplos anteriores, es por eso que puede utilizar
las variables globales sin necesidad de definir algo más.

IDENTIFICATION DIVISION.
PROGRAM-ID. POSCLIQD.
PROCEDURE DIVISION.
SET EXSTE-LIQDCN TO TRUE.
START ARCHVO-LIQDCNS
KEY IS EQUAL TO CLAVE-LIQDCN
INVALID KEY
SET NO-EXSTE-LIQDCN TO TRUE
END-START.
END-PROGRAM POSCLIQD.

Llamadas estáticas y dinámicas

El proceso normal para producir un programa ejecutable a partir de un


programa fuente COBOL, es el siguiente:

COBOL AVANZADO - 51 Página 51 de 64


Los archivos objeto externos son programas objeto generados por un
proceso similar de compilación de otro programa COBOL. Cuando el
programa principal llama a un subprograma, ambos tienen que ser
linkeditados juntos.

Este tipo de enlace entre los programas, se le conoce como llamado o


enlace estático. Al final se obtiene un solo programa ejecutable, el cual
contiene todos los m6dulos (programa principal y subprogramas).
Se le llama estático porque la llamada al subprograma "se resuelve"
desde el momento de compilación.
Es decir, el programa sabe ya qué código se ejecutará al hacer el
llamado.

COBOL AVANZADO - 52 Página 52 de 64


Un llamado o enlace dinámico, permite llamar a ejecución un programa
que se encuentra en otro archivo ejecutable, diferente del programa
principal. Además, no es necesario conocer al momento de compilación el
programa a ejecutar, es decir, puede ser variable. Dado que la llamada se
resuelve en el momento en que esta ejecutándose el programa, a esta se
le llama dinámica.

Cuando es una llamada estática y se modifica el subprograma, es


necesario repetir el proceso de compilación (a menos que si se cuente con
el programa objeto principal) y linkedicí6n del programa principal. Si la
llamada es dínámica, basta con compilar y linkeditar por separado el
subprograma.

La llamada estática se distingue porque el nombre del programa a llamar


se especifica con una literal.
Ejemplo. Llamada estática.
CALL 'CALCMONT'.

La llamada dinámica se efectúa utilizando un identificador. Este


identificador debe ser inicializado con el nombre del programa que se
desea ejecutar antes de efectuar el CALL.

Ejemplo. Llamada dinámica.

MOVE 'CALCMONT'. TO NOMBRE~SUBPRGRMA.


CALL NOMBRE-SUBPROGRMA.

Ambos ejemplos ejecutarán el mismo programa, pero el primero lo hará en


modo estático y el segundo en modo dinámico.

Otra diferencia más entre ambos modos de enlace es el uso de la


memoria. En un enlace estático todo el programa es un solo bloque que
es cargado a memoria principal de una sola vez. En un enlace dinámico
solo es cargado a memoria el programa principal y según sea necesario se
van cargando los subprogramas llamados.

Inicializaci6n y Pronervaci6n de variables.

COBOL AVANZADO - 53 Página 53 de 64


La primera vez que es lanzado un subprograma, se llevan a cabo las
inicializaciones de variables que se hayan especificado (cláusulas VALUE
de la Data Division). Pero las restantes llamadas no efectuarán las
inicializaciones. También, los valores de las variables no se pierden entre
llamado y llamado. Es decir, una vez que un subprograma es lanzado a
ejecucion por segunda vez, las variables permanecerán en el mismo
estado en que se quedaron en el llamado anterior.

Ejemplo. Analice el siguiente subprograma.

IDENTIFICATION DIVISION.
PROGRAM-ID. SUBPROG.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 VARBLES-GENRLS.
05 CONTDR PIC 9 (02) VALUE ZERO.
05 ULTMO-PARMTRO PIC X(10) VALUE SPACES.

LINKAGE SECTION.
01 PARMTRO PIC X (10).

PROCEDURE DIVISION USING PARMTRO.


ADD 1 TO CONTDR.
IF CONTRDR IS GREATER THAN 1 THEN
DISPLAY 'ULTIMO PARAMETRO: ' ULTMO-PARMTRO
END-IF.
DISPLAY 'PARAMETRO ACTUAL: ' PARMTRO.
DISPLAY 'CONTADOR = ' CONTDR .
MOVE 'PARMTRO ' TO ULTMO-PARMTRO
GOBACK.

El siguiente c6digo en un programa principal:

MOVE 'AAAA ' TO PARMTRO.


CALL SUBPROG USING PARMTRO.
MOVE ' BBBB ' TO PARMTRO.
CALL SUBPROG USING PARMTRO.

producirá la siguiente salida:

COBOL AVANZADO - 54 Página 54 de 64


PARAMETRO ACTUAL: AAAA
CONTADOR = 1
ULTIMO PARAMETRO: AAAA
PARAMETRO ACTUAL: BBBB
CONTADOR = 2

¿Puedes explicarte porqué?

La preservación de variables de la que se habla es válida para llamadas


estáticas en todos los casos y para llamadas dinámicas solo si no se ha
liberado la memoria.

Liberaci6n de memoria.
Cuando un enlace dinámico es ejecutado, la subrutina es cargada en
memoria y ahí permanecerá ocupando la memoria a menos que esta se
libere. Para liberar la memoria utilice la instrucción CANCEL, cuya
sintaxis es:
CANCEL <nombre-programa>.

Esta instrucción liberará la memoria ocupada por la subrutina llamada.


Cuando se llame a la subrutina una nueva vez, el llamado se resolverá
como si fuera el primero que se hace a la subrutina. Es decir, se carga en
memoria y se efectúan las inicializaciones de variables.

Cuando son varios los enlaces dinámicos que efectúa un programa, es


conveniente ir liberando la memoria conforme se efectúan los llamados (a
menos que se quiera preservar los valores de las variables de un
subprograma) , como lo muestra el siguiente ejemplo.

Ejemplo. Enlaces dinámicos y liberación de memoria.


MOVE ' PROGA ' TO NOMBRE-PROGRMA.
CALL NOMBRE-PROGRMA.
CANCEL NOMBRE-PROGRMA.

MOVE 'PROGB' TO NOMBRE-PROGRMA.


CALL NOMBRE-PROGRMA.
CANCEL NOMBRE-PROGRMA.

COBOL AVANZADO - 55 Página 55 de 64


De esta forma se evita una sobrecarga en memoria. De no hacerlo , así,
la memoria se agota y se al efectuar otro enlace más la ejecución fallará y
abortará el programa.

2.7.3. Parámetros por referencia y por contenido

Como se ha podido ver en los ejemplos anteriores, los subprogramas


pueden recibir o enviar parámetros. Estos parámetros deben declararse
en la LIKAGE SECTION de la Data Division. Además debe especificarse
el orden en que serán recibidos los parámetros por el subprograma en el
encabezado de la Procedure Division, tal como lo muestra el ejemplo.

Ejemplo. Recepción de parámetros en un subprograma.


IDENTIFICATION DIVISION.


DATA DIVISION.

LINKAGE SECTION.
01 PARMTROS.
05 TIPO-ACCSO PIC X.
88 CONDCNL VALUE 'C'
88 PRIMRO VALUE 'P'
88 ULTMO VALUE 'U'
88 SIGNTE
VALUE 'S'
88 ANTRR VALUE 'A'
05 CODGO-RETRNO-ACCSO PIC X(02).
PROCEDURE DIVISION USING TIPO~ACCSO
CODGO-RETRNO-ACCSO.
....
….

En el ejemplo se declaran dos variables que serán recibidas y enviadas de


vuelta como parámetros.
Y el encabezado de la PROCEDURE DIVISION especifica el orden en que
serán recibidos dichos parámetros.

COBOL AVANZADO - 56 Página 56 de 64


En un subprograma como el anterior, se pueden modificar los valores de
los parámetros y el programa principal recibir los cambios. Ya que, en
realidad, ambos programas están trabajando sobre la misma área de
memoria sobre la que se encuentran los datos parámetro. A este tipo de
parámetros se les llama: Parámetros por referencia. Esto es porque, el
programa principal envía un apuntadores al subprograma, los cuales
contienen la dirección de los datos parámetro. Cuando el subprograma
modifica un dato, realmente está modificando el dato del programa
principal.

En ocasiones, por seguridad, será necesario que el subprograma pueda


accesar los datos recibidos como parámetro, pero sin que pueda modificar
los datos del programa principal. A este tipo de parámetros se les conoce
como: Parámetros por contenido. En este caso, el subprograma recibe
una copia de los datos. Esta copia o puede ser modificada, pero, como es
una copia, no puede alterar los datos del programa principal.

Para especificar que se desea enviar un parámetro por contenido o por


referencia se especifican alguna de las cláusulas:

BY REFERENCE o
BY CONTENT
antes del nombre de la variable parámetro.
Ejemplo. Un llamado a una subrutina puede ser:

CALL SUBPROGL USING BY REFERENCE PARMTRO-1


BY CONTENT PARMTRO-2
BY REFERENCE PARMTRO-3.

Y el subprograma correspondiente debe, esta definido con el siguiente


encabezado de Procedure Division:

PROCEDURE DIVISION USING BY REFERENCE PARMTRO-1


BY CONTENT PARMTRO-2

COBOL AVANZADO - 57 Página 57 de 64


BY REFERENCE PARMTRO-3.
Si se omite cualquiera de las dos cláusulas el default es: BY
REFERENCE.

3. Prácticas

COBOL AVANZADO - 58 Página 58 de 64


3.1. Ejercicio 1
Se realizará un programa usando la especificación que se proporcionara.

COBOL AVANZADO - 59 Página 59 de 64


4. Evaluación y Referencias

4.1. Evaluación
La evaluación estará formulada por :
La participación, que constituye el 5% de la evaluación final.
La práctica, que constituye el 35% de la evaluación final.
El examen teórico, que constituye el 60% de la evaluacion final.

4.2. Referencias
Material del Curso
CONCOBAV.DOC .- Red de IDS
Práctica:
PRACOBAV.DOC .- Red de IDS
Examen
EXACOBAV.DOC .- Red de IDS

COBOL AVANZADO REF: 388315349.DOC ¡Error!Estilo no definido.  60

S-ar putea să vă placă și