2013-04-24 10 views
6

Dlaczego jest to, że kiedy otworzy IRB i biegnę
puts 'A'.unpack("B8")
uzyskać 01000001 ale gdy uruchamiam
puts 'A'.unpack("B4B4")
ja tylko dostać 0100 i nie [0100,0001]?Niespodziewane Rozpakuj wyniki z ciągów bitów

Czy rozdzielczość rozpakowywania jest tylko pełny bajt? Nic mniej?

+1

Dokumenty Ruby są nieco niejasne. Jednak "pakiet" i "rozpakowanie" Rubiego to całkiem proste kopie od Perla i [Perla 'B'] (http://perldoc.perl.org/functions/pack.html) mówi" malejąca kolejność bitów * wewnątrz każdego bajtu * "(podkreślenie moje). –

Odpowiedz

5

Zróbmy kilka testów aby zrozumieć zachowanie:

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

zwraca 8 najbardziej znaczących bitów (MSB) char 'A'

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

zwraca 4 MSB char 'A'

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

Zwraca 16 bitów MSB o wartości 'A', ale jak jest tylko 8 otrzymujemy 8 MSB

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

zwraca 16 MSB sekwencji znaków 'AB' (koniec 8 bitów 01000010 odpowiada 'B')

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

Zwraca 10 MSB sekwencji sekwencji 'AB', tjW 8 MSB 'A' i 2 MSB 'B'

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

Zwraca wszystkie MSB sekwencji znaków 'ABC', (koniec 8 bitów 01000011 odpowiada 'C')

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

zwraca on poniższa tablica:

  • pierwszy element jest 8 MSB karbonizatu 'A'
  • drugi element jest 8 MSB karbonizatu 'B'

_

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

ta zwraca następującą macierz:

  • pierwszym elementem jest 8 MSB karbonizatu 'A'
  • Drugi element to 7 MSB z char znaków 'B'

_

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

ta zwraca następującą macierz:

  • pierwszy element jest 4-MSB karbonizatu 'A'
  • drugi element jest 8 MSB karbonizatu 'B'

_

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

ta zwraca następującą macierz:

  • pierwszym elementem jest 16 MSB sekwencji znaków 'AB'
  • drugi element jest pusty, gdy znaki są już zużyte

_

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

Daje to ten sam rezultat i zużywa cały ciąg.

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

ta zwraca następującą macierz:

  • pierwszym elementem jest 9 MSB sekwencji znaków 'AB'
  • drugi element jest pusty, gdy znaki są już zużyte

Podsumowując,

dyrektywa BN przez ciąg będzie zużywał co najwyżej pierwsze znaki ((N-1)/8) + 1 ciągu znaków. Jeśli nadal występują znaki w łańcuchu i masz drugą dyrektywę BM, zużyjesz co najwyżej następne znaki ciągu znaków. I tak dalej dla wszystkich następnych dyrektyw. Jeśli użyjesz dyrektywy B*, pochłonie ona wszystkie znaki i zwróci sekwencję odpowiadających im MSB.

Na przykład:

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

Powinna ona wraca do nas:

  • z 17 MSB sekwencji ABC
  • wszystkie MSB sekwencji DEFG
  • pusty łańcuch bitów
check

Miejmy:

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

I rzeczywiście 'A'.unpack('B4B4') zwraca tablicę ["0100", ""] jako pierwsza dyrektywa zużywa char A.

+0

Wow! Dzięki za pracę z nóg! Teraz rozumiem. Spodziewałem się, że rozpakuje się dosłownie krok po kroku, a na życzenie tylko połowę postaci. Nie uważałem, że dyrektywa pochłania cały znak w ciągu znaków. – Justin