viernes, 30 de enero de 2015

Manejando bits con Harbour

En esta entrada del blog usaremos algunas de las funciones para operar con números binarios que nos aporta Harbour.
No entrare a explicar porque se usa el sistema binario en los ordenadores (supongo que como programadores es un tema que conocéis), y solo explicare brevemente el sistema binario, si ya lo conoces puedes saltarte el siguiente párrafo.
El sistema binario es un sistema de numeración en el cual los números se representan utilizando las cifras 0 y 1 . Cada dígito de un número en este sistema se denomina bit y al igual que en base 10 (el que utilizamos habitualmente), el valor depende de la posición donde se halla.
Veamos un ejemplo y nos quedará más claro:

Normalmente la manipulación de binarios queda reducida a la programación a bajo nivel, y en el resto de programación podemos sobrevivir sin manipular bits. Pero para poder ilustrar el uso de alguna de las funciones de manejo de bits de Harbour, os propondré el uso de binarios para la gestión de estatus, variables lógicas que solo puedan ser verdadero o falso, en nuestro caso 0 o 1.

Estos campos estatus habitualmente los solucionamos mediante el uso de campos lógicos, o tipo carácter de una posición grabando S o N, según corresponda. El tamaño de estos campos, o variables, es de 1 Byte (es el tamaño mínimo que podemos definir), pero 1 Byte son 8 bits, con lo cual el valor grabado en 1 Byte nos permite identificar hasta 8 estatus diferentes.

 Imaginemos que en una factura deseamos controlar varios estatus:
  • Tiene IVA
  • Tiene Recargo de Equivalencia
  • Esta cobrada
  • Esta impresa
  • Es un contado
  • Factura Rectificativa
Toda esta información podemos grabarla en un solo campo carácter de una posición, y aun nos sobra para dos estatus más.
Crearemos una tabla llamada FraCab que entre otros atributos, contendrá uno llamado Estatus del tipo carácter y de una posición.
Para el ejemplo trabajaremos sobre un único registro, y dispondremos de controles CheckBox para poder activar o desactivar nuestros estatus, que se grabaran en un campo de una sola posición.
Los ocho estatus los manejaremos mediante un Hash, por comodidad las tablas hash y algunas otras variables las he definido como estáticas al proyecto para no tener que pasarlas como parámetros.

Leeremos el campo estatus de la tabla y asignaremos a cada posición del hash el valor lógico que le corresponda. 
 Para este fin usamos la función hb_BitTest( nParam, nBit )→ lResult , le pasamos como primer parámetro el valor ascii de nuestro campo estatus y como segundo el número de bit que deseamos leer. hb_BitTest nos devuelve un valor lógico dependiendo si dicho bit vale uno o cero.


Una vez que hemos recuperados los valores de cada uno de los estatus, dibujamos el dialogo que nos permitirá ver y modificar los valores.

Para su modificación usamos controles CheckBox, que en el evento onChange, actualizan el campo, y refrescan los valores de la pantalla.
Esta es la función encargada de actualizar los valores

Recibe como parámetro la clave del hash, busca cual es su posición y lo graba en la variable nPos, esto nos permite saber que bit es el que debemos manipular.
Y procedemos a calcular el valor del nuevo estatus en función de si es falso o verdadero, mediante el uso de las funciones hb_BitSet y hb_BitGet
hb_BitSet( nParam1, nBit ) → nResult Retorna el entero resultante de activar el bit nBit en el entero nParam1
hb_BitReset( nParam1, nBit ) → nResult Retorna el entero resultante de desactivar el bit nBit en el entero nParam1.

Como podéis ver, necesitamos el código ASCII para pasar a la función de manipulación de bits, y convertimos el número obtenido a su valor ASCII, para ello usamos las funciones Asc() y Chr().

Este ejemplo ha sido programado usando FWH 15.01, Harbour 3.2.0 y BCC 5.82. Para su correcto funcionamiento es necesario linkar la libreria hbMisc.lib

Descarga código fuente
Descarga exe comprimido

 Espero que os haya resultado interesante, si además podéis extrapolarlo y hacer uso en algún caso práctico mucho mejor. Y en el peor de los casos deseo que os haya servido para conocer algunas de las funciones que incorpora Harbour y que no solemos utilizar frecuentemente.
Agradezco comentarios y sugerencias, saludos desde Mallorca.

Por cierto, en http://harbouradvisor.blogspot.com.es/2012/02/funciones-para-manipular-bits.html de mi amigo Carlos Mora, podéis encontrar una explicación de todas las funciones para manejo de bits que nos proporciona Harbour.