2014-09-05 121 views
0

我试图运行下面索引数组

Use of uninitialized value within @words in concatenation (.) or string... 

它引用在这里我尝试创建由三数组行代码时,得到的Perl以下错误,当“未初始化值使用”单词序列(以$trigrams开头的行)。任何人都可以帮我弄清楚这个问题吗?

my %hash; 
my @words; 
my $word; 
my @trigrams; 
my $i = 0; 

while (<>) { 

    @words = split; 

    foreach $word (@words) { 
     $hash{$word}++; 

     # Now trying to create the distinct six-grams in the 10-K. 
     $trigrams[$i] = join " ", $words[$i], $words[$i + 1], $words[$i + 2]; 

     print "$words[$i]\n"; 
     $i++; 
    } 
} 
+2

始终'使用严格的;使用警告;'! – Biffen 2014-09-05 21:07:00

+0

当'$ i'是最后一个(或倒数第二个)时,看起来像'$ words'带有'$ words [$ i + 1]'和'$ words [$ i + 2]'' )指数。 – Biffen 2014-09-05 21:10:21

回答

4

所有这一切都发生的事情是,你脱落阵列@words结束。您正在为@words的每个元素执行循环,因此$i的值从0变为$#words,或者数组的最后一个元素的索引。因此,线

join " ", $words[$i], $words[$i + 1], $words[$i + 2]; 

访问阵列$words[$i]内外两个元件不存在的最后一个元素。

在这种情况下,与任何使用数组当前索引的循环一样,最简单的方法是遍历数组索引而不是内容。为使join有效,您需要从零开始并在结束前的两个元素处停止,因此0 .. $#words-2

也整洁使用数组切片选择用于卦三个要素,并使用该内插的阵列成一个字符串,如在"@array"的事实,会做一样join ' ', @array。 (更准确地说,它确实是join $", @array,并且$"默认设置为单个空间。)

我建议您进行此修复。在每个Perl程序开始时,它是至关重要的use strictuse warnings,并且您应该尽可能晚地使用my声明所有变量。

use strict; 
use warnings; 

my %hash; 

while (<>) { 

    my @words = split; 
    my @trigrams; 

    for my $i (0 .. $#words - 2) { 
     my $word = $words[$i]; 
     ++$hash{$word}; 

     $trigrams[$i] = "@words[$i,$i+1,$i+2]"; 

     print "$word\n"; 
    } 
} 

更新

您可能喜欢这一点,如果不是太简洁了,你

use strict; 
use warnings; 

my %hash; 

while (<>) { 
    my @words = split; 
    my @trigrams = map "@words[$_,$_+1,$_+2]", 0 .. $#words-2; 
} 
+0

非常感谢您的回复!当我回到办公室时,我会尝试建议的修复程序! – Rick 2014-09-05 21:36:35

+0

我更喜欢你的地图解决方案。我们最好考虑所需要的占卜数量。 – Miller 2014-09-06 01:43:50

+0

我可以确认您的解决方案适用于我。非常感谢! – Rick 2014-09-08 12:19:41