Perl строка, если / или оператор сравнения - PullRequest
0 голосов
/ 14 марта 2019

Почему следующий код:

# Get new_status
print STDERR "Please enter status value (active/inactive): ";
ReadMode(1);
my $new_status = ReadLine(0);
ReadMode(0);
print STDERR "\n";

if ( ($new_status ne "active") || ($new_status ne "inactive") )
{
  die "Status must be active/inactive.";
}

всегда будет возвращать «Статус должен быть активным / неактивным». независимо от того, что я печатаю? (активный, неактивный или что-то еще, или даже просто нажмите enter.)

Код представляется действительным:

  • Я четко разделяю оба утверждения скобками
  • Я использую строку оператор "ne" в обоих случаях
  • Я использую оператор ИЛИ ||

Очевидно, что в Perl-операторах есть кое-что, что я до конца не понимаю. Что я делаю не так?

Спасибо!

Ответы [ 4 ]

2 голосов
/ 15 марта 2019

Вы хотите отобразить сообщение об ошибке, только если $new_status не active И , если $new_status не inactive, поэтому

if ( $new_status ne "active" || $new_status ne "inactive" )

должно быть

if ( $new_status ne "active" && $new_status ne "inactive" )

Мы можем доказать это. Помните законы де Моргана .

  • !( A || B ) эквивалентно !A && !B.
  • !( A && B ) эквивалентно !A || !B.

Итак,

  • Допустимый ввод, если $new_status eq 'active' || $new_status eq 'inactive'
  • Неверный ввод, если !( $new_status eq 'active' || $new_status eq 'inactive' )
  • Неверный ввод, если !( $new_status eq 'active' ) && !( $new_status eq 'inactive' )
  • Неверный ввод, если $new_status ne 'active' && $new_status ne 'inactive'

Вам нужно привыкнуть видеть следующее:

if ( $new_status ne "active" && $new_status ne "inactive" ) {
   die("Status must be active/inactive.\n");
}

Но вместо этого вы можете предпочесть настойчивый стиль кодирования.

$new_status eq "active" || $new_status eq "inactive"    # Thing that should be true.
   or die("Status must be active/inactive.\n");         # Or what to do when it isn't.
2 голосов
/ 14 марта 2019
if ( ($new_status ne "active") || ($new_status ne "inactive") )
{
  die "Status must be active/inactive.";
}

Давайте проработаем логику.

  1. Я набираю что-то случайное (давайте используем random).random не является "активным" и не "неактивным", поэтому ваше предложение if становится if (true or true) - это правда.
  2. Я печатаю active.Это ложно при первой проверке и верно при второй проверке, поэтому вы получите if (false or true) - что верно.
  3. Я печатаю inactive.Это верно для первой проверки и ложно для второй, так что вы получите if (true or false) - что верно.

Вы не можете ввести ничего, что сделает ваше утверждение if ложным.

Ваша проблема в том, что вы не хотите объединять свои два предложения с or, вместо этого вы должны использовать and.

(И взять совет от этого старого программиста - используя and иor вместо && и || для управления потоком будет гораздо менее запутанным.)

Обновление: В общем, в вашем коде слишком много негативов, и выпутаешь себяВ своем ответе вы (молча!) Изменили if на unless, тем самым усложнив код для программиста по техническому обслуживанию.

Я бы написал так:

my $valid = $new_status eq 'active' || $new_status eq 'inactive';
if (not $valid) {
   die "...";
}

Или вот так:

use List::Util 'any';

if (not any { $new_status eq $_ } qw[active inactive] ) {
  die "...";
}
2 голосов
/ 14 марта 2019

$new_status не может быть равным active и inactive одновременно, поэтому условие всегда выполняется.Вам, вероятно, нужно && вместо ||

. Выберите любой вариант, который выглядит более интуитивно понятным для вас:

# option 1
if ( ($new_status ne "active") && ($new_status ne "inactive") )
...
# option 2
unless ( ($new_status eq "active") || ($new_status eq "inactive") )
...
#option 3
my %VALID_STATUS = (
    'active' => 1,
    'inactive' => 1,
);
if (!$VALID_STATUS{$new_status})
...
0 голосов
/ 14 марта 2019

Итак, я нашел ответ на свой вопрос.

Проблема с форматированием.

Я добавил:

print Dumper $new_status;

в моем коде и вывод был:

$VAR1 = 'active
';

Итак, я добавил:

chomp $new_status;

и теперь он работает отлично.

$VAR1 = 'active';

Финальный код:

# Get new_status
print STDERR "Please enter status value (active/inactive): ";
ReadMode(1);
my $new_status = ReadLine(0);
ReadMode(0);
print STDERR "\n";

chomp $new_status;

unless ( ($new_status eq "active") || ($new_status eq "inactive") )
{
  die "Status must be active/inactive.";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...