2

我正在使用哈希表实现 perl fib:

#!/usr/bin/perl

use strict;
use warnings;
no warnings 'recursion';

my %m_fib = (0,1,1,1);

while (my $a = <STDIN>) {
    print "--".&fib($a)."\n";
}

sub fib {
    foreach my $i (@_) {
        if (not defined $m_fib{$i}) {
            $m_fib{$i} = &fib($i - 1) + &fib($i - 2);
        }
        return $m_fib{$i};
    }
}

它适用于大于 1 的输入,但适用于 0 或 1。

哈希应该没问题,因为它返回了正确的结果,但是如果我用 0 或 1 输入它,为什么它不起作用?

4

1 回答 1

6

您的输入包含行尾 ( \n)。chomp用(文档)删除它

while (my $a = <STDIN>) {
    chomp $a;
    print "--".&fib($a)."\n";
}

编辑:问题是什么

  • 对于任何输入,defined测试将始终失败,因为number\n哈希中不存在字符串

  • Perl 能够对您的输入进行数学20\n - 1运算19

  • 现在找到0或未1找到定义的值,您的代码将分别调用fib(-1)and fib(-2)or fib(0)and fib(-1)。这将产生一个无限循环。

  • 使用 2 测试将失败,Perl将执行减法调用fib(1) + fib(0)没有\n)。在第二次通话中,您的测试将按照$m_fib(0)确实存在的方式工作。

编辑 2

带有一些评论的小评论

  • 您的函数处理多个参数,但在第一个参数后退出。你永远不会用一个以上的参数调用它(即使你这样做了,它也永远不会处理第二个参数)

  • 其他一些内联注释(您可以使用Perl::Critic查看您的代码)

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    # Not needed
    # no warnings 'recursion';
    
    my %m_fib = ( 0, 1, 1, 1 );
    
    # From Perl::Critic
    #
    # Use "<>" or "<ARGV>" or a prompting module instead of "<STDIN>" at line 10, column 17.
    #   InputOutput::ProhibitExplicitStdin (Severity: 4)
    #     Perl has a useful magic filehandle called `*ARGV' that checks the
    #     command line and if there are any arguments, opens and reads those as
    #     files. If there are no arguments, `*ARGV' behaves like `*STDIN' instead.
    #     This behavior is almost always what you want if you want to create a
    #     program that reads from `STDIN'. This is often written in one of the
    #     following two equivalent forms:
    #
    #     while (<ARGV>) {
    #       # ... do something with each input line ...
    #     }
    #     # or, equivalently:
    #     while (<>) {
    #       # ... do something with each input line ...
    #     }
    #
    #   If you want to prompt for user input, try special purpose modules like
    #   IO::Prompt.
    
    while ( my $a = <> ) {
        chomp $a;
    
        # use " just when needed
        print '--' . fib($a) . "\n";
    }
    
    sub fib {
    
        my $i = shift;
    
        if ( not defined $m_fib{$i} ) {
    
            # it is not necessary to use & for subroutine calls and
            # can be confused with the logical and
    
            $m_fib{$i} = fib( $i - 1 ) + fib( $i - 2 );
        }
        return $m_fib{$i};
    
    }
    
于 2013-10-04T05:41:38.017 回答