Обработка с двумя предупреждениями @ARGS - PullRequest
0 голосов
/ 14 января 2019

Небольшой вопрос отладки, который я не могу решить по какой-то причине. Рассмотрим следующий код:

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);
}

Я получаю следующие два предупреждения:

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

Я понимаю, что причина в том, что я определяю некое значение @ARGV, а затем пытается его проверить.

То, как я это делаю, заключается в том, что я хотел бы «вырезать» некоторые данные @ARGV перед использованием модуля GetOpt (который использует этот массив).

Как это решить?

1 Ответ

0 голосов
/ 15 января 2019

Давайте немного расширим эти комментарии.

Представьте себе @ARGV содержит четыре элемента. Они будут иметь индексы 0, 1, 2 и 3 (так как массивы в Perl основаны на нуле).

И ваша петля выглядит так:

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

Вы хотите посетить каждый элемент в @ARGV, поэтому вы используете оператор диапазона (..) для генерации списка всех этих индексов. Но scalar @ARGV возвращает количество элементов в @ARGV, и это 4. Таким образом, ваш диапазон равен 0 .. 4. И нет значения в $ARGV[4] - поэтому вы получаете предупреждение «неопределенное значение» (как вы пытаетесь читать за конец массива).

Лучший способ сделать это - использовать $#ARGV вместо scalar @ARGV. Для каждой переменной массива в Perl (скажем, @foo) вы также получаете переменную (называемую $#foo), которая содержит последний индексный номер в массиве. В нашем случае это 3, и ваш диапазон (0 .. $#ARGV) теперь содержит целые числа 0 .. 3, и вы больше не пытаетесь читать после конца массива и не получаете предупреждений о «неопределенном значении».

Есть еще одно улучшение, которое я бы предложил. Внутри вашего цикла вы всегда используете $i для доступа к элементу из @ARGV. Он используется только в выражениях типа $ARGV[$i]. В этом случае, вероятно, лучше пропустить посредника и перебирать элементы массива, а не индексы.

Я имею в виду, что вы можете написать свой код так:

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

Я думаю, что за этим немного легче следовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...