В вашем коде логическая ошибка.В целях демонстрации я перейду от использования STDIN
в качестве дескриптора ввода вместо его использования DATA
, чтобы я мог запекать некоторые тестовые данные.Я также исключу внешнюю подпрограмму, поскольку она не имеет отношения к обсуждению.
use strict;
use warnings;
my %profession = (
Emelie => 'Economist',
Hugo => 'Scientist',
Maria => 'Accountant',
Linnéa => 'Medical Doctor',
);
chomp(my $name = <DATA>);
my $var = 1;
while($var) {
if (exists $profession{$name}) {
print "The profession for $name is $profession{$name}\n";
$var = 0; # This could just be the 'last' keyword.
}
else {
print "No such name ($name) found. Try again.\n";
}
}
__DATA__
John
Dave
Maria
Как видно из примеров данных, можно ожидать, что программа с правильной логикой завершит работу после третьей попытки, потому чтоMaria
- это один из ваших хеш-ключей.Но если вы запустите его, вы увидите следующее:
No such name (John) found. Try again.
No such name (John) found. Try again.
No such name (John) found. Try again.
No such name (John) found. Try again.
No such name (John) found. Try again.
No such name (John) found. Try again.
No such name (John) found. Try again.
No such name (John) found. Try again.
^C
Command terminated
(строки ^C
и Command terminated
приходят с того момента, когда я наконец нажал -c, чтобы прекратить запуск.)
Atв этот момент, с дополнительной информацией о печати имени, которое было недавно прочитано из <DATA>
, довольно легко увидеть, что мы только когда-либо смотрим на John
.Но почему?Потому что ваш цикл не читает из файлового дескриптора <DATA>
.Вы делаете это вне цикла.
Вот еще один способ Perlish для выполнения того, что вы хотите сделать:
use strict;
use warnings;
my %profession = (
'Emelie' => 'Economist',
'Hugo' => 'Scientist',
'Maria' => 'Accountant',
'Linnéa' => 'Medical Doctor',
);
while(my $name = <DATA>) {
chomp $name;
if (exists $profession{$name}) {
print "The profession for $name is $profession{$name}\n";
last;
}
print "No such name ($name) found. Try again.\n";
}
__DATA__
John
Dave
Maria
Теперь вывод будет:
No such name (John) found. Try again.
No such name (Dave) found. Try again.
The profession for Maria is Accountant
При первом цикле while
мы читаем из DATA
и получаем John\n
.Мы присваиваем его $name
, chomp
, а затем проверяем, существует ли John
как хеш-ключ.Это не так, поэтому мы печатаем имя и переходим к следующей итерации.На второй итерации <DATA>
читает Dave\n
, разбивает его и проверяет, существует ли он.Это не так, поэтому мы печатаем имя и переходим к следующей итерации.
На третьей итерации мы <DATA>
получаем Maria\n
, сжимаем его и проверяем, существует ли хеш-ключ Maria
,Это так, поэтому он печатает значение, связанное с этим ключом, а затем выполняет оператор last
.last
сообщает контролю потока о немедленном выходе из замкнутого цикла.Остальные строки в главном блоке цикла пропускаются, и больше нет итераций.Она часто более разборчива, чем переменная часового типа, такая как $var
в вашем примере кода, поскольку читателю кода не нужно отслеживать, в каком состоянии может находиться переменная.
Короче говоряВаша ошибка заключалась в том, что вы только один раз читали из дескриптора входного файла, а затем ожидали, что ваш цикл столкнется с изменениями в $name
, несмотря на то, что он был назначен только один раз, до входа в цикл.Решением было переместить прочитанный файл, чтобы он стал частью цикла.
Этот шаблон задокументирован в perldoc perlvar
, и я рекомендую вам потратить несколько минут на чтение, чтобы лучше ознакомиться с языком.
Обновление: я вижу ответ, в котором повторный вызов main()
используется как средство перебора прочитанного файла, и это не так.Но в реальном сценарии main()
может увеличиться, и когда это произойдет, цикл чтения файла должен либо снова стать явным циклом, либо прерваться на другую подпрограмму, которая может вызывать себя сама.Кроме того, циклический подход while
представляет собой идиоматические или распространенные решения, которые чаще встречаются в коде, написанном другими.Использование рекурсии для чтения файла - менее распространенный шаблон.