0

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

例如,如果我输入单词“cat”,则复数生成为“cats”。但是当我输入单词“church”时,例如,复数生成为“churches”,“fly”生成为“flys”。

这是代码:

#!/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";
}

你能帮我让代码执行这三个语句吗?

4

5 回答 5

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永远不会等于chor sh

匹配运算符使这很容易:

if ($word =~ /[bdcgrjklmnpqrtvweiou]\z/) {
   ...
}
elsif ($word =~ /(?:[sxz]|[sc]h)\z/) {
   ...
}
elsif ($word =~ /y\z/) {
   ...
}
于 2013-04-08T03:11:14.730 回答
3
  1. 在 Perl 中,我们使用eqfor 字符串比较而不是==.
  2. 你不能这样使用or。应该是这样的if (substr($word, -1) eq 'b' or substr ($word, -1) eq 'd')。否则,您可以使用包含您想要比较的所有字符串的数组,并从该数组中 grep。
于 2013-04-08T02:58:45.077 回答
2

黄昏是对的。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 模块。

于 2013-04-08T03:15:32.917 回答
2

首先,总是,总是包括use strict;and 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

另一个是or, and,||并且&&只能与两个布尔值一起使用。这不起作用:

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

这是在说什么:

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

因此,如果$c是一个非零值,那么$c将是true,并且整个语句都是正确的。你必须以这种方式做你的陈述:

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

另一件事是,在引用包含引号的字符串时使用qq(..)and 。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" ) {

永远是假的。

长的 if 很难维持。我会使用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");
}
于 2013-04-08T03:55:06.270 回答
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;

于 2013-04-08T03:13:53.990 回答