From: Tony Sloane Date: 2002-10-10T07:06:13+09:00 Subject: Re: Problem with pack and Hh format specifiers On Wed, 2002-10-09 at 03:10, Mike Stok wrote: > In article <1034037350.867.30.camel@awaji>, Tony Sloane wrote: > > > > I'm relatively new to Ruby so perhaps I'm missing something, but I can't > > get Array's pack to work in the following situation: > > > > irb(main):001:0> "%08b" % ["4","7"].pack ('HXh')[0] > > "00000111" > > > > I'm expecting to see "01000111". > > What are you really trying to do? I'm trying to get a numeric byte comprised of 4 in the high nibble and 7 in the low nibble. The "%08b" etc is just there so we can see what I get in an understandable format, not because I want a string. If I use H and h separately I get what I expect. irb(main):003:0> "%08b" % ["4"].pack ('H')[0] "01000000" irb(main):004:0> "%08b" % ["7"].pack ('h')[0] "00000111" It would seem that packing a low (high) nibble obliterates the high (low) nibble as a side effect, so when I back up a byte to write the second nibble I overwrite the first with zeros. Packing the nibbles in the other order seems to confirms this. irb(main):009:0> "%08b" % ["7","4"].pack ('hXH')[0] "01000000" Is this feature of pack deliberate? It would seem to make it impossible to pack nibbles. > There are some ugly ways to get ['4', '7'] into a string of 1's and 0s: > > irb(main):001:0> sprintf('%08b', Integer("0x" + ['4', '7'].join(''))) > "01000111" > irb(main):002:0> '%08b' % [["4", "7"].join("")].pack('H*')[0] > "01000111" > irb(main):003:0> ['47'].pack('H*').unpack('B*') > ["01000111"] Yes, there are a number of uglier ways to do it and I'm using one at the moment as a workaround. I just hoped that the simple pack method would work since it seems like it should be just the inverse of the unpack. > > Note that unpack seems to work the way I would expect. (ASCII code for > > 'G' is 01000111.) > > > > irb(main):002:0> "G".unpack ('HXh') > > ["4", "7"] > > Depending on your context you may want to use H* as a template and split > the resulting string e.g. > > irb(main):005:0> "G".unpack('H*') > ["47"] > irb(main):006:0> 'banana'.unpack('H*') > ["62616e616e61"] For my application the unpack ('HXh') above works fine to pick the data apart. > I hope that I'm not off on some wild tangent, and that this is of some > use. Thanks for taking the time to reply. Cheers, Tony