不能使用未定义的值作为子例程引用

时间:2014-05-14 19:11:41

标签: perl

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

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]}->($nb1,$nb2);导致了这个问题但我不知道为什么我从Perl开始。

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

1 个答案:

答案 0 :(得分:2)

首先,仅考虑非空格字符的有效令牌序列。其次,如果令牌看起来不像数字,请确保%operators哈希中的处理程序exists。在处理堆栈时,我发现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];}