в то время как цикл не зацикливается на 1 - PullRequest
0 голосов
/ 25 мая 2019

Я пытаюсь использовать цикл while в Perl, который принимает один аргумент из командной строки, который является числом hellos для печати на строке. Я написал следующее:

# Basic settings to catch errors
use strict;
use warnings;

# Define subroutine containing the program
sub WhileNumbers {

    # read script arguments
    my $numberOfhellos = @ARGV;
    chomp($numberOfhellos);

    # Loop through the files
    my $counts = 1;
    while($counts <= $numberOfhellos) {
        # Get user input the protein of interest
        print ("Hello number $counts \n");

        $counts ++;

    }


}

# Calling the subroutine
WhileNumbers();

Когда я бегу: $ perl hellos.pl 3

Я получаю в качестве вывода:

Привет номер 1

Хотя на самом деле я бы хотел:

Привет номер 1

Привет номер 2

Привет номер 3

Любая подсказка, почему цикл while работает не так, как задумано?

Ответы [ 2 ]

3 голосов
/ 25 мая 2019

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

my $numberOfhellos = @ARGV;

Вы присваиваете массив скалярной переменной.Это дает вам количество элементов в массиве.Поскольку вы передаете в скрипт один аргумент (3), т. Е.

@ARGV = ("3")

, это устанавливает $numberOfHellos в 1.

Исправление заключается в установке $numberOfhellos первому элементу @ARGV, например:

my $numberOfhellos = $ARGV[0];

или, альтернативно,

my ($numberOfhellos) = @ARGV;

, который (из-за круглых скобок) выполняет присвоение списка, в котором хранится первый элемент@ARGV в первом элементе списка с левой стороны, т.е. он также заканчивает настройкой $numberOfhellos = $ARGV[0].

Также вам это не нужно:

chomp($numberOfhellos);

chomp используется для удаления завершающего символа новой строки из строки, возвращаемой функцией readline.Здесь нет новых строк.


Тем не менее, более идиоматический способ написать цикл подсчета в Perl - это использовать for (и диапазон) вместо while:

my $numberOfHellos = $ARGV[0];

for my $count (1 .. $numberOfHellos) {
    print "Hello number $count\n";
}
1 голос
/ 25 мая 2019

Когда вы делаете

...
my $numberOfhellos = @ARGV;
...

используется скалярный контекст, и $numberOfhellos получает количество назначенных элементов в @ARGV, которое равно 1, если вы передали один аргумент.

Явно назначьте первый элемент переменной.

...
my $numberOfhellos = $ARGV[0];
...

Там также нет необходимости в chomp() там. Вы можете перепутать @ARGV с <STDIN> или подобным. Но проверять аргументы, которые вы ожидаете, не повредит. То есть проверьте их число, и если первый из них является целым числом. Что-то вроде:

...
my $numberOfhellos;
if (scalar(@ARGV) == 1
    && $ARGV[0] =~ m/\A[0-9]+\z/) {
    $numberOfhellos = $ARGV[0];
}
else {
    die("Wrong arguments");
}
...

Обратите внимание, что scalar(@ARGV) включает скалярный контекст на @ARGV, что приводит к его количеству элементов. То есть то же самое, что произошло в вашем первоначальном задании.

...