Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Illegal octal digit error

by lakshmananindia (Chaplain)
on Jun 06, 2009 at 05:29 UTC ( [id://768999]=perlquestion: print w/replies, xml ) Need Help??

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

I have a hash as follows

my %month_hash=( 08 => 'August' );

When I compile the program , it tells "Illegal octal digit '8'" error and I have solved this by adding single quotes like

my %month_hash=( '08' => 'August' );

Is there any other way to prevent this error, because I have more hashes like this and with this solution I need to go and change all the hashes.

--Lakshmanan G.

The great pleasure in my life is doing what people say you cannot do.


Replies are listed 'Best First'.
Re: Illegal octal digit error
by GrandFather (Saint) on Jun 06, 2009 at 07:53 UTC

    Do you want to preserve the leading 0 in the key? If so then you must quote the string because otherwise Perl will treat the digits as an octal number (as you have already found) and the key will end up as the stringised version of the number. Consider:

    use strict; use warnings; my %hash; $hash{01} = 'one'; $hash{07} = 'seven'; $hash{010} = 'eight'; $hash{10} = 'ten'; $hash{'01'} = "'one'"; $hash{'07'} = "'seven'"; $hash{'010'} = "'eight'"; $hash{'10'} = "'ten'"; print "$_ => $hash{$_}\n" for sort keys %hash;

    Prints:

    01 => 'one' 010 => 'eight' 07 => 'seven' 1 => one 10 => 'ten' 7 => seven 8 => eight

    True laziness is hard work

      This is surprising given the description of '=>' in perlop:

      The "=>" operator is a synonym for the comma, but forces any word (consisting entirely of word characters) to its left to be interpreted as a string (as of 5.001). This includes words that might otherwise be considered a constant or function call.

      And perlre defines a word character (\w) as:

      A "\w" matches a single alphanumeric character (an alphabetic character, or a decimal digit) or "_"

      Yet any collection of word characters that can be interpreted as a numeric constant is, and the result stringified. This includes octal, hex and some scientific notation (without period: e.g. 12e3).

      Am I misreading perlsyn or does it say that 07, 0666, 0x123 and 12e3 or even 08, 0abc or even 0xyz should all be forced to be interpreted as strings rather than being interpreted as numbers or compile time errors?

        Toward the end of the Comma Operator section in perlop it says:

        If the argument on the left is not a word, it is first interpreted as an expression, and then the string value of that is used.

        which is consistent with observed behaviour.


        True laziness is hard work

        The LHS of => must be a bareword for the quoting to occur. perldata defines a bareword as "a word that has no other interpretation in the grammar".

        The thing is, a bareword "will be treated as if it were a quoted string." That means => does nothing except prevent the default behaviour from being "outlawed" using use strict 'subs';.

        I don't know what the wording should be, but the docs for => need fixing. Submit a patch!

        That wording is incorrect. "=>" quotes anything on the left that looks like a valid (non-punctuation, user-definable) identifier name. And identifiers cannot start with a digit.
        $ perl -Mstrict -e 'print foo => "\n"' foo $ perl -Mstrict -e 'print foo::bar => "\n"' foo::bar $ perl -Mstrict -e 'print foo:bar => "\n"' syntax error at -e line 1, near "foo:" Execution of -e aborted due to compilation errors. $ perl -Mstrict -e 'print 0foo => "\n"' syntax error at -e line 1, near "0foo" Execution of -e aborted due to compilation errors. $ perl -Mstrict -e "print foo'bar => qq'\n'" foo::bar $ perl -Mstrict -e "print foo''bar => qq'\n'" Bad name after foo' at -e line 1. $ perl -Mstrict -e "print foo'baz'bar => qq'\n'" foo::baz::bar $
      This is a great post by Grandfather!
      There is an important part he illustrated that might get missed...notice that there are 8 hash assignment statements, but only 7 lines in printout. What happened? The $hash{10} = 'ten'; statement caused the numeric ten to be converted to string for use as a hash key. The $hash{'10'} = "'ten'"; statement generated the same key and caused 10's value to be overwritten.

      So what that means is that if you use a numeric value as a hash key, Perl will convert it to a string. There will not be any leading zeroes in that string!

      The poster looks like he wants a table to translate a number into text months. I suspect that putting '08' in quotes is unlikely to be the best thing here and that the first reply "get rid of the leading zero" is probably better because I suspect this "8" will come from a numeric routine (like a time function) and if it doesn't (like from a webpage, etc) there is any easy way to "get rid of leading zeroes".

      In Perl everything is a string until used in a numeric context. The below shows one trick that I sometimes use to "delete leading zeroes" without regex...See example 1, this just adds "0" to the string! Example 2 shows some pitfalls of comparing numeric values as strings! Example 3 show's Grandfather's 8 vs 7 keys with another example. The hash lookup needs a string and makes a string if it needs to for use in calculating the actual binary hash key.

      #EXAMPLE 1 my $a = "0001"; print "a 1 as string is:$a\n"; $a+=0; # A trick! forces numeric context!!! print "a 1 as number is:$a\n"; #EXAMPLE 2 my $b="01"; if ($a eq $b) { print "$a is eq $b\n"; } else { print "$a is NOT eq $b\n"; } if ($a == $b) { print "$a is == $b\n"; } else { print "$a is NOT == $b\n"; } #EAMPLE 3 my $string_eight="8"; my $numeric_eight = 8;
      if ($string_eight eq $b) { print "string $string_eight is eq number $numeric_eight\n"; } else { print "string $string_eight is NOT eq number $numeric_eight\n"; }
      my %hash = ('8'=>"string eight", 8 =>'number 8'); print "hash key uses the stringified version of 8: $hash{'8'} or $hash +{$numeric_eight}\n"; __END__ a 1 as string is:0001 a 1 as number is:1 1 is NOT eq 01 1 is == 01
      #string 8 is NOT eq number 8</strike>
      hash key uses the stringified version of 8: number 8 or number 8

        I had some fun with numeric keys, then explored the surprising string 8 is NOT eq number 8, not realizing until much later the cause of this result: if ($string_eight eq $b).

        After all, $string_eight and $numeric_eight are 'eq'. And, as I expected, the 'eq' operator causes stringification of the numeric value.

        use strict; use warnings; use Data::Dumper; use Devel::Peek; my %hash = ( 1e2 => '100', 100 => '100', 0x64 => '100', 0144 => '100', ); print Dumper(\%hash); my $string_eight = '8'; my $numeric_eight = 8; print "\n\$numeric_eight before use with 'eq'\n"; Dump($numeric_eight); if ($string_eight eq $numeric_eight) { print "'eq'\n"; } else { print "not 'eq'\n"; } print "\n\$numeric_eight after use with 'eq'\n"; Dump($numeric_eight); print "\n\$numeric_eight = $numeric_eight\n"; print "\n\$numeric_eight after use in a string (i.e. stringification)\ +n"; Dump($numeric_eight); if ($string_eight eq $numeric_eight) { print "not 'eq'\n"; } else { print "'eq'\n"; } print "\n\$string_eight then \$numeric_eight after all\n"; Dump($string_eight); Dump($numeric_eight); __END__ $VAR1 = { '100' => '100' }; $numeric_eight before use with 'eq' SV = IV(0x97df82c) at 0x97df830 REFCNT = 1 FLAGS = (PADMY,IOK,pIOK) IV = 8 'eq' $numeric_eight after use with 'eq' SV = PVIV(0x97e01b8) at 0x97df830 REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) <-- note POK is now set IV = 8 PV = 0x97ee168 "8"\0 <-- and there is now a PV, CUR + and LEN as well as IV CUR = 1 LEN = 4 $numeric_eight = 8 $numeric_eight after use in a string (i.e. stringification) SV = PVIV(0x97e01b8) at 0x97df830 REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 8 PV = 0x97ee168 "8"\0 CUR = 1 LEN = 4 not 'eq' $string_eight then $numeric_eight after all SV = PV(0x98339d8) at 0x98736e8 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) PV = 0x97e4ba0 "8"\0 CUR = 1 LEN = 4 SV = PVIV(0x97e01b8) at 0x97df830 REFCNT = 1 FLAGS = (PADMY,IOK,POK,pIOK,pPOK) IV = 8 PV = 0x97ee168 "8"\0 CUR = 1 LEN = 4
        perl -MData::Dumper -wle' my $r = { 010 => 123, 8 => 456 }; $r->{ 011 } = 789; print Dumper $r; ' $VAR1 = { '8' => 456, '9' => 789 };
Re: Illegal octal digit error
by CountZero (Bishop) on Jun 06, 2009 at 07:22 UTC
    In perldata we find:
    0xff # hex 0xdead_beef # more hex 0377 # octal (only numbers, begins with 0) 0b011011 # binary
    So if you want to keep the leading zero, you must quote the value: then it will be considered a string, not an octal value.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Illegal octal digit error
by afoken (Chancellor) on Jun 06, 2009 at 06:23 UTC

    Omit the leading zero.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Illegal octal digit error
by Anonymous Monk on Jun 06, 2009 at 07:25 UTC
    diagnostics, Octal
    perl -Mdiagnostics -le"print for 08 => 1" Illegal octal digit '8' at -e line 1, at end of line Execution of -e aborted due to compilation errors (#1) (F) You used an 8 or 9 in an octal number. Uncaught exception from user code: Illegal octal digit '8' at -e line 1, at end of line Execution of -e aborted due to compilation errors. at -e line 1

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://768999]
Approved by AnomalousMonk
Front-paged by ig
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2024-04-19 16:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found