【问题标题】:Can't use an undefined value as a subroutine reference不能使用未定义的值作为子例程引用
【发布时间】:2014-05-15 03:43:08
【问题描述】:

作为练习,我正在尝试实现一个堆栈来计算后缀表达式。

use strict;
use warnings;

use Scalar::Util qw(looks_like_number);

my %operators = (
    '+' => \&sum,
    '-' => \&subs,
    '*' => \&mul,
    '/' => \&div,
);

print 'Enter an expression to evaluate : ';
chomp($_ = <STDIN>);
my @lettres=split(//);

my @stack;

for(my $i = 0; $i < @lettres; $i++){
    if(looks_like_number($lettres[$i])){
        unshift @stack, $lettres[$i];
    } else {
        my $nb1 = shift @stack;
        my $nb2 = shift @stack;
        unshift @stack, $operators{$lettres[$i]}->($nb1,$nb2);
    }
}

print 'Answer : ' .shift @stack;

sub sum { return $_[0] + $_[1];}
sub mul { return $_[0] * $_[1];}
sub subs { return $_[0] - $_[1];}
sub div { return $_[0] / $_[1];}

运行它时,我得到:

Can't use an undefined value as a subroutine reference at polonaise.pl line 25,
<STDIN> line 1.

第 25 行是:

unshift @stack, $operators{$lettres[$i]}->($nb1,$nb2);

我怀疑是 $operators{$lettres[$i]}-&gt;($nb1,$nb2); 导致了这个问题,但我不知道为什么,因为我从 Perl 开始。

为什么会发生这种情况,我该如何解决?

【问题讨论】:

  • 这意味着$operators{$lettres[$i]}返回了undef。
  • @ikegami 我现在看到了。这是因为我输入了8 6 2 - / 3 + 作为输入,所以我在letters 数组中得到了空格。还有没有更好的方法呢?就像只创建一个也将运算符作为参数的函数?我的第一个实现是使用开关,但由于不支持,我使用了这种方法。
  • 而不是在//(一切)上分割,而是在所有空格/\s+/上分割,这只会采用不是空格的元素;即您的号码和运营商
  • split(' ') 甚至更好,因为它忽略了前导空格。

标签: perl


【解决方案1】:

首先,只考虑非空格字符的有效标记序列。其次,如果令牌看起来不像数字,请确保 exists%operators 哈希中的处理程序。我发现pushpop 在处理堆栈时更自然,但这并不重要;

#!/usr/bin/env perl

use strict;
use warnings;

# Turn on autoflush
local $| = 1;

use Scalar::Util qw(looks_like_number);

my %operators = (
    '+' => \&add,
    '-' => \&subtract,
    '*' => \&multiply,
    '/' => \&divide,
);

print 'Enter an expression to evaluate : ';

my $input = <STDIN>;

my @tokens = split ' ', $input;

my @stack;

for my $token (@tokens) {
    if (looks_like_number($token)) {
        push @stack, $token;
    }
    else {
        if (exists $operators{$token}) {
            my $op = $operators{$token};
            my $x = pop @stack;
            my $y = pop @stack;
            push @stack, $op->($x, $y);
        }
        else {
            warn "Unknown token '$token'\n";
        }
    }
}

print "Answer: $stack[-1]\n";

sub add      { $_[0] + $_[1];}
sub multiply { $_[0] * $_[1];}
sub subtract { $_[0] - $_[1];}
sub divide   { $_[0] / $_[1];}

【讨论】:

  • 是的,我更喜欢 shift 和 unshift,因为这就像我可视化堆栈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多