Instr. de Variables
Daré cabida en esta sección a la explicación de todas las instrucciones que hacen referencia a las variables y sus valores. Como todas, este grupo de instrucciones tiene su vital importancia en la programación y son usadas habitualmente.



MOVE, es la instrucción que usaremos para enviar datos de una variable a otra u otras.
Lo que en realidad hace es que la una variable adquiera un valor determinado, ya sea procedente de otra variable o bien desde un valor fijo o constante.

Estos son los dos formatos que posee:

Formato 1:

MOVE variable, valor TOvariable, variable, variable, ....


    Con el primer formato las variables que siguen al TO tomarán el dato de la variable o del valor que le preceden. De todo se verá al final una serie de ejemplos bien detallados.
    Siempre tendremos una serie de normas o restricciones para asegurarnos de que los valores han pasado correctamente.

  • Los campos numéricos siempre se van a alinear a la derecha, respetando la posición del punto decimal si lo hubiera. Si la variable que recibe el campo es mas pequeña, evidentemente se perderán los que no quepan y si es mas grande el resto se pondrá a ceros.
  • Si además el campo al que se mueven los datos es de edición, al hacer el paso del valor, este a su vez se formateará con la edición declarada en la WORKING.
  • Si son alfanuméricos la alineación se efectuará a la izquierda a menos que se haya especificado en la WORKING, al definirla, una justificación a la derecha (JUST RIGHT). Al igual que en los numéricos si es mas pequeño se perderán los caracteres que no quepan y si es mas grande el resto irá relleno de espacios en blanco.

  • ...
    WORKING-STORAGE SECTION.
    77  NUMERO1   PIC 9(6).
    77  NUMERO2   PIC 9(8)V99.
    77  NUMERO3   PIC ZZZ.ZZZ,ZZ.
    77  TEXTO1     PIC X(15)  VALUE "LENGUAJE COBOL".
    77  TEXTO2     PIC X(10).
    77  TEXTO3     PIC X(20) JUST RIGHT.
    ...
    PROCEDURE DIVISION.
    INICIO.
           MOVE 1536 TO NUMERO1.
           MOVE NUMERO1 TO NUMERO2 NUMERO3.
           MOVE TEXTO1 TO TEXTO2 TEXTO3.
    ...

    Nota:
    Después de aplicar estas sentencias, éste sería el resultado:


         NUMERO1=001536
         NUMERO2=0000153600 (La coma decimal es virtual)
         NUMERO3=  1.536,00

         TEXTO1=LENGUAJE COBOL
         TEXTO2=LENGUAJE C
         TEXTO3=      LENGUAJE COBOL



    Formato 2:

    MOVE CORR Identificador1 TO Identificador2

    Agregando CORR a la instrucción conseguimos mover de una sola vez un valor entre identificadores siempre que los campos que contengan tengan el mismo nombre. Estos identificadores no pueden ir en niveles 66, 77 ni 88. El efecto es el mismo que si hicieramos tantos MOVE normales como campos iguales tuviera el identificador. No es muy usual, pero si hay casos en los que puede ser razonable su uso.

    No es necesario que tengan el mismo PIC, ni que estén en el mismo orden, solo que coincidan en su nombre.

    ...
    WORKING-STORAGE SECTION.
    01  DATOS1.
         02  NOMBRE   PIC X(30).
         02  REGION   PIC X(20).
         02  PAIS       PIC X(15).
    01  DATOS2.
         02  PAIS       PIC X(10).
         02  REGION    PIC X(10).
         02  NOMBRE   PIC X(10).
    ...
    PROCEDURE DIVISION.
    INICIO.
           MOVE "ANDRES MONTES" TO NOMBRE IN DATOS1.
           MOVE "ANDALUCIA" TO REGION IN DATOS1.
           MOVE "ESPAÑA" TO PAIS IN DATOS1.
           MOVE CORR DATOS1 TO DATOS2.
    ...

    Nota:
    Para partir con unos valores, primero los he movido a las variables del primer grupo (DATOS1). Después de aplicar el MOVE CORR, el valor de las variables de DATOS2 sería:

         DATOS2:
            PAIS=ESPAÑA
            REGION=ANDALUCIA
            NOMBRE=ANDRES MON


    Fijaros que aunque el orden ni el tamaño era el mismo, el resultado es el que queríamos.
    INITIALIZE, se utiliza para inicializar variables según su descripción, es decir pondrá a ceros todas las variables numéricas o de edición y a espacios en blanco las alfabéticas y alfanuméricas. No funciona con campos definidos como FILLER, (evidente). Y puede ser muy útil para inicializar tablas completamente cuando nos referimos al nivel mas alto de la misma.

    ...
    WORKING-STORAGE SECTION.
    77  TEXTO PIC X(10) VALUE "HOLA MUNDO".
    77  NUMERO PIC 9(8) VALUE "12345678".
    ...
    PROCEDURE DIVISION.
    INICIO.
         INITIALIZE TEXTO NUMERO.
    ...

    Nota:
    Después de hacer INITIALIZE el valor de TEXTO será igual a espacios y el de NUMERO igual a ceros.

    Es el mismo resultado que utilizar MOVE haciendo uso de las CONSTANTES FIGURATIVAS que vimos en la Introducción de los manuales:

           MOVE SPACES TO TEXTO.
           MOVE ZEROS TO NUMERO.

    El resultado es el mismo en ambos casos, pero en el segundo teníamos que saber de que tipo eran las variables para moverles SPACES o ZEROS, mientras que en el primer caso, es el compilador quien se encarga se saber el tipo de la variable.



    INSPECT, esta sentencia se utiliza para contar, reemplazar o contar y reemplazar caracteres o grupos de caracteres dentro de un campo. Se puede contar las veces que aparece un caracter, o cambiar todos esos caracteres por otros, etc ...

    Esta instrucción tiene formatos diferentes según lo que se desee hacer, así que vamos a ver cada uno de ellos por separado.

    Formato 1:

    INSPECT campo1
            TALLYING variable1 FOR ( CHARACTERS)
              (( BEFORE/AFTER) INITIAL) Cadena1
                       (ALL)(LEADING) Cadena2 ...
               (Se puede repetir de nuevo)

    Este formato es el utilizado para contar el número de veces que aparece Identificador1 en el campo1 y guardará el valor en la variable1 que previamente hayamos definido en la WORKING.

    • CHARACTERS, indica que cuente todos los caracteres del campo incluso los espacios en blanco.
    • ALL, indica que tiene que buscar en todos los caracteres del campo, la cadena especificada en Cadena2.
    • LEADING, indica que tiene que buscar la cadena especificada en Cadena2, pero solo hasta que encontremos uno diferente, si nada mas empezar es diferente el resultado sera directamente 0.
    • BEFORE INITIAL, busca solo hasta que aparezca la cadena especificada como Cadena1.
    • AFTER INITIAL, empieza a buscar justo después de la cadena especificada en Cadena1.


    Veamos unos ejemplos para salir de dudas. Primero vamos a definir una WORKING-STORAGE.

    ...
    WORKING-STORAGE SECTION.
    77  TEXTO PIC X(15) VALUE "PAGINA DE COBOL".
    77  CONTA PIC 9(8).
    ...
    PROCEDURE DIVISION.
    INICIO.
         INSPECT TEXTO TALLYING CONTA FOR CHARACTERS.
    ...
    El valor de conta será de 15 que son los caracteres que tiene la variable TEXTO.

         INSPECT TEXTO TALLYING CONTA FOR ALL "A".
    ...
    El valor de conta será de 2 que son las veces que aparece la letra A en la variable TEXTO.

         INSPECT TEXTO TALLYING CONTA FOR LEADING "A".
    ...
    El valor de conta será de 0 porque no aparece ninguna A en el primer carácter de la variable TEXTO.

          INSPECT TEXTO TALLYING CONTA FOR ALL "A"
                        BEFORE INITIAL "N".
    ...
    El valor de conta será de 1 que son las veces que aparece la letra A en la variable TEXTO hasta la aparición del caracter N.

         INSPECT TEXTO TALLYING CONTA FOR ALL "A"
                       AFTER INITIAL "G".
    ...
    El valor de conta será de 1 que son las veces que aparece la letra A en la variable TEXTO, empezando a contar desde el caracter G.

    Formato 2:

    INSPECT campo1
           REPLACING variable1 CHARACTERS BY Cambio1
             (( BEFORE/AFTER) INITIAL)
    Cadena1
                      (ALL)(LEADING)( FIRST) Cadena2...
            (Se puede repetir de nuevo)

    Con este formato podemos cambiar caracteres de Campo1, su funcionamiento es igual que el anterior formato solo que en vez de contar reemplaza. Se ha incluido solo FIRST, que indicaría que solo se reemplazaría la primera vez que coincidieran las condiciones. El tamaño de la sustitución debe de ser igual al tamaño sustituido, ya que la variable campo1 no puede cambiar su tamaño.

    ...
    WORKING-STORAGE SECTION.
    77  TEXTO PIC X(15) VALUE "PAGINA DE COBOL".
    77  CONTA PIC 9(8).
    ...
    PROCEDURE DIVISION.
    INICIO.
         INSPECT TEXTO REPLACING CHARACTERS BY "H".
    ...
    El valor de TEXTO será "HHHHHHHHHHHHHHH", es decir cambia todos los caracteres por el caracter H.

         INSPECT TEXTO REPLACING ALL "A" BY "I".
    ...
    El valor de TEXTO será "PIGINI DE COBOL", es decir ha cambiado todas las A por I.

         INSPECT TEXTO REPLACING FIRST "A" BY "O".
    ...
    El valor de TEXTO será "POGINA DE COBOL", solo cambia la primera A por una O.

         MOVE "PAGIPATOPETOPA" TO TEXTO.
         INSPECT TEXTO REPLACING ALL "PA" BY "--"
                  AFTER INITIAL "G"  BEFORE INITIAL "T".
    ...
    Complicando un poco mas, el valor de TEXTO despueés de la sentencia INSPECT será PAGI--TOPETOPA, es decir se cambia todas las PA por -- pero empezando a buscar a partir de la primera letra G y justo hasta la letra T.

           MOVE "PAGIPATOPETOPA" TO TEXTO.
           INSPECT TEXTO TALLYING CONTA FOR ALL "PA"
                       REPLACING ALL "TO" BY "PO" AFTER INITIAL "OP".
    ...
    Aquí hemos mezclado ambos formatos y el resultado es el siguiente. El valor de CONTA es 3 que son las veces que aparece la cadena PA en TEXTO y después se ejecuta el REPLACING y el resultado da que TEXTO vale PAGIPATOPEPOPA, ya que ha cambiado todos los TO por PO pero después de la cadena OP.


    Formato 3:


    INSPECT
    campo1
            CONVERTING Identificador1 TO Identificador2
              (( BEFORE/AFTER) INITIAL) Cadena1 ...           (Se puede repetir de nuevo)

    Con este formato convertimos los caracteres que se especifiquen en identificador1 por los que pongamos en identificador2, respetando el orden.

    Veamos algunos ejemplos, se suele utilizar mucho para que al aceptar un campo nos de igual se ha sido introducido en mayúsculas o en minúsculas ya que lo convertiriamos a alguno de los formatos.

    ...
    WORKING-STORAGE SECTION.
    77  TEXTO PIC X(15) VALUE "PAGINA DE COBOL".
    ...
    PROCEDURE DIVISION.
    INICIO.
         INSPECT TEXTO CONVERTING "AO"TO "12".
    ...
    El valor de TEXTO será "P1GIN1 DE C2B2L", convertirá todas las A por 1 y todas las O por 2.

         INSPECT TEXTO CONVERTING               " ABCDEFGHIJKLMNÑOPQRSTUVWXYZ" TO
                    "abcdefghijklmnñopqrstuvwxyz".
    ...
    El valor de TEXTO será "pagina de cobol" ya que ha convertido todas las letras mayúsculas por minúsculas.


    Para finalizar con el comando INSPECT, decir que es un comando muy particular y cada uno deberá decidir en cada momento y con que situaciones utilizarlo.
    STRING, se utiliza para unir o concatenar campos o partes de estos y el resultado almacenarlo en otro campo. En la unión se pueden incluir tanto variables como literales o constantes de texto.

    STRING campo1, literal1
             DELIMITED BY (campo2, literal2)(SIZE)
               INTO
    Campo3
             (WITH POINTER Identificador1)
               ( ON OVERFLOW Sentencia1)
               ( NOT ON OVERFLOW Sentencia2)

    • DELIMITED BY, indica hasta donde vamos a "coger" del campo para concatenar sin contar ese caracter o cadena que se especifique en campo2 o literal2, es decir si tenemos un campo con un valor = "HOLA" y especificamos DELIMITED BY "L" a la hora de la concatenación nos hubiera cogido solo el HO, ya que al encontrarse la primera L hubiera parado.
    • SIZE, indica que se pasará todo el contenido del campo1 o literal1 sin limitaciones.
    • INTO, con esto indicamos en que variable se guardará el resultado, campo3.
    • WITH POINTER, si incluimos esta cláusula el valor de identificador1 será en la posición en que empezará a contener datos la variable que recibe el STRING. Ese identificador1 debe estar definido como binario. Por defecto el valor es 1.
    • ON OVERFLOW, se ejecutaría Sentencia1 si hubiera habido un error al hacer la concatenación, por ejemplo si se especifica Identificador1 con un valor superior al tamaño del Campo3.
    • NOT ON OVERFLOW, se ejecutará Sentencia2 si no existe error en la operación.

    Vamos a ver unos ejemplos y además vamos a comparar como se hubiera hecho utilizando la Working si no existiera el STRING.

    ...
    WORKING-STORAGE SECTION.
    01  LAFECHA.
         02  FILLER PIC X(7) VALUE "HOY ES ".
         02  LDIA    PIC Z9.
         02  FILLER PIC X(4) VALUE " DE ".
         02  LMES   PIC X(10).
         02  FILLER PIC X(4)  VALUE "DE ".
         02  LANIO  PIC 9999.
    01  FECHA.
         02  DIA    PIC 99 VALUE 22.
         02  MES   PIC 99 VALUE 06.
         02  ANIO  PIC 9999 VALUE 2001.
    01  CONSTRING PIC X(40).
    01  TABLAMES.
         02  FILLER PIC X(30) VALUE "ENERO     FEBRERO   MARZO      ".
         02  FILLER PIC X(30) VALUE "ABRIL      MAYO       JUNIO        ".
         02  FILLER PIC X(30) VALUE "JULIO      AGOSTO  SEPTIEMBRE".
         02  FILLER PIC X(30) VALUE "OCTUBRE NOVIEMBREDICIEMBRE ".
    01  LATABLA REDEFINES TABLAMES.
         02  TMES PIC X(10) OCCURS 12 TIMES.
    01  PUNTO PIC 9(4) BINARY.
    ...
    PROCEDURE DIVISION.
    INICIO.
          MOVE DIA TO LDIA.
          MOVE TMES (MES) TO LMES.
          MOVE ANIO TO LANIO.

          STRING "HOY ES " DIA " DE " TMES (MES) " DE " ANIO
                      DELIMITED BY SIZE INTO CONSTRING.
    ...

      El valor de LAFECHA sería: HOY ES 22 DE JUNIO       DE 2001.

      El valor de CONSTRING sería: HOY ES 22 DE JUNIO       DE 2001.

      Fijaros que el resultado es el mismo pero en cambio gracias a STRING no hemos tenido que definir ninguna linea en la WORKING ni tampoco tener que mover campos de unas variables a otras.

      La cláusula DELIMITED BY se ha puesto al final porque dicha cláusula se aplica a todos los campos que la preceden, si hubieramos querido coger otra limitación para un campo en concreto habría que haberlo especificado, por ejemplo vamos a afinar mas el ejemplo y conseguir que entre el mes JUNIO y el DE no exista mas que un espacio. En el ejemplo anterior ha unido los 10 caracteres que tiene la variable TMES.

     
      STRING "HOY ES " DIA " DE " DELIMITED BY SIZE
            TMES (MES) DELIMITED BY " "
            " DE " ANIO  DELIMITED BY SIZE INTO CONSTRING.

      El valor que tendrá ahora CONSTRING será el siguiente:
      HOY ES 22 DE JUNIO DE 2001.

      Como veis la diferencia está en los espacios que le sobran al mes, que al poner DELIMITED BY " " los ha evitado porque solo ha concatenado hasta que ha encontrado el primer caracter en blanco.

     
      MOVE 4 TO PUNTO.
      STRING "HOY ES " DIA " DE " DELIMITED BY SIZE
            TMES (MES) DELIMITED BY " "
            " DE " ANIO  DELIMITED BY SIZE INTO CONSTRING
            WITH POINTER PUNTO.

      El valor que tendrá ahora CONSTRING será el siguiente:
          HOY ES 22 DE JUNIO DE 2001.

      Es decir habrá empezado a concatenar a partir de la posición 4 del campo CONSTRING. Si el valor de CONSTRING previamente era espacios habría dejado 3 espacios en blanco y si hubiera sido cualquier otro hubiera respetado los 3 primeros caracteres que tuviera.
    UNSTRING, hace exactamente lo contrario de que hemos visto que hacía STRING, es decir divide el contenido de un campo en otros.

    UNSTRING campo1, literal1
           DELIMITED BY (campo2, literal2)(ALL)
             OR (campo2, literal2)(ALL)
              (Se puede repetir de nuevo)
             INTO Campo3, Campo4, ....
                  ( DELIMITER Identificador1)
                      ( COUNT Identificador2)
             (Se puede repetir de nuevo)
           (WITH POINTER Identificador3)
           (TALLYING Identificador4)
             ( ON OVERFLOW Sentencia1)
             ( NOT ON OVERFLOW Sentencia2)

    • DELIMITED BY, indica el límite hasta donde vamos cogiendo el campo1 para partirlo. Igual que en STRING, solo que con la función a la inversa.
    • OR, es igual que DELIMITED y se utiliza si hay varios delimitadores sobre los que buscar.
    • INTO, indica en que campo o campos se guardará la información que vaya fragmentando.
    • DELIMITER, va a contener en cada caso el elemento separador, si hemos incluido en DELIMITED varios, Identificador1 guardará el carácter que de los elegidos ha sido el causante de la fragmentación.
    • COUNT, cuenta el número de caracteres incluidos en la fragmentación.
    • DELIMITER y COUNT, se podrán usar si se ha especificado DELIMITED. Podemos usar tantos DELIMITER y COUNT como campos se vayan a crear en la fragmentación.
    • TALLYING, si especificamos esta opción la instrucción nos guardará en Identificador4 el número de campos que se han utilizado en la fragmentación.
    • POINTER, indica desde que posición va a ser examinado el campo que desea desfragmentar, por defecto su valor es 1, es decir desde el primer caracter.
    • ON OVERFLOW, se ejecutaría Sentencia1 si hubiera habido un error al hacer la operación.
    • NOT ON OVERFLOW, se ejecutará Sentencia2 si no existe error en la operación.

    Vamos a hacer lo contrario de antes y conseguir una fecha numérica de una frase con la fecha:

    ...
    WORKING-STORAGE SECTION.
    01  LAFECHA PIC X(30) VALUE "HOY ES 22 DE JUNIO DE 2001".
    01  FECHA.
         02  DIA    PIC 99.
         02  MES   PIC 99.
         02  ANIO  PIC 9999.
    01  CONSTRING PIC X(40).
    01  TABLAMES.
         02  FILLER PIC X(30) VALUE "ENERO     FEBRERO   MARZO      ".
         02  FILLER PIC X(30) VALUE "ABRIL      MAYO       JUNIO        ".
         02  FILLER PIC X(30) VALUE "JULIO      AGOSTO  SEPTIEMBRE".
         02  FILLER PIC X(30) VALUE "OCTUBRE NOVIEMBREDICIEMBRE ".
    01  LATABLA REDEFINES TABLAMES.
         02  TMES PIC X(10) OCCURS 12 TIMES.
    01  CONTA PIC 99.
    01  PALABRAS PIC 99.
    01  LETRAS PIC 99.
    01  TEXTOS.
         02  TEXTO1 PIC X(20).
         02  TEXTO2 PIC X(20).
         02  TEXTO3 PIC X(20).
         02  TEXTO4 PIC X(20).
         02  ELMES   PIC X(10).
    ...
    PROCEDURE DIVISION.
    INICIO.
          UNSTRING LAFECHA DELIMITED BY " "
              INTO TEXTO1 TEXTO2 DIA TEXTO3
                     ELMES COUNT LETRAS TEXTO4 ANIO.

          PERFORM VARYING CONTA FROM 1 BY 1
            UNTIL ELMES = TMES (CONTA) OR CONTA = 12
            TALLYING PALABRAS
            END-PERFORM    
    ...
      El valor de LAFECHA era: HOY ES 22 DE JUNIO DE 2001.

      Después de aplicar las instrucciones siguientes el contenido de los campos sería el siguiente:

        • TEXTO1 = HOY
        • TEXTO2 = ES
        • TEXTO3 = DE
        • TEXTO4 = DE
        • ELMES = JUNIO
        • DIA = 22
        • ANIO = 2001
        • FECHA = 22062001
        • LETRAS = 5
        • PALABRAS = 7

      La variable PALABRAS nos ha guardado el número de variables utilizadas en la fragmentación, en este caso 7. La variable LETRAS ha guardado el número de caracteres que ha cogido en la separación que ha guardado en ELMES, que han sido 5 (JUNIO). Podiamos haber puesto un COUNT para cada una.

      El PERFORM de después lo hemos hecho para encontrar en la tabla la posición que ocupaba el nombre del mes y así poder construir la variable FECHA completa en númerico.

    Vamos a hacer un ejemplo de como podríamos separar un nombre completo, por ejemplo para el nuevo modelo de la Seguridad Social (en España) y el sistema R.E.D.:

    ...
    WORKING-STORAGE SECTION.
    01  TEXTO PIC X(30) VALUE "MONTES ROBLES, ANDRES".
    01  APELLI1   PIC X(20).
    01  APELLI2   PIC X(20).
    01  NOMBRE PIC X(20).
    01  SEPARA   PIC X.
    01  SEGURIDAD.
         02  AP1 PIC XX.
         02  AP2 PIC XX.
         02  NOM PIC X.
    ...
    PROCEDURE DIVISION.
    INICIO.
          UNSTRING TEXTO DELIMITED BY " " OR ", "
              INTO APELLI1 APELLI2 NOMBRE.

    Aquí conseguimos separar cada apellido y el nombre en campos diferentes. (APELLI1, APELLI2, NOMBRE)

          MOVE APELLI1 TO AP1 MOVE APELLI2 TO AP2
          MOVE NOMBRE TO NOM.
    ...


    Aquí la variable SEGURIDAD tendría el valor: MOROA. Válido para el sistema RED.




    Este artículo proviene de Cobol en español
    http://www.escobol.com

    La dirección de esta noticia es:
    http://www.escobol.com/modules.php?name=Sections&op=viewarticle&artid=18