Freitag, 5. Februar 2010

Text in binäre Zeichenkette wandeln ... und umgekehrt / Converting text to binary string ... and vice versa

Als regelmäßiger Besucher des Universalthread (UT) war mir bereits seit geraumer Zeit aufgefallen, dass eine der Teilnehmerinnen (Hi Tc ;-)) eine interessante Signatur benutzt:

010000110101001101101000011000010111001001110000010011110111001001000010011101010111001101110100

Wird diese Signatur in 8er Blöcke zerlegt und anschließend in Zeichen umgewandelt, dann kommt ein Text heraus, der in einem VFP Forum ein wenig provokant erscheinen könnte... ;-)

Um meine eigene Signatur zu verändern habe ich mir spaßeshalber zwei kleine Routinen geschrieben, von denen die eine Funktion einen solchen Binärstring in Klartext umwandelt und die andere einen beliebigen Text als Binärstring liefert.

Wieso nur fällt mir gerade jetzt der alte Spruch ein ... von den 10 Arten von Menschen. Diejenigen welche das binäre Zahlensystem kennen und solche die es nicht kennen...

12.03.2010 UPDATE:
Heute hat mir Agnes Beste über UT eine knuffige Ergänzung zu meinen beiden Funktionen gemailt die ich mit ihrer Erlaubnis gerne in diesem Eintrag ergänze.

Hier nun der erweiterte Beispielcode, der übrigens (immer noch) nicht Tc's Signatur nutzt ;-):

LOCAL lcBinString as String, lcChrString as String
lcBinString=[0110011101100101011101000101011001000110010100000010011001101000011000010111011001100101011001100111010101101110]
lcChrString=Bin2Char(lcBinString)
?lcChrString

* // Begin of Agnes' Code --------------
lnI   = 0x000109C1
lcBin = Int2Bin(lnI)
lcNib = Int2Nibble(lnI)
lnBin = Bin2Int(lcBin)
lnNib = Nibble2Int(lcNib)

?lnI,TRANSFORM(lnI,[@0])
?lcBin,lnBin,TRANSFORM(lnBin,[@0])
?lcNib,lnNib,TRANSFORM(lnNib,[@0])

FUNCTION Nibble2Int AS INTEGER
LPARAMETERS tcString as String
    RETURN Bin2Int(CHRTR(tcString,[ ],[]))
ENDFUNC

FUNCTION Bin2Int AS INTEGER
LPARAMETERS tcString as String
    RETURN INT(VAL(STUFF(TRANSFORM(0h+Bin2Char(PADL(tcString,32,[0]))),2,1,[x])))
ENDFUNC 

FUNCTION Int2Nibble AS STRING
LPARAMETERS tiInt as Integer
    RETURN STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(Int2Bin(tiInt),29,0,[ ]),25,0,[ ]),21,0,' '),17,0,' '),13,0,' '),09,0,' '),05,0,' ')
ENDFUNC

FUNCTION Int2Bin AS STRING
LPARAMETERS tiInt as Integer
    RETURN Char2Bin(EVALUATE(STUFF(TRANSFORM(tiInt,[@0]),2,1,[h])))
ENDFUNC
* // End of Agnes' Code ----------------

FUNCTION Char2Bin as String
LPARAMETERS vString
    LOCAL i as Integer, ii as Integer, liChar as Integer, lcReturn as String
    lcReturn = []
    * // Byteweise Verarbeitung des übergebenen Strings            
    FOR i = 1 TO LEN(vString)
        * // Auslesen eines Zeichens und direktes wandeln in den
        * // entsprechenden numerischen Wert des ASCII-Tabelle    
        * // Bspw: A = 65, B = 66, ...                            
        liChar = ASC(SUBSTR(vString,i,1))
        * // Auf Basis des ermittelten ASCII-Wertes erfolgt nun    
        * // die BIT-weise Abfrage der Zahl.                    
        * // Bspw. A = 65 = 01000001                            
        * // Da die Anzeige von links nach rechts erfolgt, die    
        * // Bits jedoch von rechts nach links adressiert werden
        * // erfolgt die Verarbeitung abwärts                    
        FOR ii = 7 TO 0 STEP -1        
            lcReturn = lcReturn + IIF(BITTEST(liChar,ii),[1],[0])
        ENDFOR 
    ENDFOR 
    RETURN lcReturn
ENDFUNC 

FUNCTION Bin2Char as String
LPARAMETERS vString
    LOCAL i as Integer, ii as Integer, lcChar as String, liValue as Integer, lcReturn as String
    STORE [] TO lcChar, lcReturn
    * // Je 8 Zeichen ergeben ein vollwertiges Byte, somit ist    
    * // eine Verarbeitung in 8er Schritten notwendig            
    FOR i = 0 TO (LEN(vString) / 8) - 1
        * // 8er Block auslesen                                 
        lcChar = SUBSTR(vString,1 + (i * 8),8)
        * // Zielvariable initialisieren. Wert ist hierbei egal    
        liValue = 0
        * // Auch hier besteht das Problem, das Bits von rechts    
        * // nach links gesetzt werden, jedoch am Bildschirm    
        * // von links nach rechts dargestellt werden            
        * // Dieses Problem löst die ABS() Funktion, wodurch    
        * // der bei der Substraktion von 8 auf den aktuellen    
        * // Schleifenwert die resultierende negative Zahl vom    
        * // Vorzeichen befreit wird. aus -7 wird dadurch 7        
        FOR ii = 1 TO 8
            liValue = IIF(SUBSTR(lcChar,ii,1) = [1],BITSET(liValue,ABS(ii - 8)),BITCLEAR(liValue,ABS(ii - 8)))
        ENDFOR 
        * // Nun die berechnete Zahl in das korrespondierende    
        * // ASCI Symbol umwandeln und dem Ergebniswert anhängen
        lcReturn = lcReturn + CHR(liValue)
    ENDFOR 
    RETURN lcReturn
ENDFUNC 

Montag, 1. Februar 2010

FoxyPreviewer

Cesar Chalom hat in seinem Blog ein neues Projekt vorgestellt. Es handelt sich hierbei um eine Druckvorschau Bibliothek, mit deren Hilfe jede Menge Funktionalität im Bereich der Vorschau sowie der nachfolgenden Verarbeitung bereitgestellt wird. Unbedingt mal reinschauen: http://weblogs.foxite.com/vfpimaging/archive/2010/01/31/10127.aspx