miércoles, 26 de enero de 2011

WORKING-STORAGE: definiendo variables.

Las variables que se usan en un programa cobol deben haber sido previamente definidas en la WORKING-STORAGE SECTION.

Existen diferentes tipos de variables en cobol. Cada variable que definamos debe terminar con un punto ".".
Si la variable va a tener un valor inicial lo indicaremos con la cláusula VALUE.

Alfanuméricas: se indican con un PIC X(número de caracteres). Podrán tener como valores números y letras.

01 WX-VARIABLE-ALFNUM PIC X(10) VALUE 'LOQUESEA10'.


Numéricas normales: se indican con un PIC 9(número de dígitos). Sólo tendrán valor numérico. La V indica la coma decimal.

01 WX-VARIABLE-NUM PIC 9(5)V9(2) VALUE 12345,67.
(value sin las comillas)

Numéricos comprimidos: se indican con un PIC 9(número de dígitos) COMP-3. Sólo valores numéricos. Estas variables ocuparán, en espacio, menos que un numérico normal.
El cálculo de longitudes lo veremos más adelante. La S indica que lleva signo decimal que puede ser positivo o negativo.

01 WX-VARIABLE-COMP3 PIC S9(5)V9(2) COMP-3 VALUE 12345,67.


Numéricos hexadecimales: se indican con un PIC 9(número de dígitos) COMP. Sólo valor numérico. OJO! Aceptan letras porque el número va en formato hexadecimal, pero eso no significa que podamos informarlas con caracteres alfabéticos.

01 WX-VARIABLE-COMP PIC 9(5)V9(2) COMP VALUE 12345,67.


Editados: se indican con la cláusula PIC seguida por tantas "zetas" Z como necesitemos. Se utilizan para dar formato a campos numéricos.

01 WX-VARIABLE-EDI PIC -Z.ZZZ.ZZ9,99.


Esto equivaldría a un campo numérico PIC S9(7)V9(2). El último dígito antes de la coma decimal se indica con un 9 para que aparezca el valor numérico del 0 al 9. Las Zs sustituirán los "ceros" 0 a la izquierda por espacios.

01 WX-VARIABLE-NUM PIC S9(7)V9(2) VALUE -0001234,56.
01 WX-VARIABLE-EDI PIC -Z.ZZZ.ZZ9,99

DISPLAY 'WX-VARIABLE-NUM:'WX-VARIABLE-NUM

MOVE WX-VARIABLE-NUM TO WX-VARIABLE-EDI

DISPLAY 'WX-VARIABLE-EDI:'WX-VARIABLE-EDI


El resultado sería:
WX-VARIABLE-NUM:00012345O
WX-VARIABLE-EDI:-    1.234,56



Si queremos que el signo aparezca pegado al número, podemos definir el campo editado de la siguiente manera:
01 WX-VARIABLE-EDI PIC -.---.--9,99.

Para que se muestre como "-1.234,56".

Ahora que sabemos definir variables, vamos a ver que las variables pueden estar definidas en diferentes "niveles". Estos niveles vienen indicados por un número a la izquierda:

01 WX-INFORMACION-PERSONA.
   05 WX-NOMBRE    PIC X(10).
   05 WX-APELLIDO1 PIC X(10).
   05 WX-APELLIDO2 PIC X(10).
   05 WX-DIRECCION.
      10 WX-CALLE  PIC X(10).
      10 WX-NUMERO PIC 9(3).
      10 WX-PISO   PIC 9(2).

Y así sucesivamente.

Si tenemos algún subnivel que sea una constante, en lugar de ponerle nombre al campo podemos utilizar la cláusala FILLER:

01 WX-FECHA.
   05 WX-DIA PIC 9(2).
   05 FILLER PIC X VALUE '-'.
   05 WX-MES PIC 9(2).
   05 FILLER PIC X VALUE '-'.
   05 WX-ANO PIC 9(4).


La diferencia del FILLER con un campo "con nombre", es que el FILLER no se puede utilizar para "mover" la información que contenga. Es un campo fijo (la traducción sería "RELLENO") que no se puede informar (a no ser que informásemos el nivel superior y nos cargásemos todo, claro... xd).
El resultado del campo informado sería por ejemplo:
Fecha = 01-01-2011

Existe una forma de definir variables con dos o más tipos de formato (PIC) distintos. Se trata de la cláusula REDEFINES.
Se suele utilizar para evitar mover campos alfanuméricos a numéricos, o bien para agrupar un campo que tenga subniveles:

01 WX-CAMPO1 PIC X(3).
01 WX-CAMPO2 REDEFINES WX-CAMPO1 PIC 9(3).

01 WX-CAMPO1.
   05 WX-SUBCAMPO1 PIC X(3).
   05 WX-SUBCAMPO2 PIC 9(5).
