Perl数组的hashrefs问题

时间:2013-08-26 12:28:39

标签: arrays perl hashref

我的项目中有这个:

sub get_src_info($) {
        my $package = shift;
        my ($key,$value,$tail) =("","","");
        my (@APT_INFO,$r);

        open APT, "apt-cache showsrc $package|";

        while (<APT>){
                chomp;
                ($key,$value,$tail) = split /:/;
                if (defined ($key) && defined ($value)) {
                        $value =~ s/^\s+|\s+$//;
                        if (defined($tail)) {
                                $value = "$value:$tail";
                        }
                        if ( $key eq "Package" or $key eq "Version" ) {
                                $r->{$key} = $value;
                        }
                }
                if(/^$/) { push @APT_INFO,$r++; }
        }
        close APT;
        return @APT_INFO;
}

我通常使用use strict来检查错误。 代码使用no strict "refs";指令,但没有它就无法运行,产生错误:

Can't use string ("163277181") as a HASH ref while "strict refs" in use at a.pl line 61, <APT> line 45.

第61行是:$r->{$key} = $value;

我更喜欢修复我的代码,而不是让它沉默,但却无法解决错误/如何解决这个问题。

另外,推进引用指向下一个对象的正确方法是什么?虽然它有效但我不认为$r++在这里是正确的构造。

非常感谢。

1 个答案:

答案 0 :(得分:2)

您将$r变量用作哈希引用$r->{$key}和数字$r++。引用编号为ID,因此可以将它们用作数字。但是,您不能使用非引用标量作为引用(引用不是指针)。为了说清楚:

my $reference = { foo => 1 };
my $numified  = 0 + $reference;  # is now 163277181
say $numified->{foo};  # does not work under strict "refs"
# ${"163277181"}{foo} is equivalent: This looks for global variable %163277181

您可以通过在新块开始时在$r中创建新引用来解决问题。您还应该正确调整其他变量的范围:不要使用像APT这样的全局变量,并在循环中声明<{1}}等变量

此外,$key永远不会是$keyundef不会返回split个值),您也不应该使用原型。

我想以下代码可以满足您的需求:

undef

有关参考文献与指针的更多信息:

您不能在内存安全语言中使用指针算法。 Perl是一种内存安全的语言。您可以使用的引用类似于C中的指针。它们也是键入的(虽然是动态的),但是会自动引用计数,以便在不需要时释放引用的数据结构。垃圾收集和内存安全的支持者指出较少的错误(例如,双use autodie; # automatic error handling, e.g. for `open` sub get_src_info { my ($package) = @_; my $info = {}; my @apt_info; open my $fh, "-|", "apt", "showsrc", $package; # circumvent the shell for safety while (<$fh>) { chomp; unless (length) { push @apt_info, $info; $info = {}; # put a new reference into $info next; } my ($key, $value) = split /:/, $_, 2; # limit number of fragments to 2 next unless $key eq "Package" or $key eq "Version"; s/^\s+//, s/\s+$// for $value; # this trims at *both* ends $info->{$key} = $value; } return @apt_info; } )和提高的生产率,尽管某些算法可能不会被优雅地表达。大多数现代语言默认都是内存安全的。

即使这是C,free指向一个新地址,我也要问你:你不应该$r++新记忆吗?内存分配隐含在Perl中。 malloc为我们提供了一个新的空哈希引用。如果使用词法变量(使用$r = {}),则也会自动释放。