在Perl中修改数组对象后获取警告

时间:2014-01-26 10:00:02

标签: perl

我正在尝试编写一个简单的Perl模块来创建和操作一副牌。 (我知道这些模块已经存在;我正在做它作为练习。)套牌创建很好,并在首次创建后打印正常。但是,如果我洗牌,那么再次打印牌组会产生警告:

Use of uninitialized value in join or string at Deck.pm line 23.

以下是代码,第23行用注释表示:

sub new {
    my $classname = shift;
    my @suits = ("s", "h", "d", "c");
    my @pips = ("A", "K", "Q", "J", reverse 2 .. 10);
    my @deck;
    foreach my $suit (@suits) {
        foreach my $pip (@pips) {
            push (@deck, "$pip$suit"); 
        }
    }
    my $self = \@deck;
    bless($self, $classname);
    return $self;
} 

sub print_deck {
    my $self = shift;
    print join " ", @{$self};        # This is line 23
    print "\n";
}

sub shuffle {
    my $self = shift;
    my $i = @{$self};
    while ($i > 0) {
        my $j = int(rand($i));
        @{$self}[$i, $j] = @{$self}[$j, $i];
        $i--;
    }
}

1; 

我有一个测试脚本,可以创建一个新的牌组,打印它,将其洗牌,然后重新打印。第一次打印很好,但第二次打印会生成上面显示的警告。这是测试脚本:

my $deck = Deck->new;
print "The deck of cards looks like:\n";
$deck->print_deck;                # This print works fine

$deck->shuffle;
print "The shuffled deck looks like:\n";
$deck->print_deck;                # This print generates the warning

我做错了什么?谢谢!

1 个答案:

答案 0 :(得分:4)

您的shuffle方法在数组ref中引入了额外的undef值。在shuffle之后,还有一个元素:

my $before_shuffle = bless(
  [
    "As",  "Ks", "Qs", "Js",  "10s", "9s", "8s", "7s",  "6s", "5s",
    "4s",  "3s", "2s", "Ah",  "Kh",  "Qh", "Jh", "10h", "9h", "8h",
    "7h",  "6h", "5h", "4h",  "3h",  "2h", "Ad", "Kd",  "Qd", "Jd",
    "10d", "9d", "8d", "7d",  "6d",  "5d", "4d", "3d",  "2d", "Ac",
    "Kc",  "Qc", "Jc", "10c", "9c",  "8c", "7c", "6c",  "5c", "4c",
    "3c",  "2c",
  ],
  "Deck"
);
my $after_shuffle = bless(
  [
    "2d",  "6s",  "3s", "Qs",  "7s",  "7h", "7d",  "4c", "3c", "Jd",
    "Js",  "Qh",  "9s", "Kc",  "5d",  "2h", "5s",  "6h", "Ah", "8s",
    "7c",  "Qd",  "Qc", "3d",  "8c",  "Jh", "10c", "6c", "Jc", "9h",
    "9d",  "2s",  "4d", "4s",  "10d", "9c", "Kd",  "6d", "5c", "5h",
    "Ks",  "8d",  "Ad", undef, "As",  "8h", "3h",  "Kh", "2c", "4h",
    "10h", "10s", "Ac",
  ],
  "Deck"
);

它发生在您foreach shufflemy $i = @{$self}; # <-- this is the number of elements in the array while ($i > 0) { my $j = int(rand($i)); @{$self}[$i, $j] = @{$self}[$j, $i]; # <-- switch [52, rand] with [rand, 52] $i--; } 的第一次迭代中。

$i

52始终由0开始。但是您有5152的索引。因此,您随机播放的行将索引$j分配给索引52,反之亦然。但是之前未设置索引undef,因此它是$i。解决方案是将0减少一个以匹配51my $i = @{$self} - 1;

{{1}}