
Tablas
El uso de tablas en Cobol es algo muy frecuente y por eso he decidido crear un apartado específico para hablar de ellas.
En el capítulo de la DATA DIVISION, dentro de los manuales, podréis encontrar una explicación
de cada comando o cláusula que veamos de aquí en adelante.
En primer lugar daremos una definición de ellas.
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. Todo lo que voy
a explicar aquí, se hará desde lo más
básico. Con un ejemplo
lo vamos a ver mas claro:
Imaginamos
que queremos tener la información de cuantas
personas entran a un museo cada día de la
semana. Si como máximo entran al día
mas o menos 1.000 personas deberíamos declarar
siete variables de la siguiente manera:
01
LUNES 01 MARTES 01
MIERCOLES 01 JUEVES 01
VIERNES 01 SABADO 01
DOMINGO
|
PIC 9(4). PIC
9(4). PIC 9(4). PIC 9(4). PIC 9(4). PIC
9(4). PIC 9(4).
|
Para
introducir datos aquí podríamos hacer:
MOVE 200 TO LUNES.
MOVE 430 TO MARTES. MOVE 136 TO MIERCOLES. MOVE 525 TO JUEVES. MOVE 380 TO VIERNES.
MOVE 1910 TO SABADO. MOVE 2300 TO DOMINGO.
Fijaros que todas son del mismo tipo (numéricas)
y del mismo tamaño (4), por lo tanto cumplen el requisito para crear una tabla, así que vamos a sustituir todo lo anterior haciendo uso
de una tabla.
Ahora
tendremos una única variable donde guardar
los datos y se llamará VISITAS. Para introducir
los datos lo haríamos refiriéndonos
con un subíndice a cada uno de sus elementos,
siete en este caso, porque siete son los días
de la semana. Lo más lógico será
respetar el orden de los días, es decir 1
para el Lunes, 2 para el Martes, etc ...
MOVE 200 TO VISITAS (1). MOVE 430 TO VISITAS (2). MOVE 136 TO VISITAS (3). MOVE 525 TO VISITAS (4).
MOVE 380 TO VISITAS (5). MOVE 1910 TO VISITAS (6). MOVE 2300 TO VISITAS (7).
El
resultado es el mismo, pero solo hemos tenido que
declarar una variable. Por supuesto el número
que hace referencia al subíndice puede ser
a su vez una variable, como veremos un poco mas
abajo.
Cobol también posee la capacidad de crear una tabla y rellenarla a su vez utilizando la WORKING-STORAGE SECTION
. Para ello primero declaramos los valores en una variable y gracias a la cláusula REDEFINES, hacemos que
su valor se cargue en la tabla. Eso no quiere decir que su valor no se pueda cambiar, pero al iniciar el programa, la tabla contendrá
esos valores. Para seguir con el ejemplo crearemos una con los días de la semana.
01
TABLADIAS. 02
FILLER 02
FILLER 02
FILLER 02
FILLER 02
FILLER 02
FILLER 02
FILLER 01 TABLADEDIAS 02
ELDIA
|
PIC
X(10) VALUE "LUNES ". PIC
X(10) VALUE "MARTES ". PIC
X(10) VALUE "MIERCOLES ". PIC
X(10) VALUE "JUEVES ". PIC
X(10) VALUE "VIERNES ". PIC
X(10) VALUE "SABADO ". PIC
X(10) VALUE "DOMINGO ". REDEFINES
TABLADIAS. PIC X(10) OCCURS 7 TIMES.
|
Ya
tenemos cargada la tabla con los días de
la semana respetando también el orden que
hemos indicado anteriormente.
Ahora
mostraremos las visitas de cada día utilizando
las tablas y refiriéndonos a los elementos
de la tabla con valores variables. Vamos a pedir
que nos diga el día de la semana para el
cual quiere saber las visitas que hubo:
WORKING-STORAGE
SECTION. 01 DIA PIC
9. 01 LVISITAS PIC Z.ZZ9. ... PROCEDURE
DIVISION. ... PEDIR. DISPLAY
"INTRODUZCA DIA PARA VER SUS VISITAS" LINE
4 COL 20. ACCEPT
DIA LINE 4 COL 50 PROMPT LOW. IF
DIA < 1 OR DIA > 7 GO PEDIR. DISPLAY
"EL " LINE 10 COL 20. DISPLAY
ELDIA (DIA) LINE 10 COL 23. DISPLAY
"HUBO " LINE 10 COL 33. MOVE
VISITAS (DIA) TO LVISITAS. DISPLAY
LVISITAS LINE 10 COL 38. DISPLAY
"VISITAS." LINE 10 COL 44.
|
Al introducir, por ejemplo el valor 3 el resultado hubiera sido:
EL MIERCOLES HUBO 136 VISITAS.
VARIAS DIMENSIONES O NIVELES
Todas las que hemos visto son de una dimensión, pero se pueden definir de mas niveles y convertirlas
en matrices. Por ejemplo ahora vamos a diferenciar en la tabla, además del número de visitas, si han sido hombres o mujeres, para ello
creamos una nueva dimensión quedando la tabla de la siguiente manera:
01
DIASEMANA. 02
GENERO 03
VISITAS
|
OCCURS
2 TIMES. PIC 9(4) OCCURS 7 TIMES.
|
Como veis nuestra tabla contiene dos cláusulas OCCURS, con ello hemos conseguido crear
una matriz de 2 x 7, ahora la variable VISITAS tendrá 14 elementos. Para dirigirnos a ellos utilizaremos dos subíndices. En nuestro caso al
diferenciar el género, identificaremos con el valor 1 a los hombres y con el 2 a las mujeres. Veamos como rellenamos la tabla ahora:
MOVE 110 TO VISITAS (1, 1) MOVE 90 TO VISITAS (2, 1).
MOVE 130 TO VISITAS (1, 2) MOVE 300 TO VISITAS (2, 2).
MOVE 100 TO VISITAS (1, 3) MOVE 36 TO VISITAS (2, 3).
MOVE 250 TO VISITAS (1, 4) MOVE 225 TO VISITAS (2, 4).
MOVE 190 TO VISITAS (1, 5) MOVE 190 TO VISITAS (2, 5).
MOVE 1000 TO VISITAS (1, 6) MOVE 910 TO VISITAS (2, 6).
MOVE 1100 TO VISITAS (1, 7) MOVE 1200 TO VISITAS (2, 7).
Por supuesto al igual que antes los subíndices pueden
ser sustituidos por variables. Por ejemplo, sabiendo
los datos anteriores vamos a sumar todas las mujeres
que entraron en la semana y todos los hombres y
vamos a averiguar cual fue el día de mayor
visitas y el día de menor asistencia.
WORKING-STORAGE
SECTION. 01 DIA PIC
9. 01 LVISITAS PIC Z.ZZ9. 01
MAYOR PIC 9(4)
VALUE 0. 01 MENOR PIC
9(4) VALUE 9999. 01 DIAMAYOR
PIC 9. 01 DIAMENOR PIC 9. 01
TOTAL PIC 9(4). 01
HOMBRES PIC 9(4). 01 MUJERES
PIC 9(4). ... PROCEDURE
DIVISION. ... MOVE
0 TO DIA. MIRAR. ADD
1 TO DIA IF DIA > 7 GO FIN. ADD
VISITAS (1, DIA) TO HOMBRES. ADD
VISITAS (2, DIA) TO MUJERES. COMPUTE
TOTAL = VISITAS (1, DIA) + VISITAS (2,
DIA). IF
TOTAL > MAYOR MOVE TOTAL TO MAYOR
MOVE
DIA TO DIAMAYOR. IF
TOTAL < MENOR MOVE TOTAL TO MENOR MOVE
DIA TO DIAMENOR. GO
MIRAR. FIN. DISPLAY
"TOTAL HOMBRES " LINE 10 COL
10 ERASE. MOVE
HOMBRES TO LVISITAS.
DISPLAY LVISITAS LINE 10 COL 35.
DISPLAY
"TOTAL MUJERES " LINE 11 COL
10. MOVE
MUJERES TO LVISITAS.
DISPLAY LVISITAS LINE 11 COL 35.
DISPLAY
"----------------------------------"
LINE
12 COL 10. DISPLAY
"TOTAL VISITAS " LINE 13 COL
10. COMPUTE
LVISITAS = HOMBRES + MUJERES. DISPLAY
LVISITAS LINE 13 COL 35. DISPLAY
"----------------------------------"
LINE
14 COL 10.
DISPLAY
"DIA MAYOR " LINE 15 COL 10. DISPLAY
TSEM (DIAMAYOR) LINE 15 COL 22. MOVE
MAYOR TO LVISITAS.
DISPLAY LVISITAS LINE 15 COL 35.
DISPLAY
"DIA MENOR" LINE 17 COL 10. DISPLAY
TSEM (DIAMENOR) LINE 17 COL 22. MOVE
MENOR TO LVISITAS.
DISPLAY LVISITAS LINE 17 COL 35. ACCEPT
OP LINE 20. ...
|
LLENANDO TABLAS
Ahora imaginamos que los datos de la tabla de visitas,
en vez de asignarlos con un MOVE
como hemos hecho en los ejemplos anteriores, los
vamos a pedir mediante ACCEPT
en un programa. Vamos a hacer un pequeño
programa para que veais como quedaría:
WORKING-STORAGE
SECTION. 01
DIASEMANA. 02
GENERO OCCURS
2 TIMES. 03
VISITA PIC 9(4) OCCURS
7 TIMES. 01 SUB1 PIC
9. 01 SUB2 PIC
9. 01 OP PIC
X. 01 LGENERO PIC X(7). ... PROCEDURE
DIVISION. INICIO. DISPLAY
"CAPTURA DE DATOS" LINE 2
COL 10 ERASE. MOVE
0 TO SUB1 SUB2. METER. ADD
1 TO SUB2 IF SUB2 > 7 GO FIN. MOVE
0 TO SUB1. METER1. ADD
1 TO SUB1 IF SUB1 > 2 GO METER. IF
SUB1 = 1 MOVE "HOMBRES" TO
LGENERO ELSE MOVE
"MUJERES" TO LGENERO. DISPLAY
"VISITAS DE " LINE 10 COL
10. DISPLAY
LGENERO LINE 10 COL 21. DISPLAY
"EL DIA" LINE 10 COL 29. DISPLAY
TSEM (SUB2) LINE 10 COL 37. ACCEPT
VISITAS (SUB1, SUB2) LINE 10 COL 50. GO
METER1. FIN. DISPLAY
"PROCESO DE CAPTURA FINALIZADO" LINE
20 COL 20. ACCEPT
OP LINE 20 COL 1. ...
|
Ahora podríamos incluir el código anterior
y que nos calcule el día de mayor y menor
visitas y la suma por géneros.
BUSCANDO EN TABLAS
Para buscar en las tablas existe un comando propio llamado SEARCH, que veremos al final del capítulo,
pero ahora vamos a hacer una busqueda por subíndices
normal para encontrar alguno o varios elementos
que cumplan una determinada condición. Por
ejemplo, siguiendo con nuestra tabla (es un poco
pequeña, pero podría ser todo lo grande
que quisieramos, siempre que no desbordaramos la
memoria del ordenador o la capacidad del compilador),
vamos a buscar los días en los que la afluencia
es mayor de 1.000 personas, para saber si es necesario
contratar a mas personal para esos días.
Pero para complicar un poco mas el asunto, vamos a meter
dichos días en otra tabla y así aprendemos
a trabajar con mas de una tabla a la vez.
WORKING-STORAGE
SECTION. 01
DIASEMANA. 02
GENERO OCCURS
2 TIMES. 03
VISITA PIC 9(4) OCCURS
7 TIMES. 01 TABLA1000. 02
ELEMENTOS1000 OCCURS 7 TIMES. 02
DIA1000 PIC
9. 02
VISITAS1000 PIC 9(4). 01 SUB1
PIC
9. 01 SUB2 PIC
9. 01 SUB3 PIC
9. 01 TOPE PIC
9. 01 OP PIC
X. 01 LGENERO PIC X(7). ... PROCEDURE
DIVISION. INICIO. DISPLAY
"BUSCANDO DIAS DE MAS DE 1000 VISITAS"
LINE
2 COL 10 ERASE. MOVE
0 TO SUB1 SUB2. BUSCAR. ADD
1 TO SUB1 IF SUB1 > 7 GO MOSTRAR. COMPUTE
TOTAL = VISITAS (1, SUB1) + VISITAS
(2,SUB1). IF
TOTAL > 1000 ADD
1 TO SUB2 MOVE SUB1 TO DIA1000 (SUB2) MOVE
TOTAL TO VISITAS1000 (SUB2). GO
BUSCAR. MOSTRAR. MOVE
SUB2 TO TOPE MOVE 0 TO SUB2. MOSTRAR1. ADD
1 TO SUB2 IF SUB2 > TOPE GO FIN. DISPLAY
"EL " LINE 10 COL 29. MOVE
DIA1000 (SUB2) TO SUB3. DISPLAY
TSEM (SUB3) LINE 10 COL 37. DISPLAY
VISITAS1000 (SUB2) LINE 10 COL 50. GO
MOSTRAR1. FIN. DISPLAY
"PROCESO DE BUSQUEDA FINALIZADO" LINE
20 COL 20. ACCEPT
OP LINE 20 COL 1. ...
|
MAS TABLAS
Voy a poner algunos ejemplos de definición de tablas mas complicados que los expuestos en los ejemplos.
01
TABLA. 02
TRABAJADORES 03
NOMBRE 03
NIF 03
SALARIO 05
BRUTO 05
NETO 05
GASTOS 07
GASTO
|
OCCURS
100 TIMES. PIC X(30). PIC X(10). OCCURS
12 TIMES. PIC S9(8). PIC S9(8). OCCURS
10 TIMES. PIC S9(8).
|
Los valores para esta tabla sería:
- 100
TRABAJADORES de los que tendríamos
NOMBRE y NIF referidos como NOMBRE (X)
y NIF (X).
- A
su vez tendríamos un salario
por mes (12). Descritos con dos variables
BRUTO Y NETO a los que nos referiríamos
como BRUTO (CLIENTE, MES) y NETO (CLIENTE,
MES).
- Y
también 10 tipos de gastos por
cliente y mes referidos como GASTO (CLIENTE,
MES, TIPO).
Como véis se puede complicar cuanto se quiera:
- Para saber el nombre del trabajador número
49: DISPLAY NOMBRE (49). - Para saber el Nif del trabajador
20: DISPLAY NIF (20). - Para saber el bruto de Mayo del trabajador
15: DISPLAY BRUTO (15, 5). - Para saber el neto del trabajador
90 del mes de Noviembre: DISPLAY NETO (90, 11).
- Para saber el gasto número 3 del mes de Febrero del trabajador 10: DISPLAY
GASTO (10, 2, 3).
TABLAS DE LONGITUD VARIABLE.
Podemos
definir también una tabla con un número
de elementos variable, dependiendo del valor de
una variable. Su definición sería
así:
01
MES 01
SEMANA. 02
VISTAS
|
PIC 99.
PIC
9(4) OCCURS
28 TO 31 DEPENDING OF MES.
|
INDEXACION.
Además
podemos asignar una variable por la cual nos referiremos
a cada elemento, esto se hace añadiendo
a la línea que contiene la cláusula OCCURS, la palabra INDEXED seguida del nombre de
variable que deseemos. La ventaja es que no hay
que definirla en la WORKING. En nuestro ejemplo
le pondremos de nombre DIA y quedaría asi:
|
PIC
9(4) OCCURS 7 TIMES INDEXED DIA.
|
La gran
ventaja de utilizar este método, es que no
hay que definir esa variable, no hay que controlar
los rangos y además el valor no se alterará
ya que no utilizaremos esa variable para nada mas.
Para
dar valor a éste tipo de variables hay que
utilizar la sentencia SET, ya que no se pueden utilizar los comandos normales
ni declaraciones aritméticas, con el siguiente
formato:
SET DIA TO 1. Da el valor 1 al índice 1.
SET DIA UP 3. Suma 3 al valor del índice.
SET DIA DOWN 2. Resta 1 al valor del índice 2.
Además también utilizamos la indexación para hacer busquedas en las tablas mediante la sentencia SEARCH.
Antes hemos visto como buscar utilizando un contador y unos IF para verificar lo que buscamos. Pero Cobol tiene
una sentencia específica para buscar un valor en una tabla. Esta sentencia se llama SEARCH.
Si imaginamos una tabla de trabajadores y queremos encontrar la posición en concreto que ocupa
uno o saber si existe en la tabla haremos lo siguiente:
01
TABLA. 02
TRABAJADORES OCCURS
100 TIMES INDEXED
BY SUB1. 03
NOMBRE PIC
X(30). 03
NIF PIC
X(10). ... PROCEDURE DIVISION. ... BUSCAR. SET
SUB1 TO 1. SEARCH
ELEMENTOS AT END GO NOEXIS WHEN
NOMBRE (SUB1) = "ANDRES MONTES" GO
EXISTE. NOEXIS. DISPLAY
"TRABAJADOR INEXISTENTE" LINE
1. GO
FIN. EXIS. DISPLAY
"EL NIF DEL TRABAJADOR ES ."
LINE 2. DISPLAY
NIF (SUB1) LINE 2 COL 30. ... |
Primero inicializamos la variable de indexación para que empiece por el elemento 1, pero podiamos haber
escogido el valor que quisieramos, si le hubieramos dado uno fuera de rango, simplemente la instrucción hubiera saltado al párrafo NOEXIS
indicado en el AT END.
La sentencia SEARCH a continuación crea un bucle hasta que se cumpla la condición dada. Si no la encuentra
realiza la instrucción que haya despues de AT END. Podemos poner todas las condiciones con
WHEN que queramos y se irán ejecutanto en el orden en que se hayan puesto.
También existe la posibilidad de hacer una busqueda total de la tabla con la cláusula ALL
en la sentencia SEARCH, se denomina busqueda binaria.
Esta fórmula es mas utilizada en tablas mas grandes. Aquí no hay que preocuparse por el valor del subíndice, el comando se encarga de todo.
Pero solo podremos poner una condición WHEN y además el elemento de la tabla por el que
se busque debe de estar clasificado y especificado en la WORKING con la opción
ASCENDING o DESCENDING. Veamos un ejemplo:
01
TABLA. 02
TRABAJADORES OCCURS
100 TIMES ASCENDING
KEY NOMBRE INDEXED
BY SUB1. 03
NOMBRE PIC
X(30). 03
NIF PIC
X(10). ... PROCEDURE DIVISION. ... BUSCAR. SEARCH
ALL ELEMENTOS AT END GO NOEXIS WHEN
NOMBRE (SUB1) = "ANDRES MONTES" GO
EXISTE. NOEXIS. DISPLAY
"TRABAJADOR INEXISTENTE" LINE
1. GO
FIN. EXIS. DISPLAY
"EL NIF DEL TRABAJADOR ES ."
LINE 2. DISPLAY
NIF (SUB1) LINE 2 COL 30. ... |
La diferencia en cuanto a programación es mínima,
pero el sistema tarda menos en la busqueda y no
tenemos que tener en cuenta el inicializar el contador.
Por el contrario es necesario tener ordenada nuestra
tabla y esto a veces no sea tan rentable.
Obviamente cada una de éstas formas de buscar en Tablas
son opciones que ofrece el lenguaje Cobol. Supongo
que como en todo lo que se buscaba al principio
era limitar los tiempos de respuesta, puesto que
las máquinas eran muy pequeñas y tenían
pocos rendimientos, de ahí que ésta
orden se haya visto inalterada desde el principio.
Cada uno puede utilizar la forma que mejor se le de, la que mejor entienda o la que mejor haga su cometido.
Seguramente se podría haber hablado mucho mas de tablas, pero lo importante y lo que pretendía con éste capítulo, era que comprendiérais
el porque de una tabla y su uso mas frecuente.
|
|