01 WX-CAMPO2 REDEFINES WX-CAMPO1 PIC X(8).


IMPORTANTE: sólo se pueden "redefinir" campos que estén al mismo nivel, es decir, para redefinir un campo de un nivel 01, tendremos que hacerlo en otro campo de nivel 01.

También podemos definir tablas o arrays:
01 WX-TABLA-INTERNA OCCURS 5 TIMES.
   05 WX-CAMPO1 PIC X VALUE 'A'.
   05 WX-CAMPO2 PIC X VALUE 'B'.


De tal manera que el conjunto de los campos 1 y 2 se repiten 5 veces:
ABABABABAB

Existen otro tipo de niveles que son los niveles "88":
01 WX-RESPUESTA   PIC X.
   88 RESPUESTA-SI      VALUE 'S'.
   88 RESPUESTA-NO      VALUE 'N'.


De tal forma que la variable WX-RESPUESTA podrá tomar los valores S ó N según queramos.
Para hacer que la variable tome un valor:

SET RESPUESTA-SI TO TRUE
   tomará el valor S.
SET RESPUSETA-NO TO TRUE    tomará el valor N.

Imaginemos que tenemos una serie de campos que definen la estructura de un fichero. Si tenemos varios programas que usan ese fichero, tendremos que escribir esos campos tantas veces como programas tengamos. Para ahorrarnos trabajo tenemos la cláusula COPY.
Una "COPY" es un trozo de código cobol que puede contener la definición de variables (COPY de WORKING) o una parte del código del programa (COPY de PROCEDURE):

COPY WORKING
Se incluirán dentro de la WORKING-STORAGE.
COPY WSCOPY.

Donde WSCOPY contendrá algo de este estilo:
01 WX-WSCOPY.
   05 WX-CAMPO1 PIC X(5).
   05 WX-CAMPO2 PIC X(5).
   05 WX-CAMPO3 PIC X(5).
   05 WX-CAMPO4 PIC X(5).


COPY PROCEDURE
Se incluirán dentro de la PROCEDURE DIVISION.
COPY PDCOPY.

Donde PDCOPY contendrá algo de este estilo:
MOVE WX-CAMPO1 TO WX-REGISTRO1
MOVE WX-CAMPO2 TO WX-REGISTRO2
MOVE WX-CAMPO3 TO WX-REGISTRO3
MOVE WX-CAMPO4 TO WX-REGISTRO4
MOVE WX-CAMPO5 TO WX-REGISTRO5



CÁLCULO DE LONGITUDES

Numéricos y alfanuméricos: lo que venga indicado en el PIC X(n) ó PIC 9(n) respectivamente.

01 WX-VARIABLE-ALFNUM PIC X(5).
01 WX-VARIABLE-NUM    PIC 9(5).

longitud = 5

Numéricos COMP-3: si tenemos un PIC 9(n) COMP-3, la longitud será (n+1)/2. Si el resultado tiene decimales redondeamos hacia arriba. Hay que tener en cuenta que la coma decimal no ocupa espacio, y que el signo ocupa sólo media posición.

01 WX-VARIABLE-COMP3 PIC S9(5) COMP-3.

longitud = (5 + 1)/2 = 3

Numéricos COMP:
Un campo con PICTURE numérica y COMP se almacena en formato binario puro (base 2); el signo lo representa el bit de la derecha. El número de bytes que se reservan en memoria para cada campo es:
2 posiciones para números de 1 a 4 dígitos.
4 posiciones para números de 5 a 9 dígitos.
8 posiciones para números de 10 a 18 dígitos.

01 WX-VARIABLE-COMP PIC 9(5) COMP.

longitud = 4


VISUALIZANDO CAMPOS

Como ya hemos comentado, existen campos en cobol q no se ven "tal cual", como son los comprimidos o los hexadecimales. Vamos a ver como se verían en un fichero estos campos:

----+----1----+----2----+----3----+----4
999999999          q Íì%      00000  S 
FFFFFFFFF444444444493716000000FFFFF00E2
99999999900000000008265C000000000000122
----------------------------------------


* El campo que va de la posición 1 a la 9 sería un campo numérico normal con valor 999999999.
* El campo que va de la posición 10 a la 19 sería un campo alfanumérico con valor '         ' (9 espacios).
* El campo que va de la posición 20 a la 24 sería un campo numérico COMP-3 con valor 983276156 positivo (letra C, letra D para negativos*).
* El campo que va de la posición 25 a la 30 sería un campo informado con low-values.
* El campo que va de la posición 31 a la posición 35 sería un campo informado con 5 ceros 00000.
* El campo que va de la posición 36 a la 39 sería un campo numérico COMP con valor 1E222 (en hexadecimal) / 123426(en decimal).

