Perl中的二维数组访问

don*_*uch 3 arrays perl scalar-context

试着学习Perl.我有一个填充了城市的阵列.我想通过引用子例程传递数组并打印每个城市输出.但是我有以下问题:

1)我可以在子例程中的while循环之前访问每个元素.但我无法访问while循环中的元素.我收到错误消息:

...
Use of uninitialized value in print at <filename> line 44, <GEN2> line 997 (#1)
Use of uninitialized value in print at <filename> line 44, <GEN2> line 998 (#1)
...
Run Code Online (Sandbox Code Playgroud)

以下是代码.我评论了什么打印和什么不打印(我试图删除我的解释不需要的代码......):

@cities;

#Assume cities is loaded successfully
&loadCities(getFileHandle('cities.txt'), $NUM_CITIES, \@cities);
&printElements(getFileHandle('names.txt'), \@cities);

sub printElements{

    my $counter = 0;
    my $arraySize = scalar $_[1];

    # Prints fine!!!
    print @{$_[1][($counter)%$arraySize];

    while ((my $line = $_[0]->getline()) && $counter < 1000){

        #Doesn't print. Generates the above error
        print @{$_[1][($counter)%$arraySize];

        $counter += 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

2)Perl语法让我非常困惑.我不明白@ {$ _ [1]} [0]发生了什么.试图解决它.

  1. $ _ [1],将此位置的值视为标量值(数组的内存地址)
  2. @ {...},将存储在此内存地址的内容解释为数组
  3. @ {...} [x],访问索引x处的元素

我是在正确的轨道上吗?

hma*_*tt1 5

我的第一个技巧是,你应该把use strict;use warnings;你的脚本的顶部.这通常揭示了很多东西.

这一行:print @{$_[1][($counter)%$arraySize];没有结束}.你也不需要括号$counter.

就像你提到的那样,获得数组长度的最佳/最清晰的方法是my $arraySize = scalar @{$_[1]};.


您可以在此处查看文档以获取参考资料.我会给你一个快速概述.

您可以正常声明一个数组

my @array = (1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

然后你可以用反斜杠引用它.

my $array_ref = \@array;
Run Code Online (Sandbox Code Playgroud)

如果要使用该引用,请使用@{...}.这就像使用常规数组一样.

print @{$array_ref};
Run Code Online (Sandbox Code Playgroud)

您也可以将其声明为使用方括号的参考.

my $array_ref = [1, 2, 3];
print @{$array_ref}; # prints 123
Run Code Online (Sandbox Code Playgroud)

在Perl中,二维数组实际上是一个数组引用数组.这是一个例子:

my @array = ( ['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'] );
print @{$array[1]}; # prints def
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试将数组引用传递给子例程.

my @array = ( ['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'] );

example(\@array); # pass in an array reference

sub example {
    my @arr = @{$_[0]}; # use the array reference to assign a new array
    print @{$arr[1]};

    print @{$_[0][1]}; # using the array reference works too!
}
Run Code Online (Sandbox Code Playgroud)

现在让我们把它放在一起打印整个二维数组.

my @array = ( ['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'] );
example(\@array);
sub example {
    my @arr = @{$_[0]};
    for my $ref (@arr) {
        print @{$ref};
    }
} # prints abcdefghi
Run Code Online (Sandbox Code Playgroud)

如果您想将它用于printElements子例程,则可以非常轻松地调整此示例.


关于在数组中打印元素的另一个注意事项.让我们从最后一个例子中取这一行:

print @{$ref};
Run Code Online (Sandbox Code Playgroud)

由于我们每次通过循环调用它,我们可能希望在它的末尾打印一个新行.

print @{$ref} . "\n";
Run Code Online (Sandbox Code Playgroud)

这打印什么?试试吧!它有用吗?

这是内置子程序连接派上用场的地方.

print join(" ", @{$ref}) . "\n";
Run Code Online (Sandbox Code Playgroud)

for循环通常是迭代数组的最佳方法.我的答案在这里谈了一些关于使用while循环执行它:https://stackoverflow.com/a/21950936/2534803 您还可以查看这个问题:迭代Perl数组的最佳方法