为什么Perl中的/ elsif只执行第一个块?

时间:2013-04-08 02:54:52

标签: perl if-statement

我是Perl的新手。我有一个编写Perl程序的任务,该程序接受来自命令行的可数字,然后生成其复数形式。我在下面编写了以下代码,它没有显示编译错误。当我从命令行执行它时: (perl plural.pl,例如),它提示我输入一个名词,然后我输入的任何名词作为输入,复数形式是相同的。它不执行剩余的if语句。

例如,如果我输入单词“cat”,则复数形成为“cats”。但是当我输入“教堂”这个词时,复数就会产生“教堂”,“飞”就像“飞翔”。

以下是代码:

#!/usr/bin/perl

$suffix1 = 's';
$suffix2 = 'es';
$suffix3 = 'ies';

print "Enter a countable noun to get plural: ";
$word = <STDIN>;
chomp($word);

if(substr $word, -1 == 'b' or 'd' or 'c' or 'g' or 'r' or 'j' or 'k' or 'l' or 'm' or 'n' or 'p' or 'q' or 'r' or 't' or 'v' or 'w' or 'e' or 'i' or 'o' or 'u') {
    $temp = $word.$suffix1;
    print "The plural form of the word \"$word\" is: $temp \n";
}
elsif (substr $word, -1 == 's' or 'sh' or 'ch' or 'x' or 'z') {
    $temp = $word.$suffix2;
    print "The plural form of the word \"$word\" is: $temp \n";
}
elsif (substr $word, -1 == 'y') {
    chop($word);
    $temp = $word.$suffix3;
    print "The plural form of the word \"$word\" is: $temp \n";
}

你能帮助我让代码执行三个语句。

5 个答案:

答案 0 :(得分:8)

首先,始终使用use strict; use warnings;

  • 使用eq而非==比较字符串。

  • 当您指的是substr $word, -1 eq 'b'时,
  • substr $word, (-1 eq 'b')表示substr($word, -1) eq 'b'。如果省略函数调用的问题,你将面临很多问题。

  • substr($word, -1) eq 'b' or 'd'表示与(substr($word, -1) eq 'b') or ('d')相同。 'd'总是如此。您需要使用substr($word, -1) eq 'b' or substr($word, -1) eq 'd'。 (最好将substr $word, -1保存在变量中以避免重复执行。)

  • substr $word, -1永远不会等于chsh

匹配运算符使这很容易:

if ($word =~ /[bdcgrjklmnpqrtvweiou]\z/) {
   ...
}
elsif ($word =~ /(?:[sxz]|[sc]h)\z/) {
   ...
}
elsif ($word =~ /y\z/) {
   ...
}

答案 1 :(得分:3)

  1. 在Perl中,我们使用eq进行字符串比较,而不是==
  2. 您不能像这样使用or。它应该像if (substr($word, -1) eq 'b' or substr ($word, -1) eq 'd')。否则,您可以使用一个数组,其中包含您要比较的所有字符串以及该数组中的grep。

答案 2 :(得分:2)

Duskast是对的。 Perl使用符号进行数字比较,使用字符串进行字符串比较。

==   eq
!=   ne
<    lt
<=   le
>    gt
>=   ge
<=>  cmp

此外,您使用or虽然是一次不错的尝试但不起作用。关键字or的优先级较弱,因此表达式

substr $word, -1 == 'b' or 'd' or 'c' or
                    'g' or 'r' or 'j' or
                    'k' or 'l' or 'm' or
                    'n' or 'p' or 'q' or
                    'r' or 't' or 'v' or
                    'w' or 'e' or 'i' or
                    'o' or 'u'

被解释为

substr ($word, (-1 == 'b')) or 'd' or 'c' or
                    'g' or 'r' or 'j' or
                    'k' or 'l' or 'm' or
                    'n' or 'p' or 'q' or
                    'r' or 't' or 'v' or
                    'w' or 'e' or 'i' or
                    'o' or 'u'

我不确定substr的作用是什么,但如果它是假的,则表达式继续到or 'b',这被解释为true。你看过正则表达了吗?

更像是惯用语
if ($word =~ /[bdcgrjklmnpqrtvweiou]$/) {...} 
# Does $word match any of those characters followed by
# the end of the line or string?

在Perl文档中查找字符串替换和s /.../.../构造。

顺便说一下,如果你是这样做的而不是学生,你就会使用Lingua模块。

答案 3 :(得分:2)

首先,始终包括use strict;use warnings;

其次,使用缩进。我在工作中教过Perl课程并且拒绝接受任何没有正确缩进的作业。事实上,我对此非常非常严格,因为我希望用户学会编写标准代码(4个空格缩进等)。它使您的程序更易于阅读和支持。

虽然我们正在努力,但要打破过长的行 - 特别是在StackOverflow上。当你必须来回滚动时,很难阅读一个程序。

快速查看您的计划:

在Perl中,字符串和数字使用两组不同的布尔运算。这是因为字符串只能包含数字,但仍然是字符串。想象一下库存项目编号,例如1384993。如果我将它们排序为字符串,则1384项首先出现。如果我在数字上对它们进行排序,993应该首先出现。除了你使用的布尔操作外,你的程序无法知道这个:

Boolean Operation   Numeric  String
=================   =======  ======
Equals              ==       eq
Not Equals          !=       ne
Greater Than        >        gt
Less Than           <        lt
Greater than/Equals >=       ge
Less than/Equals    <=       le

另一个是orand||&&仅适用于两个布尔值。这不起作用:

if ( $a > $b or $c ) {

这说的是:

if ( ( $a > $b ) or $c ) {

因此,如果$c为非零值,则$c将为 true ,整个语句将为true。你必须这样做你的陈述:

if ( $a > $b or $a > $c ) {

另一方面,在引用包含引号的字符串时使用qq(..)q()。这样,您就不必在它们前面加上反斜杠。

print "The word is \"swordfish\"\n";

print qq(The word is "swordfish"\n);

并且,如果您在程序的顶部使用use feature qw(say);,则会获得say的奖励命令,类似于print,除了假定结束的新行:

say qq(The word is "swordfish");

当您使用substr, $foo, -1时,您只会查看最后一个字符。它不能是两个字符串:

if ( substr $word, -1 eq "ch" ) {

总是假的。

很长时间难以维持。我会使用for loop(实际上不是,但让我们假装现在......):

#! /usr/bin/env perl

#
# Use these in ALL of your programs
#
use strict;
use warnings;
use feature qw(say);

#
# Use better, more descriptive names
#
my $standard_plural_suffix = 's';
my $uncommon_plural_suffix = 'es';
my $y_ending_plural_suffix = 'ies';

print "Enter a countable noun to get plural: ";
chomp (my $word = <STDIN>);

my $plural_form;

#
# Instead of a long, long "if", use a for loop for testing. Easier to maintain
#
for my $last_letter qw( b d c g r j k l m n p q r t v w e i o u) {
    if ( substr($word, -1) eq $last_letter ) {
        $plural_form = $word . $standard_plural_suffix;
        last;
    }
}
#
# Is it an "uncommon plural" test (single character)
#
if ( not $plural_form ) {
    for my $last_letter qw(s x z) {
        if ( substr($word, -1) eq $last_letter ) {
            $plural_form = $word . $uncommon_plural_suffix;
            last;
        }
    }
}
#
# Is it an "uncommon plural" test (double character)
#
if ( not $plural_form ) {
    for my $last_two_letters qw(sh ch) {
        if ( substr($word, -2) eq $last_two_letters ) {
            $plural_form = $word . $uncommon_plural_suffix;
            last;
        }
    }
}
if ( not $plural_form ) {
    if ( substr($word, -1) eq 'y' ) {
        chop ( my $chopped_word = $word );
        $plural_form = $chopped_word . $y_ending_plural_suffix;
    }
}

if ( $plural_form ) {
    say qq(The plural of "$word" is "$plural_form");
}
else {
    say qq(Could not find plural form of "$word");
}

你知道正则表达式吗?这些比使用substr要好得多,因为你可以一次测试多个东西。另外,我不会使用chop,而是使用正则表达式替换:

#! /usr/bin/env perl

#
# Use these in ALL of your programs
#
use strict;
use warnings;
use feature qw(say);

#
# Use better, more descriptive names
#
my $standard_plural_suffix = 's';
my $uncommon_plural_suffix = 'es';
my $y_ending_plural_suffix = 'ies';

print "Enter a countable noun to get plural: ";
chomp (my $word = <STDIN>);

my $plural_form;

#
# Standard plural (adding plain ol' 's'
#
if ( $word =~ /[bdcgrjklmnpqrtvweiou]$/ ) {
    $plural_form = $word . $standard_plural_suffix;
}
#
# Uncommon plural (adding es)
#
elsif ( $word =~ /([sxz]|[sc]h)$/ ) {
    $plural_form = $word . $uncommon_plural_suffix;
}
#
# Final 'y' rule: Replace y with ies
#
elsif ( $word =~ /y$/ ) {
    $plural_form = $word;
    $plural_form =~ s/y$/ies/;
}

if ( $plural_form ) {
    say qq(The plural of "$word" is "$plural_form");
}
else {
    say qq(Could not find plural form of "$word");
}

答案 4 :(得分:0)

我已经改变了你的代码。我正在使用正则表达式:

#!/usr/bin/perl

$suffix1 = 's';
$suffix2 = 'es';
$suffix3 = 'ies';

print "Enter a countable noun to get plural: ";
$word = <STDIN>;
chomp($word);

if ( $word =~ m/(s|sh|ch|x|z)$/) {
    $temp = $word . $suffix2;
}
elsif ( substr( $word, -1 ) eq 'y' ) {
    chop($word);
    $temp = $word . $suffix3;
}
else {
    $temp = $word . $suffix1;
}

print "The plural form of the word \"$word\" is: $temp \n";

另外,我建议您始终use strict;use warnings;