*Para campos numéricos con signo del tipo S9(3)V99, podemos distinguir el signo fijándonos en la última posición:
A = +1
B = +2
C = +3
D = +4
E = +5
F = +6
G = +7
H = +8
I = +9
J = -1
K = -2
L = -3
M = -4
N = -5
O = -6
P = -7
Q = -8
R = -9
{ = +0
} = -0


En el próximo artículo veremos la PROCEDURE DIVISION, donde se codifica la "miga" del programa. Veremos como informar campos, como inicializarlos y como codificar bucles y condiciones.

29 comentarios:

Anónimo dijo...

Jejeje, en Marzo hablamossss.
Perdonar, pero no estoy de acuerdo con el cálculo propuesto para los campos binarios COMP.
Opción COMPUTATIONAL

Un campo con PICTURE numérica y COMP se almacena en formato binario puro (base 2); el signo lo representa el bit de la derecha. El número de bytes que se reservan en memoria para cada campo es:

2 posiciones para números de 1 a 4 dígitos.
4 posiciones para números de 5 a 9 dígitos.
8 posiciones para números de 10 a 18 dígitos.

Con esta opción se ahorra memoria (almacena un número de 3 o 4 cifras en 2 bytes).

Un saludo.

P.D: Me ha gustado mucho la página.

A seguir de ferrari a sueldo de seiscientos jejejej

Tallian dijo...

Donde estabas tú cuando escribimos esto eh?? jaja
Pues ahora mismo lo "actualizo".
Ya que estás puedes ir preparando el artículo de la query dinámica en pli!jajaja

Anónimo dijo...

Entonces que longitud tiene un PIC S9(16)V9(2) COMP-3.

Gracias.

Tallian dijo...

Pues como se explica en la sección de numéricos COMP-3: n+1/2
En tu caso:
16+2=18
(18+1)/2=9,5
Redondeamos hacia arriba así que medirá 10 posiciones : )

Anónimo dijo...

Gracias, de acá tomé algo q me sacó de un apuro

Solo es un pequeño comentario jeje. la expresión n+1/2 debería ser escrita (n+1)/2 por prioridad de operadores. con n+1/2 se ejecutaría primero la división

XD Saludos

Tallian dijo...

Jajaja, ok, le pongo los paréntesis ^^

Anónimo dijo...

Exelente explicaciòn para el calculo de longitudes en los diferentes formatos.Gracias.
E. Nunes (Caracas Venezuela)

Tallian dijo...

Añadido campos editados, que se nos habían quedado olvidados...

Nueva dijo...

Sobre datos COMP y COMP-3, tengo varias dudas:
1. No entiendo la parte "Para campos numéricos con signo del tipo S9(3)V99, podemos distinguir el signo fijándonos en la última posición"
2. ¿cómo se distinguen los decimales en formato COMP?
3. ¿cómo se escribe el signo en formato COMP?

muchas gracias!

Tallian dijo...

Hola Nueva! Bienvenida al Consultorio : )
Vamos por orden:
1. Para campos numéricos con signo, que no estén comprimidos, al visualizarlos, el último dígito será una letra o un corchete "{/}". Esta letra nos indicará el signo y el valor del último dígito, según está indicado en la tabla.
Por ejemplo, para un S9(3)V9(2) con valor -155,22:
1552K
La coma decimal no se ve.

2. Los decimales no se distinguen en ninguno de los formatos, porque la coma decimal no ocupa posición. Sabrás cuáles son al ver el formato del campo en cuestión.
En los campos COMP, tendrás que pasarlos de hexadecimal a decimal con la calculadora para ver el valor.

3. El signo no se distingue. El valor del campo (signo incluido) lo verás al pasar de hexadecimal a decimal con una calculadora^^

Espero haberte aclarado las dudas!

Anónimo dijo...

Gracias, por subir información como esta!

De verdad que me ha servido mucho!

Felicidades!

Anónimo dijo...

POdrian subir la definicion de File Section lo necsito urgente :(

Tallian dijo...

Hola Anónimo.
La FILE SECTION es el lugar donde se definen los ficheros del programa, con su estructura, su longitud, el tipo de longitud (fija o variable). Puedes verlo en:
http://www.consultoriocobol.com/2011/01/esquema-de-un-programa-cobol.html
O bien ver ejemplos de uso en los artículos:
http://www.consultoriocobol.com/2011/02/ejemplo-2-leer-de-sysin-y-escribir-en.html
http://www.consultoriocobol.com/2011/02/ejemplo-3-leer-de-fichero-y-escribir-en.html
http://www.consultoriocobol.com/2011/03/ejemplo-4-generando-un-listado.html

Anónimo dijo...

Una duda,
Pero el signo sin ser un campo comprimido como se cuenta? Es decir un PIC S9(9) cuanto ocupa?

Muchas gracias, la página es de mucha ayuda.

Tallian dijo...

Hola anónimo (y perdón por no haber contestado antes).
El signo ocupa solo media posición, por lo que la última posición cambiará dependiendo del valor y del signo. Tienes la lista de equivalencias al final del artículo (A = +1, B = +2, etc.).
La longitud sería la que indica el PIC, en tu caso 9 posiciones : )
Ej.- 01 WX-CAMPO1 PIC S9(9) VALUE +123456789.
En un fichero se vería: 12345678I
Ocupando 9 posiciones.

