8 Bit zu 3 Bit | Bitaufteilung

  • Hallo Community! :)
    Ich sitze gerade an einem Problem wo ich absolute nicht weiterkomme. Und zwar möchte ich einen beliebigen String in ASCII Codes konvertieren und die ASCII Codes ins Dualsystem befördern. Das klappt soweit sehr gut. Dafür habe ich mir folgende Funktion geschrieben:

    Spoiler anzeigen
    [autoit]

    Func _AscToDua($sString)
    Local $asAsc = StringToASCIIArray($sString)
    Local $aiDua[UBound($asAsc)][8]
    Local $iA, $iB

    [/autoit] [autoit][/autoit] [autoit]

    For $iA = 0 To UBound($asAsc) - 1
    For $iB = UBound($aiDua, 2) - 1 To 0 Step - 1
    $aiDua[$iA][$iB] = Int(BitAND($asAsc[$iA], BitShift(1, $iB * -1)) <> 0)
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $aiDua
    EndFunc

    [/autoit]

    Wenn ich als String "AutoIt" übergebe, erhalte ich ein Array mit folgenden Zahlen im Dualsystem:

    Spoiler anzeigen
    Code
    A -> 10000010
    u -> 10101110
    t -> 00101110
    o -> 11110110
    I -> 10010010
    t -> 00101110

    Hier die praktische Anwendungsmethode:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $array = _AscToDua('AutoIt')
    _ArrayDisplay($array)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _AscToDua($sString)
    Local $asAsc = StringToASCIIArray($sString)
    Local $aiDua[UBound($asAsc)][8]
    Local $iA, $iB

    [/autoit] [autoit][/autoit] [autoit]

    For $iA = 0 To UBound($asAsc) - 1
    For $iB = UBound($aiDua, 2) - 1 To 0 Step - 1
    $aiDua[$iA][$iB] = Int(BitAND($asAsc[$iA], BitShift(1, $iB * -1)) <> 0)
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $aiDua
    EndFunc

    [/autoit]

    Nun wird es aber ein wenig kompliziert. Ich erhalte ja durch meine Funktion _AscToDua() ein Array. Dieses Array beinhaltet die ASCII Codes meines Strings pro Buchstabe im Dualsystem. Diese sind logischerweise 8 Bit / 1 Byte groß. Allerdings möchte ich diese 8 Bit nun in ein weiteres Array aufteilen, welches pro Index nur 3 Bit fasst. Diese Dualzahlen:

    Spoiler anzeigen
    Code
    10000010
    10101110
    00101110
    11110110
    10010010
    00101110

    Sollen jetzt in 3 Bit päcken aufgeteilt werden. Später würde das ganze dann so aussehen:

    Spoiler anzeigen

    Und genau hier hängt es... Ich finde einfach keine Lösung dazu...
    Bisher habe ich folgenden Ansatz:

    Spoiler anzeigen
    [autoit]

    Func _8To3Bit($ai8Dua)
    Local $ai3Dua[Ceiling(UBound($ai8Dua) / 3 * 8)][3]
    Local $iA, $iB

    [/autoit] [autoit][/autoit] [autoit]

    For $iA = 0 To UBound($ai3Dua) - 1
    For $iB = 0 To UBound($ai3Dua, 2) - 1
    ; Code
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $ai3Dua
    EndFunc

    [/autoit]

    Das war's aber auch schon. Ich hoffe ihr könnt mir einen Denkanstoß geben! --- Ich komme hier nicht weiter.
    LG. Make :)

    2 Mal editiert, zuletzt von Yjuq (30. April 2013 um 19:18) aus folgendem Grund: Kleiner - unter Umständen tragischer - Fehler in eines der Skripte. * Gefixt :D *

    • Offizieller Beitrag

    Da 8 auf 3 sowieso nicht geht brauchst du immer n*3 8er Pakete, sonst geht es ja nicht auf. Insofern halte ich das eh für wenig sinnhaft, da diese Bedingung deinen Ausgangsdaten vorgegeben werden muß. :huh:
    Aber um es in 3er Blöcke zu setzen:
    einfach alle 8er als String zusammenklöppeln und anschließend mit StringTrimLeft(STRING-8, 3) in 3er Blöcke zerlegen oder einfacher mit Regex "([10]{3})" zerlegen.

  • Probiere es mal damit:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $array = _AscToDua('AutoIt')
    $a3bit = StringRegExp($array[0][0], ".{3}", 3)
    _ArrayDisplay($a3bit)

    [/autoit] [autoit][/autoit] [autoit]

    Func _AscToDua($sString)
    Local $asAsc = StringToASCIIArray($sString)
    Local $aiDua[UBound($asAsc) + 1][8]
    Local $iA, $iB, $bin

    [/autoit] [autoit][/autoit] [autoit]

    For $iA = 0 To UBound($asAsc) - 1
    For $iB = UBound($aiDua, 2) - 1 To 0 Step - 1
    $aiDua[$iA + 1][$iB] = Int(BitAND($asAsc[$iA], BitShift(1, $iB * -1)) <> 0)
    $bin &= $aiDua[$iA + 1][$iB]
    Next
    Next
    $aiDua[0][0] = $bin
    Return $aiDua
    EndFunc

    [/autoit]

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Super, konnte es nun lösen! :P
    Vielen Dank BugFix! :D

    Spoiler anzeigen
    [autoit]

    Func _8To3Bit($ai8Dua)
    Local $ai3Dua[Ceiling(UBound($ai8Dua) / 3 * 8)][3]
    Local $iA, $iB, $sDual, $asDual

    [/autoit] [autoit][/autoit] [autoit]

    For $iA = 0 To UBound($ai8Dua) - 1
    For $iB = 0 To 7
    $sDual &= $ai8Dua[$iA][$iB]
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    $asDual = StringRegExp($sDual, '[01]{1,3}', 3)

    [/autoit] [autoit][/autoit] [autoit]

    For $iA = 0 To UBound($asDual) - 1
    $ai3Dua[$iA][0] = StringMid($asDual[$iA], 1, 1)
    $ai3Dua[$iA][1] = StringMid($asDual[$iA], 2, 1)
    $ai3Dua[$iA][2] = StringMid($asDual[$iA], 3, 1)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $ai3Dua
    EndFunc

    [/autoit]

    Edit:
    UEZ >> Sorry, hatte die Seite nicht refresht. ^^
    Danke auch an dir dass du mitgedacht hast! :P

  • Hi,

    Zitat

    Und zwar möchte ich einen beliebigen String in ASCII Codes konvertieren und die ASCII Codes ins Dualsystem befördern.

    verstehe ich und kann das auch nachvollziehen...
    Was ich absolut nicht verstehe ist der Umweg über die Arrays.
    Ein String IST bereits ein Array....zwar nicht ein zweidimensionales wie bei dir^^, aber ein Array!
    Wie du ja seltsamerweise in deiner Lösung per StringMid() gezeigt hast, ist dir dieser Befehl ja bekannt.

    Ok, hier nun mein Lösungsvorschlag.
    Als Standard wird ein 3-Bit-"Array" zurückgegeben, wenn man als zweiten Parameter eine Ziffer von 1 bis 8 eingibt, erhält man das entsprechende Array.

    Spoiler anzeigen
    [autoit]

    #include <array.au3> ;nur fürs Anzeigen des Arrays

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $string = "AutoIt rockt!"

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $3BitArray = _String_to_BitArray($string)
    _ArrayDisplay($3BitArray)
    $string = _BitArray_to_String($3BitArray)
    MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @LF & '$string' & @LF & @LF & 'Return:' & @LF & $string) ;### Debug MSGBOX

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $5BitArray = _String_to_BitArray($string, 5)
    _ArrayDisplay($5BitArray)
    $string = _BitArray_to_String($5BitArray, 5)
    MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @LF & '$string' & @LF & @LF & 'Return:' & @LF & $string) ;### Debug MSGBOX

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _String_to_BitArray($string, $bits = 3)
    If $string = "" Then Return StringSplit($string, "") ;leeres Array zurückgeben
    Local $Bitstrom = "" ;hier werden alle Bits nacheinander eingeschrieben
    For $i = 1 To StringLen($string) ;jeden einzelnen Buchstaben
    $asc = Asc(StringMid($string, $i, 1)) ;ascii-code
    For $bit = 7 To 0 Step -1 ;alle Bits je Buchstabe, rückwärts
    $Bitstrom &= 1 * (BitAND($asc, 2 ^ $bit) <> 0) ;i love it^^
    Next
    Next
    $fuellbits = Mod(StringLen($Bitstrom), $bits) ;der Bitstrom wird mit Bits aufgefüllt, damit er durch Anzahl Bits teilbar ist
    $Bitstrom &= StringLeft($Bitstrom, Mod($bits, $fuellbits)) ;einfach hinten dranhängen
    ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Bitstrom = ' & $Bitstrom & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Return StringRegExp($Bitstrom, '[01]{1,' & $bits & '}', 3) ;als 3-Bit Arrayzurückgeben
    EndFunc ;==>_String_to_BitArray

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _BitArray_to_String($array, $bits = 3)
    If Not IsArray($array) Then Return "" ;wenn array leer, leeren String zurückgeben
    Local $Bitstrom = "", $ascii = 0, $string = ""
    For $i = 0 To UBound($array) - 1 ;aus allen indizes den Bitstrom generieren
    $Bitstrom &= $array[$i]
    Next
    ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Bitstrom = ' & $Bitstrom & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    If Mod(StringLen($Bitstrom), $bits) <> 0 Then Return "Array fehlerhaft!" ;summe Bits stimmt nicht
    For $i = 1 To StringLen($Bitstrom) ;alle bits im Bitstrom
    $bit = StringMid($Bitstrom, $i, 1) = 1 ;bit 0 oder 1?
    $ascii += $bit * (2 ^ (7 - ($bit * Mod($i - 1, 8))));wenn bit gesetzt, dann aufaddieren
    If Mod($i, 8) = 0 Then ;wenn 8 bits zusammen....
    $string &= Chr($ascii) ;string mit buchstaben füllen
    $ascii = 0 ;ascii zurücksetzen
    EndIf
    Next
    Return $string
    EndFunc ;==>_BitArray_to_String

    [/autoit]
  • Ich wollte erst einmal zwei funktionierende Funktionen.
    Jetzt war ich dabei mir dies in einer Funktion umzubauen.
    Später soll dies nämlich in einem Verschlüsselungs Algorithmus eingebaut werden.

    Der "Umweg" übers Array ist wegen den zwei Funktionen entstanden.
    Du hast ja direkt eine Funktion geliefert welches das gewünschte Ergebnis liefert.

    Danke Andy :)