Búsquedas en tablas de COBOL

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úsuqeda devolverá resultados incorrectos.

Para poder utilizar la búsqueda binaria, habría que modificar la definición de la tabla para añadir el campo clave:

01 TABLA.
   05 FILAS OCCURS 20 
              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.

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

 

2 comentarios sobre Búsquedas en tablas de COBOL

  • Mónica

    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

  • JORGE AZOCAR GARCIA

    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.

Deja un comentario