【问题标题】:Perl string if/or comparison operatorPerl 字符串 if/或比较运算符
【发布时间】:2019-03-14 12:38:50
【问题描述】:

为什么是下面的代码:

# 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”
  • 我使用 OR 运算符 ||

显然,我没有完全掌握 Perl 运算符。 我做错了什么?

谢谢!

【问题讨论】:

    标签: perl if-statement operators conditional-statements


    【解决方案1】:

    $new_status 不能同时等于activeinactive,所以条件总是为真。你可能需要&& 而不是||

    选择任何对您来说更直观的选项:

    # 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})
    ...
    

    【讨论】:

    • 我对这个答案投了反对票,因为你假设我不知道 AND 或 OR 之间的区别,并且我试图获得一个既活跃又不活跃的状态,但事实并非如此.
    • @Bluz 好吧,您实际上使用了|| 而不是&&...我的意思是,这没什么大不了的:几乎每个人都发生过。但是这个答案是正确的,绝对没有理由拒绝它。
    • 请不要使用unless 进行琐碎检查;必须分发隐含的否定会使太多人感到困惑。
    【解决方案2】:
    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

    (从这位老程序员那里得到一个提示 - 使用 andor 而不是 &&|| 进行流控制会更容易混淆。)

    更新: 总而言之,您的代码中有太多负面因素,您自己都感到困惑。在您的回答中,您(默默地!)将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 "...";
    }
    

    【讨论】:

    • 请不要推荐在流控制之外使用not/or/andor dieor lastor return等)。它会导致错误,例如我必须在您的答案中修复的错误。
    • @ikegami:该死。你是对的。忽略我自己的最佳实践。对此感到抱歉。
    【解决方案3】:

    如果$new_status 不是active,你只想显示错误消息AND如果$new_status 不是inactive,所以

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

    应该是

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

    我们可以证明这一点。记住De Morgan's laws

    • !( 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.
    

    【讨论】:

      【解决方案4】:

      所以我找到了问题的答案。

      问题在于格式。

      我补充说:

      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.";
      }
      

      【讨论】:

      • 你用unless替换if,这绝对不是细节。
      • 其实他们做了三个相关的改变:if→unless, ne→eq, ne→eq(格式的改变不相关。)
      猜你喜欢
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多