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

I have meet a strange question.When I run ,always shows one line of

Use of uninitialized value within @parr in concatenation (.).

my code as follow

@PC1=(58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17,9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7); my @parr=('0','M','0','A','0','I','0','L'); for my $i(0..63){ my $tmp2 = ($PC1[$i])%8; my $tmp1 = ($PC1[$i]-$tmp2)/8; printf $parr[$tmp1]."\n"; }

where 's fault of my code?

Replies are listed 'Best First'.
Re: Use of uninitialized value within
by Corion (Patriarch) on Feb 03, 2015 at 08:21 UTC

    Have you looked at the values of $tmp1? Most likely, $tmp1 gets a value larger than the number of elements of @parr, and that's why you get the warning.

    Update:

    I found the following line instructive:

    printf "%d: %d -> %s\n", $i, $tmp1, $parr[$tmp1];
      Thanks guy,I have found the mistake.My array index is out of range.
Re: Use of uninitialized value within
by pme (Monsignor) on Feb 03, 2015 at 09:22 UTC
    In case of errors/warnings you can use splain to get explanation:
    $ perl yourprogram.pl 2>&1 >/dev/null | splain
Re: Use of uninitialized value within
by BillKSmith (Monsignor) on Feb 03, 2015 at 14:47 UTC

    I am unable to duplicate your problem with my perl v5.16.3. I can suggest several improvements to your code.

    Always use strict and warnings.

    Use of printf with only a format is confusing. Use print

    Your math is unnecessarily complicated.

    use strict; use warnings; use POSIX qw(floor); my @PC1=(58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17,9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7); my @parr=('0','M','0','A','0','I','0','L'); print $parr[floor( $PC1[$_]/8 )], "\n" for (0..63);

    My use of 'floor' is not strictly necessary in this case, but is recommended for the reason explained in int.

      I am unable to duplicate your problem with my perl v5.16.3.

      I can duplicate the problem with both Strawberry 5.14.4.1 and ActiveState 5.8.9, both under Win32.

      c:\@Work\Perl>perl -wMstrict -le "use POSIX qw(floor); ;; print 'perl version ', $]; ;; my @PC1=(58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17, 9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7); ;; my @parr=('0','M','0','A','0','I','0','L'); printf $parr[floor( $PC1[$_]/8 )] for (0..63); " perl version 5.014004 Use of uninitialized value in printf at -e line 1. L0I0A0M0L0I0A0M0L0I0A0M0L0I0A0ML0I0A0M0L0I0A0M0L0I0A0M0L0I0A0M0
      As in the OPed code, the problem arises from the element of 64 in the  @PC1 array producing an index of 8 into the  @parr array, the highest valid index of which is 7.


      Give a man a fish:  <%-(-(-(-<

      Your math is unnecessarily complicated.

      One could further simplify the math by taking advantage of the fact that the  [ ] subscript operator does its own 'floor' operation by just throwing away the fractional part of the (inherently) double number:

      c:\@Work\Perl>perl -wMstrict -le "use POSIX qw(floor); ;; print 'perl version ', $]; ;; my @PC1=(58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17, 9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7); ;; my @parr = qw(0 M 0 A 0 I 0 L); printf $parr[floor( $PC1[$_]/8 )] for (0..63); print ''; printf $parr[ $_ / 8 ] for @PC1; " perl version 5.014004 Use of uninitialized value in printf at -e line 1. L0I0A0M0L0I0A0M0L0I0A0M0L0I0A0ML0I0A0M0L0I0A0M0L0I0A0M0L0I0A0M0 Use of uninitialized value in printf at -e line 1. L0I0A0M0L0I0A0M0L0I0A0M0L0I0A0ML0I0A0M0L0I0A0M0L0I0A0M0L0I0A0M0
      (Of course, this doesn't address the root problem of generating an index that's out of range!)


      Give a man a fish:  <%-(-(-(-<

      You don't see the warning because you didn't run the script with warnings turned on. Most likely the OP used -w on the command line to achieve that.

      Running the updated version of the script that you provided does show the warning. I guess you posted the code without running it?

      Perl is the programming world's equivalent of English
      Sorry guys, I missed the message when it scrolled off the screen.
      Bill
Re: Use of uninitialized value within
by Kita (Initiate) on Feb 03, 2015 at 13:54 UTC
    printf $parr[$tmp1]." - $i= @{ [ @PC1[$i] ] } tmp1=$tmp1\n";
    Try to print tmp1, with value 64, you havnt nothing for index 8 in array @parr ...
      Kita, when providing solutions, please wrap code in <code> tags to keep things properly formatted. Note how your square brackets got mangled into links. I presume you originally intended to write:
      printf $parr[$tmp1]." - $i= @{ [ @PC1[$i] ] } tmp1=$tmp1\n";
      As a side note, you probably shouldn't use printf if print will do (there's no templating in your string), it seems odd that you are both concatenating and interpolating, and why use the baby carriage operator and a slice when a value would be equivalent; why not just
      print "$parr[$tmp1] - $i= $PC1[$i] tmp1=$tmp1\n";

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

        I m familiar with java a. And I have learn perl for a short time.So thank for your suggettion very much.
Re: Use of uninitialized value within
by Corion (Patriarch) on Feb 03, 2015 at 08:20 UTC

    Have you looked at the values of $tmp1? Most likely, $tmp1 gets a value larger than the number of elements of @parr, and that's why you get the warning.