Perl Can';t使用未定义的值作为子例程引用
作为练习,我尝试实现一个堆栈来计算后缀表达式Perl Can';t使用未定义的值作为子例程引用,perl,Perl,作为练习,我尝试实现一个堆栈来计算后缀表达式 use strict; use warnings; use Scalar::Util qw(looks_like_number); my %operators = ( '+' => \&sum, '-' => \&subs, '*' => \&mul, '/' => \&div, ); print 'Enter an expression to evalua
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];}
我怀疑$operators{$lettres[$I]}->($nb1,$nb2)代码>导致了这个问题,但我不知道为什么,因为我从Perl开始
为什么会发生这种情况,我如何解决这个问题?
首先,只考虑非空间字符的有效令牌序列。其次,如果令牌看起来不像数字,请确保%operators
哈希中有一个处理程序。我发现在处理堆栈时,它更加自然,但这并不重要
#!/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,
'/' => \÷,
);
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];}
#/usr/bin/env perl
严格使用;
使用警告;
#启用自动刷新
当地$|=1;
使用Scalar::Util qw(看起来像数字);
我的%operators=(
“+”=>\&add,
“-”=>\&subtract,
“*”=>\&乘法,
“/”=>\÷,
);
打印“输入要计算的表达式:”;
我的$input=;
my@tokens=拆分“”,$input;
我的@stack;
我的$tokens(@tokens){
如果(看起来像数字($token)){
推@stack,$token;
}
否则{
if(存在$operators{$token}){
my$op=$operators{$token};
my$x=pop@stack;
my$y=pop@stack;
推送@stack,$op->($x,$y);
}
否则{
警告“未知令牌“$token”\n;
}
}
}
打印“应答:$stack[-1]\n”;
子添加{$\[0]+$\[1];}
子乘法{$\[0]*$\[1];}
子减法{$\[0]-$\[1];}
子除法{$\[0]/$\[1];}
它的意思是$operators{$lettres[$i]}
返回了undf。@ikegami我现在明白了。这是因为我输入了8 6 2-/3+
作为输入,所以在字母
数组中得到了空格。还有更好的方法吗?就像只创建一个函数,它也将运算符作为参数?我的第一个实现是使用一个开关,但由于它不受支持,我使用了这种方法。不是在/
(所有内容)上拆分,而是在所有空白/\s+/
上拆分,这将只取非空白的元素;也就是说,你的数字和运算符split(“”)
甚至更好,因为它忽略了前导空格。是的,我更喜欢移位和取消移位,因为这就像我可视化堆栈一样。
unshift @stack, $operators{$lettres[$i]}->($nb1,$nb2);
#!/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,
'/' => \÷,
);
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];}