A few things:
- Use the pragmas
use strict; and use warnings;. These will catch a lot of errors. If you use use strict;, you'll have to declare your variables with my (sometimes you'll use our, but 99% of the time, you'll use my)
- In your
for loop, you're using the default variable $_. This variable is evil for a variety of reasons. (One, it's global in scope, so something else could change this variable on your and you wouldn't know.). Declare your variables except in situations where you must use $_.
- Standard is to put the
{ on the line with the for and while. Another is to avoid the C style for loop (and to avoid foreach which is just an alias to for)
- Use spaces. It's much easier to read
$i <= $#a than $i<=$a.
Here's my interpretation of your program:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say); #A nicer 'print'
my @a = qw(12 13 14 15 16 17 18 19 20);
my @even;
my @odd;
for my $element (0..$#a) {
if ( $element % 2 ) {
push @odd, $a[$element];
}
else {
push @even, $a[$element];
}
}
say '@even = ' . join ': ', @even;
say '@odd = ' . join ': ', @odd;
The output:
@even = 12: 14: 16: 18: 20
@odd = 13: 15: 17: 19
- Note my
for loop. I use the 0..$#a to go through each element of the array. The $# is returns the last index of the array. Note that this is easier to understand than the for($i=0;$i<=$#a;$i++) that you used. It's one of the reasons why C style for loops are discouraged.
- I use the modulo operator
% to parse my even/odd. Modulo is like remainder division. If the number is odd, the modulo % 2 will be a 1. Otherwise, it's zero. Modulo operations are great for anything that works on a cycle.
But let's get back to your program. Here's your original code with a few minor tweaks.
- I added the
use strict; and use warnings;. These catch about 99% of your programming errors.
- I use
use feature qw(say); because say is nicer when it comes to debugging. I can take a statement, copy it, and then throw say qq(...); around it and see what it's doing.
- I added a bunch of
say statements to reveal the logic of your code.
Let's watch what happens. Here's your program slightly modified:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
my @b;
my @a = (1,2,3,4,5,6,7,8,9,10);
my $i;
for($i=0; $i<=$#a; $i++) {
say "Index = $i Element = $a[$i + 1]";
say qq(push(\@b, $a[$i+1]););
push(@b,$a[$i+1]);
}
print "@b";
And here's the output:
Index = 0 Element = 2
push(@b, 2);
Index = 1 Element = 3
push(@b, 3);
Index = 2 Element = 4
push(@b, 4);
Index = 3 Element = 5
push(@b, 5);
Index = 4 Element = 6
push(@b, 6);
Index = 5 Element = 7
push(@b, 7);
Index = 6 Element = 8
push(@b, 8);
Index = 7 Element = 9
push(@b, 9);
Index = 8 Element = 10
push(@b, 10);
Use of uninitialized value in concatenation (.) or string at ./test.pl line 11.
Index = 9 Element =
Use of uninitialized value within @a in concatenation (.) or string at ./test.pl line 12.
push(@b, );
Use of uninitialized value $b[9] in join or string at ./test.pl line 15.
I can see the how each push statement is being executed, and look at that, you're pushing in each and every element. Actually, you're not because you used $a[$i+1] as what you're pushing.
Using use warnings and I can see that I am trying to push the non-existant $a[10] into your @b array.
Let's change your for loop to go to every other element
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
my @b;
my @a = qw(1 2 3 4 5 6 7 8 9 10);
my $i;
for ($i=0; $i <= $#a; $i += 2) {
push @b, $a[$i];
}
The first element is $a[0]. The next element in the loop is $a[2] because I added 2 to the index instead of just incrementing it by 1. Now, I'll go through all the even elements and skip all of the odd elements.
And the output:
1 3 5 7 9
(Note that $a[0] = 1. That's why they're all odd numbers. It's why I started at 12 in my program, so $a[0] = 12 which is the even number).
My preference would be to use the while and avoid the for(...; ...; ...) construct:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
my @b;
my @a = qw(1 2 3 4 5 6 7 8 9 10);
my $i = 0;
while ( $i < $#a ) {
push @b, $a[$i];
$i += 2;
}