xiaoyafeng has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I received a binary string on twitter, and I translated it into words in perl:

my $string="01100110 01100101 01100101 01101100 01101001 01101110 0110 +0111 00100000 01101100"; #$string=~ s/ (\d+)/pack('B8', $1)/egx; # way 1 $string=~ s/ (\d+)/chr(oct('0b'.$1))/egx; # way 2
My question is why perl do not support
chr('0b'.$1) #it will throw a error message: Argument "0b01100110 " is +n't numeric
Thanks very much!

UPDATE:

I mean, I know I should pass a number to chr, but is there a way to convert a string to number explicitly like perl6?
+('0b'~'0111011') #perl6




I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Replies are listed 'Best First'.
Re: what is difference between chr and oct?
by bluescreen (Friar) on Jul 12, 2010 at 17:52 UTC

    As stated here Numeric Conversions perl doesn't not convert a binary number stored in a string to an integer automatically

    chr function expects a number and as said before Perl doesn't do it automatically and it fails, on the other hand oct function expects an expression and if it is an string and it starts with 0b will interpret it as binary number and will return the corresponding integer.

Re: what is difference between chr and oct?
by JavaFan (Canon) on Jul 12, 2010 at 17:28 UTC
    My question is why perl do not support chr('0b'.$1)
    Because chr takes a number as an argument. You pass it a string - a string that doesn't look like a number. The "0b" only works for numeric literals, or arguments to oct and hex. '0b' . $1 is not a literal.
    Is there a way to convert a string to number explicitly like perl6?
    eval, as in
    $string =~ s/ (\d+)/chr eval "0b$1"/egx;
      Thanks! eval is a great trick!




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

        No, it's plain stupid. oct("0b".$1) is what you want. eval with a string argument starts the huge perl parser, whereas oct uses much more efficient code that can only convert strings to numbers.

        Using a string eval is not needed most of the times, and very often, it opens a security hole. JavaFans code does not open a security hole, because it allows only digits to be passed to eval. But it is still wrong, it should allow only 0 and 1, not all digits. And it does not remove the whitespace.

        $string=~s/\s*([01]+)/chr oct "0b$1"/eg;

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: what is difference between chr and oct?
by Khen1950fx (Canon) on Jul 12, 2010 at 18:34 UTC
    You can convert a binary string to a number by using unpack. I took your string and came up with this. Note that I used "V", long little-endian. You may need to use something else, probably "N".
    #!/usr/bin/perl use strict; use warnings; use diagnostics; my $str = "01100110 01100101 01100101 01101100 01101001 01101110 01100111 00100000 01101100"; my $int = unpack( "V", $str ); my $str1 = ord($int); my $str2 = chr($str1); binmode STDOUT, ':utf8'; print $int, "\n"; print $str1, "\n"; print $str2, "\n";
Re: what is difference between chr and oct?
by toolic (Bishop) on Jul 12, 2010 at 17:20 UTC
    I am not able to answer either of your questions, but I think it is significant to point out that you received a warning message, not an error message. Furthermore, you only received the warning because you wisely had warnings in effect. Had you not, your code would have silently proceeded to do something you did not intend.

    One way to promote all warnings to errors is as follows:

    use warnings FATAL => 'all';
      Thanks for your reply. You may see above message as a warning other than error, but as matter of fact, it just because chr treat any string as number 0 if closed warning pragma. That means the output will be totally wrong:
      #wrong output: xyf@andy:~$ perl tt.pl xyf@andy:~$ # right output: xyf@andy:~$ perl tt.pl f e e l i n g lxyf@andy:~$




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction