2013-04-24 7 views
6

Warum ist es, dass, wenn ich irb öffnen und ich laufen
puts 'A'.unpack("B8")
ich 01000001 bekommen, aber wenn ich laufe
puts 'A'.unpack("B4B4")
ich nur 0100 und nicht [0100,0001]?Unexpected auspacken Ergebnisse mit Bitfolgen

Ist die Auflösung von entpacken nur ein ganzes Byte? Nicht weniger?

+1

Die Ruby-Dokumente sind ein bisschen vage. Rubys "pack" und "unpack" sind jedoch ziemlich direkte Kopien von Perl und [Perls 'B'] (http://perldoc.perl.org/functions/pack.html) sagt" absteigende Bit-Reihenfolge "innerhalb jedes Bytes * "(Betonung meiner). –

Antwort

5

Lassen Sie uns einige Tests durchführen, um das Verhalten zu verstehen:

> 'A'.unpack('B8') 
=> ["01000001"] 

Es gibt die 8 höchstwertigen Bits (MSBs) der char 'A'

> 'A'.unpack('B4') 
=> ["0100"] 

Es gibt die 4 MSBs von char 'A'

> 'A'.unpack('B16') 
=> ["01000001"] 

Es gibt die 16 MSBs von charzurück 0, aber da es nur 8 wir die 8 MSBs

> 'AB'.unpack('B16') 
=> ["0100000101000010"] 

Es gibt die 16 MSBs der Folge von Zeichen 'AB' (das Ende 8 Bits 01000010 entspricht 'B')

> 'AB'.unpack('B10') 
=> ["0100000101"] 

Es gibt bekommen die 10 MSBs der Folge von Zeichen 'AB', dhDie 8 MSBs der 'A' und die 2 MSBs von 'B'

> 'ABC'.unpack('B*') 
=> ["010000010100001001000011"] 

Es gibt alle die MSBs der Folge von Zeichen 'ABC', (das Ende 8 Bits 01000011 entspricht 'C')

> 'AB'.unpack('B8B8') 
=> ["01000001", "01000010"] 

Es gibt die folgende Anordnung:

  • das erste Element ist der 8 MSBs der char 'A'
  • das zweite Element ist die 8 höchstwertigen Bits des char 'B'

_

> 'AB'.unpack('B8B7') 
=> ["01000001", "0100001"] 

Es gibt die folgende Anordnung:

  • das erste Element ist der 8 MSBs der char 'A'
  • das zweite Element ist die 7 MSBs der char 'B'

_

> 'AB'.unpack('B4B8') 
=> ["0100", "01000010"] 

Es gibt die folgende Anordnung:

  • das erste Element ist die 4 MSBs des char 'A'
  • das zweite Element ist die 8 höchstwertigen Bits des char 'B'

_

> 'AB'.unpack('B16B8') 
=> ["0100000101000010", ""] 

Es gibt die folgende Anordnung:

  • das erste Element ist die 16 MSBs der Folge von Zeichen 'AB'
  • das zweite Element leer ist, da die Zeichen bereits verbraucht worden

_

> 'AB'.unpack('B*B8') 
=> ["0100000101000010", ""] 

Es gibt Ihnen das gleiche Ergebnis und konsumieren die ganze Zeichenfolge.

> 'AB'.unpack('B9B8') 
=> ["010000010", ""] 

Es gibt die folgende Anordnung:

  • das erste Element ist der 9 MSBs der Folge von Zeichen 'AB'
  • das zweite Element leer ist, da die Zeichen bereits verbraucht worden sind

Als Fazit,

die Richtlinie BN über einen String wird maximal die ersten ((N-1)/8) + 1 Zeichen des Strings verbrauchen. Wenn in der Zeichenfolge noch Zeichen vorhanden sind und Sie eine zweite Anweisung BM haben, werden Sie höchstens die nächsten ((M-1)/8) + 1 Zeichen der Zeichenfolge verbrauchen. Und so weiter für alle nächsten Direktiven. Wenn Sie die Direktive B* verwenden, werden alle Zeichen konsumiert und die Reihenfolge der entsprechenden MSBs zurückgegeben.

Zum Beispiel:

'ABCDEFG'.unpack('B17B*B8') 

Es sollte liefert uns:

  • die 17 MSBs der Sequenz ABC
  • alle MSBs der Sequenz DEFG
  • eine leere bitstring

Lassen Sie uns:

> 'ABCDEFG'.unpack('B17B*B8') 
=> ["01000001010000100", "01000100010001010100011001000111", ""] 

Und in der Tat 'A'.unpack('B4B4') das Array zurückgibt ["0100", ""] als die erste Richtlinie A die Kohle verbraucht.

+0

Wow! Danke für die Beinarbeit! Ich verstehe jetzt. Ich habe erwartet, dass es sich buchstäblich nach und nach entpackt und nur die Hälfte des Charakters verbraucht, wenn das gewünscht wird. Ich habe nicht berücksichtigt, dass die Anweisung das gesamte Zeichen in der Zeichenfolge verbraucht. – Justin