TTaJTa4
TTaJTa4

Reputation: 840

Handling with two warnings of @ARGS

Small debug question I can't solve for some reason. Consider the following code:

use warnings;
my $flag = 0;
foreach my $i (0..scalar(@ARGV)) {
    $data{$OPTION} .= $ARGV[$i]." " if($flag);
    $flag = 1 if($ARGV[$i] =~ /$OPTION/);
    undef $ARGV[$i] if($flag);
}

I get the following two warnings:

Use of uninitialized value within @ARGV in concatenation (.) or string at line 4
Use of uninitialized value in pattern match (m//) at line 5

I get the reason is that I undefine some value of @ARGV and then it tries to check it.

The way I do it like this is because I would like to 'cut' some of the data of @ARGV before using GetOpt module (which uses this array).

How to solve it?

Upvotes: 0

Views: 63

Answers (1)

Dave Cross
Dave Cross

Reputation: 69244

Let's expand on those comments a bit.

Imagine @ARGV contains four elements. They will have the indexes 0, 1, 2 and 3 (as arrays in Perl are zero-based).

And your loop looks like this:

foreach my $i (0..scalar(@ARGV)) {

You want to visit each element in @ARGV, so you use the range operator (..) to generate a list of all those indexes. But scalar @ARGV returns the number of elements in @ARGV and that's 4. So your range is 0 .. 4. And there's no value at $ARGV[4] - so you get an "undefined value" warning (as you're trying to read past the end of an array).

A better way to do this is to use $#ARGV instead of scalar @ARGV. For every array variable in Perl (say @foo) you also get a variable (called $#foo) which contains the last index number in the array. In our case, that's 3 and your range (0 .. $#ARGV) now contains the integers 0 .. 3 and you no longer try to read past the end of the array and you don't get the "undefined value" warnings.

There's one other improvement I would suggest. Inside your loop, you only ever use $i to access an element from @ARGV. It's only used in expressions like $ARGV[$i]. In this case, it's probably better to skip the middle man and to iterate across the elements in the array, not the indexes.

I mean you can write your code like this:

foreach my $arg (@ARGV) {
    $data{$OPTION} .= $arg . " " if($flag);
    $flag = 1 if($arg =~ /$OPTION/);
    undef $arg if($flag);
}

I think that's a little easier to follow.

Upvotes: 3

Related Questions