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

Hello, I am using an array holding 10 elements: 2, 25, 2, 26, 2, 27, 2, 28, 2, 29 My code is:
@array = (2, 25, 2, 26, 2, 27, 2, 28, 2, 29); for ($i = 0; $i < @array; $i++) { print "Slot: $array[$i*2], port: $array[$i*2 + 1]\n" }
and I get the message: Use of uninitialized value in join or string at ./test.pl line 7. Why is this happening and how can I fix it? Isn't $i initialized with 0 inside the for loop? Thanks in advance.

Replies are listed 'Best First'.
Re: Accessing array elements
by almut (Canon) on Jun 18, 2009 at 13:40 UTC
    Isn't $i initialized with 0 inside the for loop?

    it is... but if you test $i < @array and then access elements with an index $i*2, you're accessing elements outside of those you have defined...

Re: Accessing array elements
by Corion (Patriarch) on Jun 18, 2009 at 13:35 UTC

    Consider the different values that $i will assume as the loop runs. Potentially just print out $i like:

    print "Slot[$i]: $array[$i*2], port: $array[$i*2 + 1]\n"
Re: Accessing array elements
by davorg (Chancellor) on Jun 18, 2009 at 13:59 UTC

    If you look at code written by Perl experts then you'll probably notice that they very rarely use the C-style for loop like you're using here. Most people find the shell-style foreach loop far easier to deal with.

    In this case, I think you want:

    foreach my $i (0 .. ($#array/2) - 1) { ... }
    --

    See the Copyright notice on my home node.

    Perl training courses

      But the set of people who avoid using C-style for loop are typically the ones that avoid $# as well.

      I do use the C style for loop if I want the index, because, IMO, it's easier to avoid off-by-one errors than using foreach style. The latter means you either have to use '- 1', or remember to use '$#'.

      for (my $i = 0; $i < @array; $i++) {...}
      is standard idiom which translates easily between languages. Both
      foreach my $i (0 .. @array - 1) {...}
      and
      foreach my $i (0 .. $#array) {...}
      feel artificial, and Perl specific to me. And they both have their ugliness (either -1 or $#array).
      foreach my $i (0 .. ($#array/2) - 1) { ... }
      This produces an off-by-one error. Either
          ($#array/2)
      or the uglier
          (@array/2) - 1
      works as I understand the OPer requires.
      >perl -wMstrict -le "my @ra = qw(a A b B c C d D e E); for my $i (0 .. ($#ra/2) - 1) { print qq{$ra[ $i * 2 ] : $ra[ $i * 2 + 1 ]}; } " a : A b : B c : C d : D >perl -wMstrict -le "my @ra = qw(a A b B c C d D e E); for my $i (0 .. ($#ra/2)) { print qq{$ra[ $i * 2 ] : $ra[ $i * 2 + 1 ]}; } " a : A b : B c : C d : D e : E