Почему мой цикл Perl отключается одним в конце? - PullRequest
5 голосов
/ 23 октября 2010

У меня есть эта программа, которая не работает, как ожидалось.Помогите мне.

Я хочу напечатать заголовок строки.

Если ввод 4, я хочу вывод 1|2|3|4.

Он не работает каквсе, если я жестко кодирую значение $count, оно работает частично, но последнее число отсутствует.

sub printC {
        my $count = @_;
        # count = 4  # works partially only prints 1|2|3
        for(my $i=1;$i<$count;$i++) {
                print "$i|";
        }
        print $i;
}
$count  = 2;
&printC($count);
print "\n";

Ответы [ 4 ]

11 голосов
/ 23 октября 2010

Проблема здесь:

my $count = @_;

Назначение происходит в скалярном контексте, который присваивает количество элементов в массиве @_ для $count, что в вашем случаеравно 1, так как вы передаете 1 аргумент функции.

Чтобы исправить это, вы можете сделать:

my ($count) = @_; 

или

my $count = $_[0];

здесьДругая проблема:

for(my $i=1.....
    ^^

Используя my, вы сделали $i local для тела for, и оно не будет доступно за пределами это.Таким образом, ваш окончательный print вне for ничего не печатает.Чтобы исправить это, переместите объявление $i вне цикла:

sub printC {
        my ($count) = @_;
        my $i;
        ....

Всегда ставьте точку, чтобы писать

use strict;

в верхней части вашей программы, что позволяет вам ловитьтакие ошибки.

Способ perl делать то, что делает ваша функция:

print join('|',1..$count);
5 голосов
/ 23 октября 2010

Настоящий Perl-хакер может написать что-то вроде этого:

sub printC {
  my $count = shift;
  print join "|", (1 .. $count);
}

Как только вы поймете, как это работает, вы обнаружите, что узнали немного больше о Perl. : -)

1 голос
/ 23 октября 2010

$i не существует, как только вы вышли из цикла for из-за того, где он объявлен.

Вы можете сделать

sub printC {
    my ($count) = @_;
    my $i;
    for ($i = 1; $i < $count; $i++) {
        print "$i|";
    }
    print $i;
}

Еще проще:

sub printC {
    my ($count) = @_;
    print join("|", 1 .. $count) . "\n";
}
0 голосов
/ 24 октября 2010

Еще один бит "быть более Perlish" - это не использовать цикл C-style for.Существует почти никогда необходимость использовать стиль C * for в Perl.

Вместо

for(my $i=1;$i<$count;$i++) { ... }

использовать

for my $i (1 .. $count) { ... }

Они почти эквивалентны, за исключением того, что последняя версия более легко читаема и более устойчива к ошибкам, возникающим в результате единичных ошибок.(Причина, по которой ваш код печатал только 1|2|3 вместо 1|2|3|4, заключается в том, что тест в вашем стиле C for проверял $i<$count, когда он должен был быть $i<=$count - это очень распространенная ошибка с C-style for циклы, которые for (list) полностью избегает.)

Кроме того, не добавляйте префиксы к вашим дополнительным вызовам с &.Это пережиток Perl 4, который больше не нужен в Perl 5 и имеет побочные эффекты, о которых вы, вероятно, не знаете и, вероятно, не хотите.Просто используйте printC($count) вместо &printC($count).

Но, да, в данном конкретном случае join, вероятно, лучше, чем for в любом случае.

...