Принимая операторы в качестве переменных аргумента - PullRequest
0 голосов
/ 05 июня 2019

Привет! Я пытаюсь создать простой калькулятор, содержащий всего четыре оператора +, -, / и *, и по какой-то причине моя реализация не работает.

Я видел несколько рабочих реализаций (включая те, которыезаслуживает награды за самое запутанное) однако мне интересно узнать, почему не выполняет следующую работу?

#!/usr/bin/perl

my $num1 = $ARGV[0];
my $num2 = $ARGV[2];

my $operator = $ARGV[1];

print "$operator \n";

if($operator == '-')
{
  $num3 = $num1 - $num2;
  print "$num1 - $num2 = $num3\n";
} 
elsif($operator == "+")
{
  $num3 = $num1 + $num2;
  print "$num1 + $num2 = $num3\n";
}
elsif($operator == "/")
{
  $num3 = $num1 / $num2;
  print "$num1 / $num2 = $num3\n";
}
elsif($operator == "*")
{
  $num3 = $num1 * $num2;
  print "$num1 * $num2 = $num3\n";
}

Кроме того, команда ./expr.pl 7 * 2 возвращает следующее: 03.bellpaper.doc что просто непостижимо.

Ответы [ 3 ]

5 голосов
/ 05 июня 2019

Всегда начинайте свои файлы с

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";
}
3 голосов
/ 05 июня 2019

Однако, однако, команда ./expr.pl 7 * 2 возвращает следующее: 03.bellpaper.doc, что просто непостижимо.

* - это глобус оболочки.Ваша оболочка заменяет * именами каждого файла в текущем каталоге.Аргументами вашей программы являются 7, затем множество имен файлов, затем 2.Первое из этих имен файлов печатается вашей строкой print "$operand\n", а затем, поскольку $operand не соответствует ни одной из проверяемых вами вещей, больше ничего не происходит.

Обойти это простоставить кавычки вокруг * или вводить данные другим способом, кроме командной строки.

0 голосов
/ 05 июня 2019

Обычно, когда я делаю такие вещи, я делаю целочисленную переменную с именем choice, которая передается в методы.И в методе я бы имел операторы if и else if для интерпретации аргумента.Например: 0 = +, 1 = -, 2 = / и 3 ​​= *

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