Chicote dijo...

Me encanta la página chicos, pasé de programar en Cobol hace 17 años con la cabeza loca a la construcción (un intervalo de 17 años), ahora con la empresa de carpinteria destruida me muevo nuevamente hacia el viejo COBOL.Gracias...

Anónimo dijo...

Gracias por la información, en general. Saludos a todos

Anónimo dijo...

Buenas, tengo una duda técnica, ¿Se le puede mover LOW-VALUES a un COMP? Estoy editando el fichero con HEX ON pero al meterle:
0000
0000 le mete el valor 0.

Se que es incongruente mover un LOW-VALUES a un numérico, pero lo pide el cliente...

Tallian dijo...

Hola Anónimo, el problema es que al ser un campo COMP, el valor está en hexadecimal, y por eso interpreta el 0.
Lo que intentas hacer solo es válido para los numéricos COMP-3.

Para un COMP tendría que hacer la prueba de moverle LOW-VALUES a ver como se ve.... :P

Anónimo dijo...

Hola!! tengo una pregunta si es que pueden ayudarme, Se pueden realizar operaciones aritméticas con campos editados??

Loboc dijo...

No puedes usar variables numéricas editadas en expresiones aritméticas o en ADD, SUBTRACT, MULTIPLY, DIVIDE o COMPUTE. Pero eso tiene muy fácil solución, con declarar una variable no editada para realizar las operaciones aritméticas y luego moverla de nuevo a la editada solucionado.

Anónimo dijo...

Según lo que indican arriba:
2 posiciones para números de 1 a 4 dígitos.
4 posiciones para números de 5 a 9 dígitos.
8 posiciones para números de 10 a 18 dígitos.

01 WX-VARIABLE-COMP PIC 9(5) COMP.

Si tengo mi variable comp definida de largo 19, ¿eso cuanto vale?

Tallian dijo...

Hola anónimo.
No puedes definir variables numéricas de más de 18 posiciones... da error al compilar.

Kraken dijo...

Hola Tallian, gracias por la pagina.

Tengo un problema que no lo veo por ningún lado, necesito pasar una variable alfanumerica de 8 posiciones a un S9(5)V9(3) USAGE COMP-3.

El alfanumerico puede venir como 12345.00 o 0
-0.99900 o 123.2000.

No consigo convertirlo. Gracias de antemano, un saludo

Tallian dijo...

Hola Kraken.
El alfanumérico que indicas, veo que no siempre lleva formato S9(5)V9(3) (viendo la posición del punto decimal).
Si es así, lo mejor es hacerlo "a mano".
Con un bucle, te recorres posició a posición tu campo alfanumérico hasta encontrar la coma o el punto.
De esa forma tendrás localizada la parte entera y la parte decimal.
Es muy largo de explicar el ejemplo por aquí. Si puedes manda un mail a consultoriocobol@gmail.com y te lo pongo entero.

Gracias!

.. dijo...

Hola buenos días , alguien sabe, cual es la mejor forma de definir campos numéricos en cobol (para darle agilidad al programa) formatos numérico normal (display) , empacados en comp-3 o binario como comp, internamente cual es la mejor forma de que sea mas optimo algún programa cobol con estas definiciones ? y si es preferible "empacar" campos numericos (comp o comp-3) de cierta longitud minima o desde la longitud de 1 es optimo ??? Muchas Gracias ...

Kuruynzi dijo...

Hola, una consulta: Si tengo una variable(Fecha1) proveniente de una fecha DATE del DB2 con el formato PIC S9(08) y otra variable(Fecha2) ingresada por un Data Entry con formato PIC 9(08) con la misma fecha podemos concluir que las dos variables son iguales? ¿Son diferentes?. Es decir puedo decir Fecha1 = Fecha2 sin ningún problema?

Jose Adan Felipe Morales dijo...
Este comentario ha sido eliminado por el autor.
Nicolas Quiñones dijo...

Hola, estoy tratando de revisar en un antiguo programa en cobol, donde se declara una funcion que me alerta con error al ingresar el año 2017 dentro del programa, estoy tratando de buscar esa validacion para cambiar o eliminar, alguien sabe como puedo encontrarla?

De verdad que me ayudarian un monton. Muchas gracias.