Spielerei: BitArray für Nullen und Einsen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Shardik
Beiträge: 746
Registriert: 25.01.2005 12:19

Beitrag von Shardik »

NicTheQuick hat geschrieben: Für alle, die etwas Speicherplatz sparen wollen und wenn es nur um Einsen oder Nullen geht
Sehr schönes Beispiel für unlimitierte Bit-Arrays!!! Ich habe vor geraumer Zeit ein ähnliches Beispiel geschrieben, das allerdings nur mit einem Long-Wert zur Speicherung von 32 Bits arbeitet, dafür aber optimiert in Assembler:

Code: Alles auswählen

Procedure ClearFlag(FlagBit.L)
  !MOV EAX,[ESP+4]
  !BTR DWORD[v_Flags],EAX
EndProcedure


Procedure SetFlag(FlagBit.L)
  !MOV  EAX,[ESP+4]
  !BTS  DWORD[v_Flags],EAX
EndProcedure


Procedure GetFlag(FlagBit.L)
  !PUSH EBX
  !XOR  EAX,EAX
  !MOV  EBX,DWORD[ESP+8]
  !BT   DWORD[v_Flags],EBX
  !JNC  $+3
  !INC  EAX
  !POP  EBX
  ProcedureReturn 
EndProcedure


Global Flags.L

i.L

Debug "Test ClearFlag() - alle Flags der Reihe nach löschen"
Flags = $FFFFFFFF
Debug "Flags = " + Hex(Flags)

For i = 0 To 31
  ClearFlag(i)
  Debug "Flags = " + RSet(Hex(Flags), 8, "0")
Next i

Debug "-----"
Debug "Test SetFlag() - alle Flags der Reihe nach setzen"
Flags = 0
Debug "Flags = " + RSet(Hex(Flags), 8, "0")

For i = 0 To 31
  SetFlag(i)
  Debug "Flags = " + RSet(Hex(Flags), 8, "0")
Next i

Debug "-----"
Debug "Test GetFlag() - alle Flags der Reihe nach testen"

Flags = $C0000013

Debug "Flags = " + Hex(Flags)

For i = 0 To 31
  Debug "Flag " + Str(i) + " = " + Str(GetFlag(i))
Next i
Der Vorteil dieses Verfahrens besteht darin, daß man bis zur 32 Flags in einem Wert in einer Konfigurationsdatei (z.B. Ini-Datei) sehr bequem speichern und wieder einlesen kann. Ich benutze z.B. folgende Flags für einen von mir programmierten FTP-Client:

Code: Alles auswählen

Enumeration
  #DownloadMayOverwriteFile
  #DownloadStripEOL
  #EOLCharIsCRLF              ; 0 = LF, 1 = CRLF
  #RemoveTrailingBlanks
  #TransferModeIsASCII        ; 0 = Binary, 1 = ASCII
  #UploadMayOverwriteFile
  #PCCharSetIsASCII           ; 0 = ANSI, 1 = ASCII
  #DownloadAppendsToFile
  #UploadMayOverwriteMember
  #UploadAppendsToFile
  #UploadAppendsToMember
EndEnumeration
und kann dann sehr bequem über die Bit-Konstantennamen auf das entsprechende Flag zugreifen:

Code: Alles auswählen

If GetFlag(#RemoveTrailingBlanks) = #True
  ...
End If
Außerdem kann ich in einer erweiterten Programmversion noch weitere Konstanten in die Enumeration hinten anfügen, solange deren Default-Wert 0 ist, ohne daß schon bestehende Ini-Dateien unbrauchbar werden (die Abwärtskompatibilität ist für meine Anwender sehr wichtig!). In einer Übertragungsliste meines FTP-Programms kann der Anwender viele verschiedene Dateitransfers speichern, die unterschiedlichste Parameter aufweisen können, z.B. die erste Datei überschreibt die Server-Datei, die nächste Datei wird an eine andere Server-Datei angehängt, oder nach einem Upload erfolgt direkt ein Download usw. Für jede vom Anwender vorgegebene Übertragung in der abgespeicherten Übertragungsliste braucht so immer nur ein Long-Wert mit den Flags gespeichert werden.