Buchempfehlung
Windows System Programming
Windows System Programming
Das Kompendium liefert viele interessante Informationen zur Windows-Programmierung auf Englisch. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Code-Beispiel

Code-Beispiele » Kleine Helferlein

BIT-Feld (BitArray), viele Ein/Aus-Schalter mit Index

Lizenz:Erster Autor:Letzte Bearbeitung:
k. A.MitgliedTJF 23.05.2011

Dieses Beispiel betrifft BitArrays, also viele Ein/Aus-Schalter (= boolsche Werte oder boolean) in einer Feld-Variablen und ist für alle Betriebssysteme anwendbar (dos / windows / UNIX / LINUX).

BitArrays können einerseits in einer TYPE-Struktur zusammengefasst werden, z. B. durch

TYPE Schalter
  AS INTEGER Rot : 1
  AS INTEGER Blau : 1
END TYPE

und dann mit aussagekräftigen Namen im Quelltext verwendet werden. Andererseits eignet sich diese Lösung jedoch nur bedingt, wenn sehr viele Schalter vorhanden sind und diese in Programm-Schleifen abgefragt oder verändert werden sollen. Hier ist es vorteilhaft, die Schalter über einen Index auswählen zu können.

Der folgende Quelltext erzeugt ein UDT (= TYPE-Struktur) zur Speicherung eines beliebig großen BIT-Feldes. Er sollte unter dem Namen BitArray.bas abgespeichert werden.

' This is file BitArray.bas, a UDT for variable length arrays of bits
' (C) 2011 by Thomas[ dot ]Freiherr[ at ]gmx{ dot }net
' License LGPLv 2
'
' Note: index is zero based (allways)

#DEFINE BitArrayError(_V_) ?"BitArray error: Index out of range (" & _V_ & ")"

TYPE BitArray
  DECLARE CONSTRUCTOR(BYVAL N AS UINTEGER = 0, BYVAL V AS UBYTE = 0)
  DECLARE PROPERTY Bit_(BYVAL I AS UINTEGER, BYVAL B AS INTEGER)
  DECLARE PROPERTY Bit_(BYVAL I AS UINTEGER) AS INTEGER
  DECLARE SUB Redim_(BYVAL N AS UINTEGER = 0, BYVAL V AS UBYTE = 0)
  DECLARE SUB Xor_(BYVAL I AS UINTEGER = 0)
  DECLARE FUNCTION Ubound_() AS UINTEGER
Private:
  AS STRING Store
  AS UINTEGER Maxi, Ubo
END TYPE

CONSTRUCTOR BitArray(BYVAL N AS UINTEGER = 0, BYVAL V AS UBYTE = 0)
  Ubo = N
  Maxi = N SHR 3
  Store = STRING(1 + Maxi, V)
END CONSTRUCTOR

PROPERTY BitArray.Bit_(BYVAL I AS UINTEGER) AS INTEGER
  VAR p = I SHR 3
  IF p > Maxi THEN BitArrayError(I) : RETURN 0
  RETURN BIT(Store[p], I - (p SHL 3))
END PROPERTY

PROPERTY BitArray.Bit_(BYVAL I AS UINTEGER, BYVAL B AS INTEGER)
  VAR p = I SHR 3, x = I - (p SHL 3)
  IF p > Maxi THEN BitArrayError(I) : EXIT PROPERTY
  IF B THEN Store[p] = BITSET(Store[p], x) : EXIT PROPERTY
  Store[p] = BITRESET(Store[p], x)
END PROPERTY

SUB BitArray.Redim_(BYVAL N AS UINTEGER = 0, BYVAL V AS UBYTE = 0)
  VAR ln = N SHR 3
  IF ln > Maxi THEN
    Store &= STRING(ln - Maxi, V)
  ELSE
    Store = LEFT(Store, ln + 1)
  END IF
  Ubo = N
  Maxi = ln
END SUB

SUB BitArray.Xor_(BYVAL I AS UINTEGER = 0)
  VAR p = I SHR 3, x = I - (p SHL 3)
  IF p > Maxi THEN BitArrayError(I) : EXIT SUB
  IF BIT(Store[p], x) THEN Store[p] = BITRESET(Store[p], x) : EXIT SUB
  Store[p] = BITSET(Store[p], x)
END SUB

FUNCTION BitArray.Ubound_() AS UINTEGER
  RETURN Ubo
END FUNCTION

Anwendung

Beispiel1 (Modulebene)

' This is file BitArrayTest.bas, an example for BitArray.bas
' (C) 2011 by Thomas[ dot ]Freiherr[ at ]gmx{ dot }net
' License GPLv 3

#INCLUDE "BitArray.bas"

#IFNDEF __FB_UNIX__
SCREEN 13
#ENDIF

'#DEFINE english

' used to print out headers and values
#MACRO HEADER(_G_, _E_)
 #IFDEF english
   ?:?_E_
 #ELSE
   ?:?_G_
 #ENDIF
#ENDMACRO
#DEFINE SHOW(_V_, _I_) PRINT #_V_ & ".Bit_(" & _I_ & ") = " & _V_##.Bit_(_I_)

HEADER("BitFeld erzeugen jeden zweiten Wert setzen", _
       "Create a BitArray, set each second values")
