En este artículo vamos a analizar las diferentes formas que ofrece COBOL de hacer búsquedas en tablas
Recordemos que una tabla es cualquier variable definida con más de una ocurrencia o que pertenece a un grupo de nivel superior con más de una ocurrencia.
Por ejemplo, supongamos una tabla que almacene nombres de personas definida así:
01 TABLA. 05 FILAS OCCURS 20. 10 NOMBRE PIC X(15). 10 APELLIDO PIC X(30).
Para buscar a una persona por apellido, podríamos emplear un bucle construido con un PERFORM VARYING. Tendríamos que definir en Working Storage una variable numérica para utilizarla como índice y un switch o indicador que permita saber si el apellido se ha encontrado no.
01 WS-IND PIC 9(2) COMP. 01 WS-APELLIDO PIC X(30) VALUE “GARCIA”. 01 SW-INDICADOR PIC X VALUE SPACES. 88 NO-ENCONTRADO VALUE “N”. 88 ENCONTRADO VALUE “S”. SET NO-ENCONTRADO TO TRUE PERFORM VARYING WS-IND FROM 1 BY 1 UNTIL WS-IND > 20 OR ENCONTRADO IF APELLIDO(IND) = WS-APELLIDO SET ENCONTRADO TO TRUE END-IF END-PERFORM IF NO-ENCONTRADO DISPLAY “Apellido no econtrado” END-IF
El bloque de código anterior se podría simplificar con el uso de la instrucción SEARCH, que nos evita tener que declarar un índice explícitamente y resulta más legible. Tendríamos que cambiar la definición de la tabla para incluir el índice en la misma, de forma que quedara así:
01 TABLA. 05 FILAS OCCURS 20 INDEXED BY IND. 10 NOMBRE PIC X(15). 10 APELLIDO PIC X(30).
Este tipo de índices asociados a la tabla tienen una representación interna especial, por lo que solo es posible modificar su valor mediante la instrucción SET. No se pueden utilizar en operaciones aritméticas ni en un DISPLAY. En una búsqueda con SEARCH solo hay que especificar el valor del índice en el que queremos que se empiece a buscar.
La búsqueda anterior quedaría de este modo con SEARCH:
SET NO-ENCONTRADO TO TRUE SET IND TO 1 SEARCH FILAS AT END DISPLAY “Apellido no encontrado” WHEN APELLIDO(IND) = WS-APELLIDO SET ENCONTRADO TO TRUE END-SEARCH
La condición lógica del WHEN se irá evaluando para todos los elementos de la tabla hasta que sea verdadera o se llegue al final. Si se ha llegado al último elemento sin cumplirse la condición, se ejecutará la instrucción indicada en el AT END.
Como hemos comentado, las búsquedas anteriores implican recorrer todos los elementos de la tabla hasta encontrar el buscado. Existe una forma más eficiente de buscar en tablas llamada búsqueda binaria (instrucción SEARCH ALL), que utiliza un algoritmo especial. Su inconveniente es que requiere que la tabla esté ordenada por un campo clave. Además, los elementos vacíos deben contener HIGH-VALUES si el orden es ascendente o LOW-VALUES si es descendente. Si no se cumplen estos requisitos, la búsqeda devolverá resultados incorrectos.
Para evitar este último requisito, podemos utilizar la cláusula DEPENDING ON, que permite definir un campo numérico para almacenar número de elementos informados de la tabla. Si actualizamos el valor de este campo al añadir elementos, no será necesario llenar el resto de la tabla con HIGH-VALUES o LOW-VALUES.
Este ejemplo de definición de tabla nos permitiría hacer búsqueda binaria sin necesidad de inicializar la tabla con HIGH-VALUES o LOW-VALUES.
01 MAX-TABLA PIC 9(2). 01 TABLA. 05 FILAS OCCURS 1 TO 20 DEPENDING ON MAX-TABLA ASCENDING KEY IS APELLIDO INDEXED BY IND. 10 NOMBRE PIC X(15). 10 APELLIDO PIC X(30).
Hemos indicado orden ascendente. Para orden descendente se utilizaría DESCENDING KEY IS.
En el código de la búsqueda habría que cambiar SEARCH por SEARCH ALL y se puede quitar la inicialización del índice porque se hace automáticamente. El campo MAX-TABLA debe contener la posición del último elemento informado.
SET NO-ENCONTRADO TO TRUE SEARCH ALL FILAS AT END DISPLAY “Apellido no encontrado” WHEN APELLIDO(IND) = WS-APELLIDO SET ENCONTRADO TO TRUE END-SEARCH
Tengo una tabla interna (tabla1) de 100 occures e índice IND-C con un campo CODIGO y otra tabla interna (tabla2) de 100 occures e índice IND-D con dos campos, uno CODIGO y el otro DESCRIPCION. Tengo que coger cada código de la tabla 1 y buscar su definición en la tabla2.
Soy nueva codificando en COBOL y no se cómo hacerlo.
Es una rutina online.
Gracias
Un saludo
SE ENTREGA A CONTINUACIÓN, UNA POSIBLE SOLUCIÓN, MUY SIMPLIFICADA PARA LO QUE CONSULTA MONICA.
QUIEN LO DESARROLLA, VIVE EN LA CIUDAD DE VALPARAISO, V REGION DE VALPARAISO, CHILE.
SET LIM-IND-C TO CT-MAX-ELEM-VECTOR-1.
SET LIM-IND-D TO CT-MAX-ELEM-VECTOR-2.
PERFORM RECORRIDO-EN-VECTORES-REL THRU FIN-RECORRIDO-EN-VECTORES-REL.
RECORRIDO-EN-VECTORES-REL.
PERFORM RECORRER-VECTOR-1 THRU FIN-RECORRER-VECTOR-1
VARYING IND-C FROM CT-1 BY CT-1
UNTIL IND-C > LIM-IND-C
END-PERFORM.
FIN-RECORRIDO-EN-VECTORES-REL.
EXIT.
RECORRER-VECTOR-1.
MOVE CODIGO-1 (IND-C) TO WS-CODIGO-ARG.
SET IND-D TO CT-1.
SEARCH ALL WS-VECTOR-2
AT END
DISPLAY ‘ARGUMENTO ‘, WS-CODIGO-ARG, ‘ NO ENCONTRADO EN VECTOR 2’
PERFORM CANCELAR-PROCESO
GOBACK
WHEN CODIGO-2 (IND-D) = WS-CODIGO-ARG
DISPLAY ‘CODIGO ‘, WS-CODIGO-ARG ‘ ENCONTRADO ‘, DESCRIPCION-2 (IND-D)
END-SEARCH.
EXIT.
POR SUPUESTO ESTA ES LA PARTE MINIMA, DE UNA SOLUCIÓN AL PROBLEMA PLANTEADO.
NO HAY QUE OLVIDAR QUE PARA CADA PROBLEMA, HAY ‘N’ SOLUCIONES, O SEA, UN CONJUNTO SOLUCIÓN.
EL ARREGLO NÚMERO 2 DEBE ESTAR ESTRICTAMENTE ORDENADO EN FORMA ASCENDENTE, CON LOS ELEMENTOS NULOS (SI LOS HAY), RELLENADOS CON NUEVES. ES LA UNICA FORMA QUE FUNCIONE SEARCH ALL (BUSQUEDA BINARIA O POR BISECCION DE INTERVALOS).
HAY QUE DEFINIR TODAS LAS CONSTANTES A SER UTILIZADAS, IDEALMENTE PARA LO NUMÉRICO, COMO PACKED-DECIMAL O COMP-3, CON NUMERO IMPAR DE DIGITOS.
LO ANTERIOR EVITA CONVERSIONES Y RECONVERSIONES DE DATOS, QUE DESPERDICIAN RECURSOS DE MAQUINA, DE ALMACENAMIENTO, OVERHEAD, ETC.