Re: Convert ASCII string to 7-bit binary string
by kennethk (Abbot) on Oct 27, 2015 at 19:22 UTC
|
Define better. More readable/maintainable? Faster? Algorithmically more elegant? I'm always a huge fan of "works," which your code does.
print my $out = join '', map {substr unpack('B8'), 1} split //, '4B';
substr, unpack
print my $out = join '', map {sprintf '%07b', ord} split //, '4B';
sprintf, ord
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] [d/l] [select] |
|
|
why is substr needed there?
| [reply] |
|
|
substr $var, 1 returns the string in $var minus the first character. That's what converts the 8 character binary output from unpack into the desired 7 character one. You could do the same thing with a substitution with the /r modifier, and I'm sure a number of other methods. In the OP, it's handled with s/^.//;, but then you can't chain.
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] [d/l] [select] |
Re: Convert ASCII string to 7-bit binary string
by AnomalousMonk (Archbishop) on Oct 27, 2015 at 20:34 UTC
|
c:\@Work\Perl\monks>perl -wMstrict -le
"my $out;
;;
$out .= reverse for unpack '(b7)*', '4B3A';
print qq{'$out'};
"
'0110100100001001100111000001'
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
|
$ perl -Mstrict -Mwarnings -E '
my $out;
$out .= $_ for map { unpack q{xA7}, $_ } unpack q{(B8)*}, q{4B3A};
say $out;'
0110100100001001100111000001
$
Not as succinct but possibly slightly easier to work out what is going on because it is not immediately clear that your b7 format will drop the last (most significant) bit before you reverse the bits into the correct order.
| [reply] [d/l] [select] |
|
|
c:\@Work\Perl\monks>perl -wMstrict -le
"my $out;
$out .= sprintf '%07b', $_ for unpack 'C*', '4B3A';
print qq{'$out'};
"
'0110100100001001100111000001'
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
Because the b7 unpack template that drops the most significant bit of the converted character also produces the binary digits in little-endian order. The OPer wants them in big-endian (i.e., most significant binary digit on the left) order, hence the 7-character sub-string must be reversed before being appended to the $out string. Try it without reverse and see what you get.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re: Convert ASCII string to 7-bit binary string
by ikegami (Patriarch) on Oct 28, 2015 at 21:18 UTC
|
For long input strings, the following should be faster than the previously submitted solutions:
my $out = unpack('B*', $str) =~ s/.(.{7})/$1/sgr; # 5.14+
( my $out = unpack('B*', $str) ) =~ s/.(.{7})/$1/sg; # 5.6+
| [reply] [d/l] |
Re: Convert ASCII string to 7-bit binary string
by Anonymous Monk on Oct 27, 2015 at 19:25 UTC
|
$out = unpack('B*', '4B') =~ s/.(.{7})/$1/gr;
| [reply] [d/l] |
Re: Convert ASCII string to 7-bit binary string
by AppleFritter (Vicar) on Oct 27, 2015 at 22:17 UTC
|
$string = '4B';
($out = $string) =~ s/(.)/unpack 'B8', $1/eg;
Fairly straightforward, actually - this globally (/g) matches every character ((.)), executes (/e) the embedded snippet of code, and replaces the matched character with the result of the call to unpack.
EDIT: please see below for a version that actually works properly.
| [reply] [d/l] |
|
|
Problem is, that doesn't actually work. That outputs "0011010001000010" instead of "01101001000010".
| [reply] |
|
|
Mea culpa; I should pay more attention, and not just assume that two similar-looking binary strings are, in fact, the same. Thanks for the correction.
Fortunately it's easily-fixed; just use substr in the substitution to chop off the first character:
($out = $string) =~ s/(.)/substr unpack('B8', $1), 1/eg;
| [reply] [d/l] |
|
|