CONST Az = 19
VAR Test = BitArray(Az, &b01010101)
FOR i AS INTEGER = 0 TO Az
  SHOW(test, i)
NEXT

HEADER("Fuenf zufaellig ausgewaehlte BITs anzeigen:", _
       "Show five randomly choosen values")
FOR j AS INTEGER = 0 TO 4
  VAR i = INT(RND * (Az + 1))
  SHOW(test, i)
NEXT

HEADER("Bei einem zu grossen Index erfolgt eine Fehlermeldung:", _
       "Error message in case of out-ranged index:")
SHOW(test, Az + 8)

HEADER("Ein BIT veraendern", _
       "Change a value")
' this doesn't work, since fbc cannot handle the index
'   Test.Bit_(i) XOR= Test.Bit_(i)
VAR i = Az SHR 1
SHOW(test, i)
'Test.Bit_(i) = Test.Bit_(i) XOR -1
Test.Xor_(i)
SHOW(test, i)

HEADER("Eine Kopie des BitFeldes erzeugen:", _
       "Create a copy of the BitArray:")
VAR neu = test
SHOW(neu, i)

HEADER("Die Groesse des neu-BitFeldes reduzieren, alle BITs anzeigen:", _
       "Reduce the neu BitArray and show all values:")
neu.Redim_(7)
FOR i AS INTEGER = 0 TO neu.Ubound_()
  SHOW(neu, i)
NEXT

HEADER("Die Groesse des neu-BitFeldes wieder erhoehen, alle BITs anzeigen:", _
       "Increment the neu BitArray and show all values:")
neu.Redim_(11, &b11111111) ' sets all new values
FOR i AS INTEGER = 0 TO neu.Ubound_()
  SHOW(neu, i)
NEXT


#IFNDEF __FB_UNIX__
SLEEP
#ENDIF

Beispiel2 (in TYPE Struktur)

' This is file BitArrayTest2.bas, an example for BitArray.bas
' (C) 2011 by Thomas[ dot ]Freiherr[ at ]gmx{ dot }net
' License GPLv 3

#INCLUDE "BitArray.bas"

'#DEFINE english

#MACRO SHOW(_V_, _G_, _E_)
  #IFDEF english
    ?_E_
  #ELSE
    ?_G_
  #ENDIF
  FOR i AS UINTEGER = 0 TO _V_.Ubound_()
    ?_V_.Bit_(i); " ";
  NEXT : ?
#ENDMACRO


TYPE UDT
  DECLARE SUB Operate()
  AS BitArray Publ = BitArray(24, &b10101010) ' 24 bits, second set
Private:
  AS BitArray Priv = BitArray(9, &b11111111) '   9 bits, all set
END TYPE

SUB UDT.Operate()
  CLS
  SHOW(Publ, "Das öffentliche (PUBLIC) BIT-Feld (Vorgabe jedes 2. BIT ein)", _
             "The public bit array (every second bit set on init)")

  Publ.Redim_(Publ.Ubound_() SHR 1)
  SHOW(Publ, "Verkleinere auf die Hälfte", _
             "decrease the entries to half")

  ?
  SHOW(Priv, "Das verborgene (PRIVATE) BIT-Feld (Vorgabe BITs ein)", _
             "The private bit array (all bits set on init)")

  Priv.Redim_(Priv.Ubound_() SHL 1, &b11111111)
  SHOW(Priv, "Die Anzahl der Eintraege verdoppeln (neue BITs ein)", _
             "double the entries (new bits set)")

  FOR i AS INTEGER = 0 TO Priv.Ubound_() STEP 3
    Priv.Xor_(i)
  NEXT
  SHOW(Priv, "Jedes dritte BIT umschalten", _
             "switch every third bit")

  ?
  VAR neu = Priv
  SHOW(neu, "Eine Kopie des verborgenen Feldes", _
            "A copy of the private bit array")
END SUB


#IFNDEF __FB_UNIX__
SCREEN 13
#ENDIF


' ***  main  ***

DIM AS UDT test
test.Operate()


? : ? : ?"Ein BIT ausserhalb der TYPE-Struktur / A bit outside the UDT"
VAR n = 7
?test.Publ.Bit_(n)
'   Die Folgezeile kompiliert nicht (error 175: Illegal member access)
'   next line doesn't compile (error 175: Illegal member access)
'?test.Priv.Bit_(n)


#IFNDEF __FB_UNIX__
SLEEP
#ENDIF

Anmerkungen

English

This example is about an UDT for creating an array of boolean values (BITs) and can be used on all platforms.

BIT arrays can be done by defining a TYPE-structure like

TYPE Schalter
  AS INTEGER Rot : 1
  AS INTEGER Blau : 1
END TYPE

and the BITs can be used in the source by their meaningful names. But it's not sufficiant when you need to use a large number of BITs in a loop. In this case you may want to refer to the BITs by an index. Here's one way how to do so.

The first second block generates an UDT to store a variable length bit array. It should be saved as file BitArray.bas.

Usage

The third (Beispiel1) and fourth (Beispiel2) code blocks show examples on how to use it.

Anotations


Zusätzliche Informationen und Funktionen
  • Das Code-Beispiel wurde am 08.05.2011 von MitgliedTJF angelegt.
  • Die aktuellste Version wurde am 23.05.2011 von MitgliedTJF gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen