Всегда начинайте свои файлы с
use strict;
use warnings;
В вашем случае это сначала приводит к
Global symbol "$num3" requires explicit package name (did you forget to declare "my $num3"?) at script line 14.
После добавления отсутствующей my $num3
декларации мы получаем
Argument "-" isn't numeric in numeric eq (==) at script line 13.
Это происходит потому, что оператор ==
является числовым равенством. Он преобразует оба операнда в число, которое (если вы не включаете предупреждения) молча дает 0
для недопустимых строк. Вот почему ($operand == '-')
в итоге делает 0 == 0
, что, конечно, верно.
Для сравнения строк необходимо использовать eq
:
if ($operand eq '-')
См. Также Операторы связи in perldoc perlop
.
Проблема с ./expr.pl 7 * 2
заключается в том, что *
- это подстановочный знак, который ваша оболочка раскрывает в список всех файлов в текущем каталоге. Ваша программа будет вызываться как ./expr.pl 7 03.bellpaper.doc expr.pl whatever-else-is-in-the-current-directory 2
.
Чтобы предотвратить это, вам нужно процитировать его, например, с ./expr.pl 7 '*' 2
или ./expr.pl 7 "*" 2
или ./expr.pl 7 \* 2
.
Другие примечания:
$operand
неправильное имя. Это оператор. Два числа являются операндами.
- Ручные назначения из
$ARGV[...]
можно объединить в один список: my (...) = @ARGV;
- Операторы
print
в каждом блоке практически идентичны. Мы можем вытащить их как print "$num1 $operator $num2 = $num3\n"
(убедившись, что $num3
действительно установлен).
Это дает нам:
#!/usr/bin/perl
use strict;
use warnings;
my ($num1, $operator, $num2) = @ARGV;
print "$operator\n";
my $num3;
if ($operator eq '-') {
$num3 = $num1 - $num2;
} elsif ($operator eq '+') {
$num3 = $num1 + $num2;
} elsif ($operator eq '/') {
$num3 = $num1 / $num2;
} elsif ($operator eq '*') {
$num3 = $num1 * $num2;
}
if (defined $num3) {
print "$num1 $operator $num2 = $num3\n";
}